반복주기 2 - 회원가입, 목록 확인 작성하기

본 포스팅은 박재성 NEXT 교수님의 Spring-Boot, JPA로 질문/답변 게시판 구현 과정을 공부한 내용입니다.
전체 개발 과정은 Mac OS에서 진행됐습니다.


  • Docker 설정도 다 했고 이제 스프링만 잘 쓰면된다.
  • 이번 수업에서는 회원 가입을 진행하고 회원의 목록을 보는 화면과 컨트롤러를 구현했다.
  • 회원 목록을 볼 때, 회원 데이터는 항상 바뀌기 때문에 가입 화면처럼 static에서 구현하면 안된다. templates 디렉토리에서 만들어야하며(list.html) 컨트롤러에서 호출해 줘야 한다.
  • 또한 넘겨받은 회원 데이터를 mustache 템플릿 엔진을 이용해서 표시해보자.

2-1 : 컨트롤러 추가, mustache에 인자 전달

바로 기능 구현을 하기 전에 controller와 mustache를 공부해보자.
Controller는 MVC 모델에서 client의 이벤트를 받는 역할을 한다.
여기서는 HTTP GET 또는 POST가 이벤트가 될 것이다.
내가 작성한 Contrller class가 Controller인지 명시해주는 annotation을 추가한다.
@Controller
public class UserController {
    ...
}

유저가 요청했을 때 url과 method(GET 또는 POST)를 이용해 이를 처리하는 메소드를 만들자.

@Controller
public class UserController {
	@GetMapping("/welcome")
	public String helloworld() {
		return "welcome";
	}
}
@GetMapping을 이용하면 GET 방식이고 어떤 url로 요청했는지 매핑하는지 설정할 수 있다.
위 예제는 localhost:8080/welcome 으로 접속하면 templates/welcome.html을 반환한다.
이제 mustache를 써보자. 그러려면 요청을 받을 때 데이터를 받아야 한다.
GetMapping으로 했으니 GET 방식으로 요청을 받아보자.


localhost:8080/welcome?name=inkiHwang


위 url로 접속하면 UserController의 helloworld 메소드로 들어가지는데 
name:inkiHwang 이란 데이터를 GET 방식을 이용해 추가로 전달해준다.
이를 helloworld 메소드의 인자로 전달받을 수 있다.
@Controller
public class UserController {
	
	@GetMapping("/welcome")
	public String helloworld(String name) {
		System.out.println("name : " + name);
		return "welcome";
	}
}
2개의 데이터를 전달하고 싶으면? 인자를 추가해주기만 하면 된다.


localhost:8080/welcome?name=inkiHwang&age=27


@Controller
public class UserController {
	
	@GetMapping("/welcome")
	public String helloworld(String name, int age) {
		System.out.println("name : " + name + " age : " + age);
		return "welcome";
	}
}
String이 아닌 int형으로 인자를 전달받을 수 있다.
하지만 int 데이터에 'aa'와 같은 데이터를 넘겨주면 Exception이 발생하니 주의하자!
client에서 controller로 인자를 넘겨주는 방법을 공부했다.
그러면 이제 controller에서 view로 데이터를 넘겨줘서 view에서 이걸 표시해주면 되겠네?
view로 넘겨줄 때는 Model이라고 하는 class를 이용한다.
@Controller
public class UserController {
	
	@GetMapping("/welcome")
	public String helloworld(String name, int age, Model model) {
		System.out.println("name : " + name + " age : " + age);
		model.addAttribute("name", name);
		model.addAttribute("age", age);
		return "welcome";
	}
}
"name" key에 name value를 입력해 전달한다.
이걸 view인 welcome.html에서 어떻게 표시할까? mustache를 이용한다.


가 mustache 용법이다. 자세한건 아래 링크를 통해 공부하면 되는데 나중에 정리해서 포스팅해야지
은 name을 key로 하는 value를 가져온다.

https://mustache.github.io/mustache.5.html

2-1 정리
브라우저에서 localhost:8080/welcome?name=inkiHwang&age=27을 전달하면
controller가 name과 age를 전달받아 model에 이를 그대로 전달한다.
view는 mustache를 이용해 model에서 전달받은 name과 age를 표시한다.
그런데 만약 localhost:8080/welcome?name=inkiHwang 입력 받으면 에러가 난다.
age가 없어 controller에 인자가 전달되지 않았기 때문이다.
예외 처리 해볼려그랬는데 안되네 ㅎㅎ.. 다음에 배우겠지

2-2 : 회원가입 기능 구현, 회원가입 데이터를 입력 받아 출력

회원 가입 데이터를 받아서 출력한다. 참고로 회원 가입 데이터는 form.html에서 구현했다.
id, password, name, email을 입력받아보자.


회원 가입 데이터를 GET 방식으로 보내보자. 그러려면 데이터를 입력 받는 input 태그에
name을 추가해 주어야 한다. 또한 form 태그에 action을 추가해 submit 버튼을 누르면
어느 url로 요청을 보내는지 설정해야한다.


form.html에 가입 양식을 입력하고 submit 버튼을 클릭해보자.


http://localhost:8080/create?userId=fisache&password=1234&name=inkiHwang&email=hwang031451%40gmail.com


action 태그에서 create로 지정해줬으니 url은 create가 되고,
각 input 태그마다 name으로 설정해준 값이 키가 되어 전달된다.
form 태그에서 method 입력을 따로 해주지 않으면 GET 방식으로 전달된다.
아직 create를 처리하는 controller를 추가해주지 않았으니 에러가 난다.
이제 controller에 추가해보자.
@GetMapping("/create")
public String create(String userId, String password, String name, String email) {
	System.out.println("name : " + name);
	return "create";
}
다 출력해주니 귀찮으니 name만 출력해봐서 데이터가 제대로 들어오나 확인해보자.
return 값인 "create"와 매칭되는 templates/create.html 을 꼭 만들어 주어야 에러가 안난다!
해놓긴 했지만 restful 방식을 따른다면 create는 post와 매칭되야 한다.
그래서 form.html form 태그에 method를 추가하고
controller에서 GetMapping annotation을 바꿔주자.
<form action="/create" method="post">
@PostMapping("/create")
public String create(String userId, String password, String name, String email) {
	System.out.println("name : " + name);
	return "create";
}
이렇게 하면 url에 유저정보가 나오지 않는다. 물론 개발자도구로 까보면 나온다.
다음으로는 controller에서 받는 인자를 처리해보자. 인자가 너무 많다. 이걸 하나의 클래스로 만들어서 받아보자.
User class를 만들어 유저 정보를 필드로 하고 이 필드의 setter 메소드를 만들자.
요청이 들어오면 User class로 반환해 주도록 하는 방법인데 인자 이름은 setter 메소드와 매칭되니 주의!
String userId -> User :: setUserId(...) 방식으로 매핑된다.
User.java
package io.fisache.web;

public class User {
	private String userId;
	private String password;
	private String name;
	private String email;
	
	public void setUserId(String userId) {
		this.userId = userId;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	@Override
	public String toString() {
		return "User [userId=" + userId + ", password=" + password + ", name=" + name + ", email=" + email + "]";
	}
}


UserController.java
@PostMapping("/create")
public String create(User user) {
    System.out.println("user : " + user);
    return "create";
}
User를 프린트 할거기 때문에 toString까지 오버라이딩 해줬다.
이렇게 User객체로 인자를 받게되면 인자 중 하나가 없더라도 에러가 나지 않는다. 개이득
2-2 정리
회원 가입 기능을 구현하자.
가입 기능은 post를 이용하자.
요청받는 인자가 너무 많기 때문에 User 객체를 만들어 사용하자. Setter주의!

2-3 : 회원 목록

회원가입된 사용자 목록을 조회하자.
사용자가 가입하면 사용자를 저장해야한다. DB를 써야하지만 일단 java collection을 이용하자.
redirect를 통해 사용자가 가입하면 목록을 보여주는 화면으로 redirect 시켜보자.


List를 이용해 사용자를 저장해보자.
@Controller
public class UserController {	
	
	List<User> users = new ArrayList<User>();
	
	@PostMapping("/create")
	public String create(User user) {
		System.out.println("user : " + user);
		users.add(user);
		return "create";
	}
}
회원 정보를 보여주는 list 화면을 보여주는 메소드를 추가해보자.
@GetMapping("/list")
public String list() {
	return "list";
}
list에 Model을 추가해서 view에 데이터를 전달해줄 수 있도록 해보자.
전달해주는 데이터는 사용자 목록, 즉 users가 된다.
@GetMapping("/list")
public String list(Model model) {
	model.addAttribute("users", users);
	System.out.println("users : " + users);
	return "list";
}
사용자가 가입하면 list를 보여줘야 한다. 이를 위해 return "list"를 하면 문제가 된다.
왜냐하면 저런 리턴은 model에 users를 추가하지 않고 바로 list.html를 호출하기 때문이다.
따라서 redirect를 통해 list를 새롭게 요청해야한다.
@PostMapping("/create")
public String create(User user) {
	System.out.println("user : " + user);
	users.add(user);
	return "redirect:/list";
}
user : User [userId=fisache, password=1234, name=inkiHwang, email=hwang031451@gmail.com]
users : [User [userId=fisache, password=1234, name=inkiHwang, email=hwang031451@gmail.com]]
form.html에서 유저 데이터를 입력하고 submit 했을 때 나오는 프린트다.
create 메소드에서 user가 users list에 추가되고 redirect를 통해 list 요청을 새로 보낸다.
list 메소드에서 list 요청을 받아 list.html에 users list를 전달한다.
이제 list.html에서 받은 데이터를 mustache를 이용해 표시해보자.



   구문을 살펴보자.
mustache의 for문에 해당한다. users를 key가지는 model은 list이기 때문에 이렇게 한다.
즉, users list를 수행하면서 name을 출력한다라는 의미가 된다.

_config.yml

2-3 정리
사용자가 가입하면 list 화면을 보여줄건데 redirect를 이용해 /list로 새로 요청해야한다.
그래야 model에 users를 넣어서 전달해준다.
mustache에서 for문 쓰는 법을 배웠다.

2-4 서버에 배포

서버 배포는 단순 git pull 사용 방법이기 때문에 생략한다.
```java 쓰기 매우 귀찮고 짜증남. 로컬이랑 배포랑 다르게 나와서 다음부턴 gist만 써야겠다.
gist 짱짱맨
Written on October 4, 2016