[Spring Boot] 회원 관리 예제 - 웹 MVC 개발(홈 화면, 등록, 조회 기능)

GyeongEun Kim·2021년 6월 14일
0

Spring Boot

목록 보기
12/12
post-thumbnail
post-custom-banner

본 게시물은 인프런 김영한 강사님의 '스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술' 강의를 듣고 개인 공부용으로 작성되었음을 알립니다.


이전 게시글에서 스프링 빈들의 의존관계를 설정하고, MemberController의 뼈대까지 만들어보았다. 이 게시글에서는 홈화면, 회원 등록과 조회를 웹 MVC로 구현해 볼 것이다.

홈 화면

먼저 HomeController를 만들자. @Controller 애노테이션을 달아주고, @GetMapping을 통해 주소와 매핑시켜준다. 그리고 home이라는 이름의 template을 리턴한다.


@Controller
public class HomeController {
    @GetMapping("/")
    public String home() {
        return "home";
    }
}

HomeController가 home.html을 리턴하므로 view도 작성해주자. 주목할 것은 두가지의 a태그가 있는데, 하나는 회원가입 페이지로 이동하는 것이고 하나는 회원목록을 조회하는 페이지로 이동하는 하이퍼링크이다. 회원 가입 페이지는 /members/new 이고 회원 목록 조회 페이지는 /members이다

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
  <div>
    <h1>Hello Spring</h1>
    <p>회원 기능</p>
    <p>
      <a href="/members/new">회원 가입</a>
      <a href="/members">회원 목록</a>
    </p>
  </div>
</div> <!-- /container -->
</body>
</html>

서버를 실행하고 localhost:8080에 접속해보면

이렇게 잘 작동한다

#참고 : index.html(welcome page)보다 HomeController가 우선순위가 높기 때문에 HomeController가 먼저 작동한다.

회원 가입

두번째로 회원 가입을 구현해 볼 것이다. 우선 회원가입 페이지를 띄워야 하니 MemberController@GetMapping을 통해 주소와 매핑시켜주자. 그리고 templates/members/createMemberForm을 띄워주자.

@GetMapping("/members/new")
    public String createForm() {
        return "members/createMemberForm";
    }

createMemberForm.html을 작성하자.
form태그로 이름을 입력받으면 된다. /members/new로 데이터를 보낼것이기 때문에action="/members/new이고, 입력을 받아오기 때문에 method="post"이다.

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
  <form action="/members/new" method="post">
    <div class="form-group">
      <label for="name">이름</label>
      <input type="text" id="name" name="name" placeholder="이름을
입력하세요">
    </div>
    <button type="submit">등록</button>
  </form>
</div> <!-- /container -->
</body>
</html>

서버를 실행해보면

이런식으로 나타난다. 그런데 지금 이름을 적고 등록을 누르면 에러가 난다. 이름을 받아와 등록버튼을 누르면 어떻게 할지에 대한 Controller를 작성해주지 않았기 때문이다.

form태그에서 이름을 받아 저장할 MemberForm 클래스를 작성하자.(MemberContoroller에서만 사용할 것이기 때문에 Controller패키지 안에 작성한다) name이라는 private변수를 선언하고, 게터와 세터를 작성한다.

public class MemberForm {
    private String name;
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

그리고 MemberController에 다음과 같이 작성한다.

@PostMapping("members/new")
    public String create(MemberForm form) {
        Member member = new Member();
        member.setName(form.getName());

        memberService.join(member);

        return "redirect:/";
    }

이번에는 @GetMapping이 아니라 @PostMapping이다. 폼태그에서 name을 받아오기 때문이다. 폼태그에서 받아온 name을 저장한 객체인 MemberForm을 매개변수로 받아오고, 새 멤버 인스턴스를 생성한다. 그리고 새 멤버 인스턴스의 setNameform.getName()을 통해 이름을 저장한다.

그런데 나는 여기서 이런 의문이 생겼다

Q. form.setName으로 폼태그에서 받은 name을 설정해주지 않았는데 form.getName() 실행이 가능한건가?

A. 스프링 컨트롤러에서 해당 컨트롤러 메서드가 호출되기 직전에 form.setName()이 자동으로 실행되어 폼태그로 받은 name을 저장해준다. (스프링 MVC의 기능! 자바빈 프로퍼티 규약)

마지막으로 memberService.join(member);에서 새 멤버의 정보가 회원 리스트로 등록되게 한다. 리턴값인 redirect:/는 홈 화면으로 이동하게 한다.

회원 목록 조회

MemberController에 메소드를 작성한다.

@GetMapping("/members")
    public String list (Model model) {
        List<Member> members = memberService.findMembers();
        model.addAttribute("members",members);
        return "members/memberList";
    }

Model 객체는 Controller 에서 생성된 데이터를 담아서 View 로 전달할 때 사용하는 객체이다. addAttribute("키", "값") 메소드를 사용하여 전달할 데이터 세팅한다.
출처: https://lopicit.tistory.com/224 [로픽의 IT블로그]
개발자가 직접 model을 생성할 필요 없이 파라미터로 선언만 해주면 스프링이 알아서 만들어준다.
출처: https://hoyhouse.tistory.com/19 [hoyhouse]


그럼이제 templates/members/memberList 를 작성하자.

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
  <div>
    <table>
      <thead>
      <tr>
        <th>#</th> //table heading
        <th>이름</th>
      </tr>
      </thead>
      <tbody>
      <tr th:each="member : ${members}">
        <td th:text="${member.id}"></td>
        <td th:text="${member.name}"></td>
      </tr>
      </tbody>
    </table>
  </div>
</div> <!-- /container -->
</body>
</html>

여기서 주목해야할 부분은

<tr th:each="member : ${members}">
        <td th:text="${member.id}"></td>
        <td th:text="${member.name}"></td>
      </tr>

이다.

  • ${}는 model안에 있는 값을 꺼낸다는 뜻이다.
  • th:eachthymeleaf문법으로, for each문과 같은 기능 (members에서 하나씩 꺼내 member에 담음)
  • th:text는 출력 기능
  • member.idmember.name을 호출하면 자동으로 member.getXx메소드가 호출되어 값을 가져온다 (자바 프로퍼티 방식의 접근)
profile
내가 보려고 쓰는 글
post-custom-banner

0개의 댓글