본문 바로가기

개발새발 개발하기

[Spring] 회원 관리 예제 - 웹 MVC 개발

인프런의 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술를 정리한 글이다

🏃🏻‍♀️ 회원 웹 기능 - 홈 화면 추가

controller 패키지 아래에 HomeController 파일을 생성한다.

HomeController 안에서 인덱스 페이지 매핑을 하고 있으므로, index.html이 아닌 home.html을 인덱스 페이지로 보여줄 것이다.

package hello.hellospring.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HomeController {

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

templates 폴더 아래에 home.html 파일을 생성한다.

 

이후 localhost:8080을 띄워보면, index.html 파일이 아닌 home.html 파일이 나타난다.

[참고]

컨트롤러가 정적 파일보다 우선순위가 높다.

 

🏃🏻‍♀️ 회원 웹 기능 - 등록

1. GetMapping을 통해 화면 연결

멤버 등록하는 화면을 연결시켜주기 위해, 먼저 MemberController에 코드를 추가한다.

전체 코드

package hello.hellospring.controller;

import hello.hellospring.domain.Member;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

/**
 * 스프링이 처음에 뜰 때, 스프링 컨테이너라는 통이 생기고 거기에
 * 아래와 같이 Controller라는 어노테이션이 있으면
 * MemberController 객체를 생성해서 스프링에 넣어두고, 스프링이 관리한다.
 */
@Controller
public class MemberController {

    /**
     * MemberService를 new해서 사용하면 다른 여러 컨트롤러들이 MemberService를 사용할 때마다 새로운 객체가 생성된다. (매번 생성)
     * -> 하나의 객체를 공유해서 사용하면 됨
     */
    private final MemberService memberService;

    /**
     * 생성자 사용
     * 생성자에 Autowired가 있으면 스프링이 스프링 컨테이너에 있는 서비스를 연결시켜 준다.
     * ! 그런데 !
     * MemberSerivce는 순수한 자바 클래스이기 때문에 스프링이 얘를 알 수가 없다.
     * -> MemberService에 @Service를 넣어준다.
     * MemoryMemberRepository도 마찬가지 (@Repository를 넣어주면 된다.)
     */
    @Autowired
    public MemberController(MemberService memberService) { // MemberController를 생성할 때, memberService를 넣어준다. (의존관계)
        this.memberService = memberService;
    }

    @GetMapping("/members/new")
    public String createForm() {
        return "members/createMemberForm"; // templates의 members/createMemberForm으로 간다. (화면에 띄움)
    }
}
/**
 * 컨트롤러를 통해 외부 요청을 받고,
 * 서비스를 통해 비즈니스 로직을 만들고,
 * 레포지토리에서 데이터를 저장
 */

 

회원 등록 폼 화면을 생성해주기 위해, templates아래에 members 폴더를 생성하고, createMemberForm 파일을 생성한다.

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

 

2. 폼 객체 생성

localhost:8080을 띄우고, 회원 가입 버튼을 누르면 localhost:8080/members/new로 이동하고, 다음과 같은 화면이 뜬다.

 

이 화면에서 데이터를 전달 받을 폼 객체를 controller 폴더 아래에 생성한다. (MemberForm 파일)

package hello.hellospring.controller;

public class MemberForm {

    private String name; // 이 name과 createMemberForm.html의 name과 매칭이 된다.

    public String getName() {
        return name;
    }

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

 

3. 회원 등록 기능 추가

이후, 회원을 실제로 등록하는 기능을 추가하기 위해 MemberController에 다음과 같은 코드를 추가한다.

전체 코드

package hello.hellospring.controller;

import hello.hellospring.domain.Member;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

/**
 * 스프링이 처음에 뜰 때, 스프링 컨테이너라는 통이 생기고 거기에
 * 아래와 같이 Controller라는 어노테이션이 있으면
 * MemberController 객체를 생성해서 스프링에 넣어두고, 스프링이 관리한다.
 */
@Controller
public class MemberController {

    /**
     * MemberService를 new해서 사용하면 다른 여러 컨트롤러들이 MemberService를 사용할 때마다 새로운 객체가 생성된다. (매번 생성)
     * -> 하나의 객체를 공유해서 사용하면 됨
     */
    private final MemberService memberService;

    /**
     * 생성자 사용
     * 생성자에 Autowired가 있으면 스프링이 스프링 컨테이너에 있는 서비스를 연결시켜 준다.
     * ! 그런데 !
     * MemberSerivce는 순수한 자바 클래스이기 때문에 스프링이 얘를 알 수가 없다.
     * -> MemberService에 @Service를 넣어준다.
     * MemoryMemberRepository도 마찬가지 (@Repository를 넣어주면 된다.)
     */
    @Autowired
    public MemberController(MemberService memberService) { // MemberController를 생성할 때, memberService를 넣어준다. (의존관계)
        this.memberService = memberService;
    }

    @GetMapping("/members/new")
    public String createForm() {
        return "members/createMemberForm"; // templates의 members/createMemberForm으로 간다. (화면에 띄움)
    }

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

        memberService.join(member);

        return "redirect:/"; // 회원가입이 끝나면 홈 화면으로 돌린다.
    }
}
/**
 * 컨트롤러를 통해 외부 요청을 받고,
 * 서비스를 통해 비즈니스 로직을 만들고,
 * 레포지토리에서 데이터를 저장
 */

 

localhost:8080/members/new 화면에서 이름을 입력하고, 등록 버튼을 누르면 다시 홈 화면으로 이동한다.

 

🏃🏻‍♀️ 회원 웹 기능 - 조회

1. 회원 조회 기능 추가

회원 조회 기능을 추가하기 위해 MemberController에 다음 코드를 추가한다.

전체 코드

package hello.hellospring.controller;

import hello.hellospring.domain.Member;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import java.util.List;

/**
 * 스프링이 처음에 뜰 때, 스프링 컨테이너라는 통이 생기고 거기에
 * 아래와 같이 Controller라는 어노테이션이 있으면
 * MemberController 객체를 생성해서 스프링에 넣어두고, 스프링이 관리한다.
 */
@Controller
public class MemberController {

    /**
     * MemberService를 new해서 사용하면 다른 여러 컨트롤러들이 MemberService를 사용할 때마다 새로운 객체가 생성된다. (매번 생성)
     * -> 하나의 객체를 공유해서 사용하면 됨
     */
    private final MemberService memberService;

    /**
     * 생성자 사용
     * 생성자에 Autowired가 있으면 스프링이 스프링 컨테이너에 있는 서비스를 연결시켜 준다.
     * ! 그런데 !
     * MemberSerivce는 순수한 자바 클래스이기 때문에 스프링이 얘를 알 수가 없다.
     * -> MemberService에 @Service를 넣어준다.
     * MemoryMemberRepository도 마찬가지 (@Repository를 넣어주면 된다.)
     */
    @Autowired
    public MemberController(MemberService memberService) { // MemberController를 생성할 때, memberService를 넣어준다. (의존관계)
        this.memberService = memberService;
    }

    @GetMapping("/members/new")
    public String createForm() {
        return "members/createMemberForm"; // templates의 members/createMemberForm으로 간다. (화면에 띄움)
    }

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

        memberService.join(member);

        return "redirect:/"; // 회원가입이 끝나면 홈 화면으로 돌린다.
    }

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

        return "members/memberList";
    }
}
/**
 * 컨트롤러를 통해 외부 요청을 받고,
 * 서비스를 통해 비즈니스 로직을 만들고,
 * 레포지토리에서 데이터를 저장
 */

 

2. 회원 조회 화면 추가

회원 조회 화면을 추가하기 위해, 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>
          <!-- th:each는 thymeleaf 문법으로, members 배열에 있는 아이템들을 하나씩 접근한다는 소리다 (for문) -->
          <tr th:each="member : ${members}">
            <!-- Member 객체의 getId, getName을 통해 id와 name값을 받아온다. -->
            <td th:text="${member.id}"></td>
            <td th:text="${member.name}"></td>
          </tr>
        </tbody>
      </table>
    </div>
  </div> <!-- /container -->
</body>
</html>

위의 MemberController의 list 함수를 보면, Model을 해당 화면으로 보내주고, 이 화면에서 members 리스트를 받아, th:each를 사용해 각 멤버들을 화면에 나타나게 한다.

 

localhost:8080을 실행하고, 회원 가입 후, localhost:8080/members를 확인하면 가입한 회원들의 목록이 나타난다.