본문 바로가기

Spring/스프링 입문

04. 회원 관리 페이지 만들기 - 홈 화면, 회원 가입, 회원 조회 개발하기

💡 본 게시글은 김영한님의 인프런(Inflearn) 강의 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술에 대해 공부하고, 정리한 내용입니다.

1) 홈 화면 추가하기

(1) Controller를 통해 html 연결하기

이전에는 MemberController를 만들고, 컴포넌트 스캔 혹은 @Bean을 통해 의존 관계를 설정했습니다.

 

이번에는 홈 화면을 추가하는 방법에 대해 설명하겠습니다. 먼저, controller 패키지에서 HomeController 클래스를 생성합니다.

@Controller
public class HomeController {

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

 

이 클래스에는 @Controller 어노테이션이 붙어있습니다. 그리고 @GetMapping을 통해 "/"를 연결시킵니다. 여기서 "/"는 도메인의 첫번째 주소를 의미합니다. 즉, "localhost:8080/"에 접속하면 위의 home 메서드가 호출되는 것입니다.

 

메서드는 "home"이라는 문자열을 반환하며, 이는 templates 패키지에서 home.html 파일을 찾아가는 것을 의미합니다.

 

따라서 이 설정을 통해 "localhost:8080/" 주소로 접속했을 때 home.html 페이지로 연결되도록 설정을 완료한 것입니다.


(2) Controller를 통해 출력할 home.html 작성하기

이제 home.html 파일을 작성해보겠습니다.

<!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>

 

우리의 목표는 Spring을 배우는 것이므로 html 코드는 복사해 사용하도록 합니다. 이렇게 작성한 후 코드를 실행하고 "localhost:8080/"로 접속하면 위와 같은 화면이 출력될 것입니다.

 

하지만 현재는 버튼을 눌러도 페이지 에러가 발생하며, 페이지가 제대로 출력되지 않습니다. 이는 아직 페이지 연결을 설정하지 않았기 때문입니다.

 

다음에는 "회원 가입"과 "회원 목록" 버튼을 눌렀을 때 원하는 페이지가 출력되도록 설정해보겠습니다.


2) 회원 등록 개발하기

(1) MemberController를 통해 html 출력하기

이번에는 "회원 가입" 버튼을 누르면 회원 가입 폼이 나오고, 아이디를 입력하면 회원 가입이 이루어지는 과정을 설정해보겠습니다.

 

먼저, home.html에서 "회원 가입" 버튼을 눌렀을 때 "/members/new"로 연결되도록 설정했습니다. MemberController에서 @GetMapping을 통해 해당 URL을 연결하는 createForm 메서드를 만들어봅시다. 이 메서드는 별다른 기능 없이 createMemberForm.html로 연결만 합니다.

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

 

 여기서 주의할 점은 반환값이 "members/createMemberForm"인 것입니다. 기본적으로 반환된 문자열 이름의 html 파일을 template 패키지에서 찾는데, 이처럼 작성하면 경로로 인식합니다. 즉, templates - members 패키지에 있는 createMemberForm.html을 찾게 됩니다.

 

이제 createMemberForm.html을 생성해보겠습니다.

<!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>

 

이 페이지에서는 '회원 가입' 시 필요한 정보를 입력하고, "등록" 버튼을 눌러 회원 가입을 진행합니다.

 

여기서 주목할 부분은 <form action="/members/new" method="post">와 <input type="text" id="name" name="name" placeholder="이름을 입력하세요">입니다. 전자는 "/members/new"를 POST 방식으로 전달한다는 것을 의미하고, 후자는 key는 "name"이고 value는 입력받은 문자열을 받는다는 뜻입니다.

 

하지만 아직 "/members/new"를 POST 방식으로 받는 메서드를 작성하지 않았기 때문에, "등록"을 눌러도 페이지 에러가 발생합니다. 이 부분은 다음에 해결하도록 하겠습니다.


(2) MemberForm 클래스 생성하기

createMemberForm.html에서는 key가 "name", value가 사용자가 입력한 값으로 pair를 만들어 전달합니다. 이를 저장할 수 있는 클래스를 생성해봅시다.

 

MemberForm 클래스를 생성하고, 이 클래스에서는 받은 값을 변수에 저장합니다. 회원 가입 시 필요한 정보는 문자열 형태이므로, String 타입의 변수 name을 선언하고, Getter와 Setter 메서드를 추가합니다.

package Practice1.practicespring.controller;

public class MemberForm {
    private String name;

    public String getName() {
        return name;
    }

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

  createMemberForm.html에서의 "name"과 MemberFormname 변수는 서로 매칭되어 값을 받아옵니다. 이렇게 해서 사용자가 입력한 정보를 안전히 저장할 수 있게 되었습니다.


(3) 입력 받은 데이터를 통해 회원 가입이 가능하도록 개발하기

웹에서 입력받은 데이터를 통해 회원 가입을 진행하는 코드를 작성해봅시다.

 

createMemberForm.html에서는 <form action="/members/new" method="post">를 통해 POST 방식으로 데이터를 전달합니다. 이를 MemberController에서 @PostMapping을 통해 연결합시다.

@PostMapping("/members/new")
public String create(MemberForm form){
    // 멤버 객체 생성
    Member member = new Member();
    member.setName(form.getName());

    memberService.join(member);
    return "redirect:/";
}

 

매개변수 MemberForm을 사용해 createMemberForm.html에서 입력받은 이름(아이디) 정보를 받습니다. 이후 Member 객체를 생성하고 setName 메서드를 통해 아이디를 설정합니다.

 

 이 member 객체를 memberService를 통해 join 메서드를 호출하며, 회원 가입을 진행합니다. 마지막으로 "redirect:/"를 리턴함으로써 홈 화면으로 돌아갑니다.

이제 코드 원리를 한번 살펴봅시다.

  1. 홈 화면(home.html)에서 "회원 가입" 버튼을 클릭하면 /members/new 링크로 연결됩니다.
  2. MemberController에서 @GetMapping을 통해 매핑이 설정되어 있으므로, createForm() 메서드가 실행되고 templates - members - createMemberForm.html이 템플릿 엔진을 통해 렌더링됩니다.
  3. 해당 페이지에서 아이디를 입력하고 '등록' 버튼을 클릭하면 <form action="/members/new" method="post"> 코드에 의해 /members/new로 POST 방식으로 전달합니다.
  4. MemberController에서는 @PostMapping이 설정되어 있으므로, 해당 어노테이션이 붙은 메서드가 실행됩니다. @PostMapping은 주로 데이터를 Form에 넣어 전달할 때 사용하고, @GetMapping은 주로 조회할 때 사용합니다.
  5. @PostMapping으로 연결된 create 메서드가 호출됩니다. 이때, 매개변수로 전달되는 MemberForm에 아이디가 들어있으며, 이를 다시 create 메서드에 전달합니다. 이 이름을 이용해 Member 객체에 이름을 설정하고, join을 진행합니다.

3) 회원 조회 개발하기

(1) MemberController에서 url 매핑하기

이전에는 홈 화면에서 "회원 가입" 버튼을 누른 후, 회원을 등록하는 것까지 진행했습니다. 이번에는 홈 화면에서 "회원 목록" 버튼을 눌렀을 때, 회원 목록이 출력되도록 구현하겠습니다.

 

웹에서 입력받은 데이터를 통해 회원 가입을 진행하는 코드를 작성해봅시다.

 

home.html에서 "회원 목록"을 클릭하면 /members로 이동하도록 설정했습니다. 따라서 @GetMapping 어노테이션을 사용해 매핑을 설정하고, 회원 조회를 위한 메서드를 작성해봅시다.

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

 

먼저 /members URL과 연결하려면 @GetMapping("/members")를 사용하여 URL을 연결합니다.

 

매개변수로 Model을 받습니다. 그리고 memberService의 findMembers 메서드를 호출하여 반환된 값을 List 변수에 저장합니다.

 

이후 매개변수로 받은 Model에 addAttribute 메서드를 사용하여 회원 정보를 추가합니다.

 

마지막으로 "members/memberList"를 반환하여 templates/members 패키지에서 memberList.html을 찾도록 합니다. 이렇게 하면 회원 목록 버튼을 클릭했을 때, 회원 목록이 표시되는 페이지로 이동하게 됩니다.


(2) MemberList.html 작성하기 

이제 templates/members 패키지에 memberList.html 파일을 만들어 보겠습니다. 아래는 해당 파일의 내용입니다.

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
    <div>
        <table>
            <thead>
            <tr>
                <th>#</th>
                <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>

 

이제 "회원 등록" 버튼을 클릭하여 'spring1'과 'spring2'를 등록해 보고, "회원 목록" 버튼을 클릭하면 'spring1'과 'spring2'가 표시되는 것을 확인할 수 있습니다.

 

웹 페이지의 소스를 보면, <tr> 태그에 'spring1'과 'spring2'가 표시되어 있는 것을 확인할 수 있습니다. Thymeleaf 템플릿 엔진이 작동하여 렌더링하고 있기 때문입니다.

 

다음 코드를 주의깊게 살펴보세요.

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

 

${members}는 Model에서 key가 'members'인 value를 읽어오라는 의미입니다. MemberController에서 model.addAttribute를 통해 회원 정보를 List로 전달했기 때문에, 해당 List가 전달될 것입니다.

 

th:each는 Thymeleaf 문법으로, 'members'에 있는 모든 요소들을 순회하게 합니다. Loop를 돌면서 각 회원의 'id'와 'name'을 화면에 렌더링합니다.

 

 그러나 현재는 메모리를 사용하는 memoryMemberRepository를 이용하고 있기 때문에, 서버를 종료하면 회원 정보가 모두 삭제됩니다. 이는 원하는 동작이 아니므로, 다음 시간에는 회원 데이터를 파일이나 DB에 저장하는 방법을 알아보겠습니다.