본문 바로가기
Java | Spring/Spring 입문

[스프링 입문] 5. 회원 관리 예제 - 웹 MVC 개발

by 동기 2022. 3. 14.
반응형

홈화면 추가 및 회원 등록,조회 기능을 추가 해 보자.

1. Home 컨트롤러 및 html 추가

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

 

 

home.html 추가

home.html 추가

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Hello</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
    <div>
        <h1>Hello Spring</h1>
        <p>회원 기능</p>
        <p>
            <a href="/members/new">회원 가입</a>
            <a href="/members">회원 목록</a>
        </p>
    </div>

</body>
</html>

 

앞서 게시한 정적 컨텐츠 에서 설명했듯이, 스프링 컨테이너에서 컨트롤러를 먼저 확인한다. 기존에는 루트 ( / ) 컨트롤러가 없었기 때문에, 정적 컨텐츠인 index.html을 반환하였다.

현재는 HomeController의 추가 및 루트(/) 리턴값으로 home을 설정했기 때문에, 템플릿 폴더의 home.html을 반환해 준다.

 

실행 결과

HomeController의 루트(/)추가 및 리턴값 home 설정으로,  정적 컨텐츠로 static 의 index.html 를 반환하는것이 아닌 templates의 home.html 을 반환.

 

2. 회원가입

홈 화면에서 회원가입(등록)을 누르면 /members/new , 회원 목록(조회)을 누르면 /members url로 가도록 되어있으니 해당 요청을 처리하는 코드를 MemberController에 추가해 주자.

 

@Controller
public class MemberController {
    private final MemberService memberService;

    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }

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

    @PostMapping("/members/new")
    public String joinMember(MemberForm form){ //createMemberForm.html 의 input창으로 받아온 post요청 처리, MemberForm 객체에 담아서 전달 받는다.
        Member member = new Member();
        member.setName(form.getName());
        memberService.join(member);
        System.out.println("member name ="+ member.getName());
        return "redirect:/";
    }

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

각 리턴값에 맞게 디렉토리 및 파일을 생성해 주자.

 

먼저, 가입(createMemberForm) 쪽을 살펴보자.

 

createMemberForm.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Hello</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<div class="container">
   <form action="/members/new" method="post">
       <div class="form-group">
           <label form="name">이름</label>
           <input type="text" id="name" name="name" placeholder="이름을 입력하세요">
       </div>
       <button type="submit">등록</button>
   </form>
</div>

</body>
</html>

 

홈화면에서 회원가입 버튼을 눌러 /members/new url로 접근을 하게 되면, 위의 MemberController에서 createMemberForm.html을 반환한다.

 

createMemberForm 에서는 사용자 입력을 받아 /members/new 경로로 post요청을 하게 된다. 이 요청은 form태그를 이용하여 가능하다.

 

<form 간단 설명>
<form>태그를 통해 /members/new url로 post요청을 할 수 있으며, Controller에서 처리하게 된다.
<form>태그 내부의 <input>태그를 통해 사용자 입력을 받아 서버로 폼을 전송할 수 있다. (다른 태그도 가능하니 검색해보자!)
<input> 태그의 name 속성은 <input> 요소의 이름을 명시한다.name 속성은 폼(form)이 제출된 후 서버에서 폼 데이터(form data)를 참조하기 위해 사용되거나, 자바스크립트에서 요소를 참조하기 위해 사용된다.

 

요청을 받는 Controller를 보면, members/new post요청의 메서드를 보면, 인자로 MemberForm객체를 받고 있다.

MemberForm 객체를 통해 <form>태그에서 제출한 데이터를 담아 Controller에서 처리할 수 있다.

 

MemberForm 클래스를 만들어 보자.

class MemberForm{
        String name;

        public String getName() {
            return name;
        }

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

위의 createMemberForm 내부의 <input>태그의 name="name"이라고 썼기 때문에, 클래스 에서도 name으로 받는다.

*만약 name="userName" 으로 작성했으면, 클래스에서도 String userName; 으로 작성하여 받아올 수 있다.

 

MemberForm 클래스는 작성이 완료되었고, 해당 메서드를 살펴보자.

    @PostMapping("/members/new")
    public String joinMember(MemberForm form){ //createMemberForm.html 의 input창으로 받아온 post요청 처리, MemberForm 객체에 담아서 전달 받는다.
        Member member = new Member();
        member.setName(form.getName());
        memberService.join(member);
        System.out.println("member name ="+ member.getName());
        return "redirect:/";
    }

member 인스턴스를 생성하고, 이름을 설정 해주는데, 사용자 입력값이 담긴 form 객체에서 꺼낸 이름을 넣어준다.

그리고 memberService의 join 메서드에 member객체를 넣어준다.

완료되면 home으로 간다. ( redirect: 를 통해 다른 뷰로 넘겨줄 수 있다. 여기서는 루트(/)이기 때문에 홈으로 간다.)

 

결과

MemberService의 join()메소드에는 중복처리도 해놨기 때문에, 첫 가입은 성공하고 두번째 가입에는 Exception을 던지고 있다.

 

3. 회원 목록

이번에는 회원 목록을 조회하는 부분을 살펴보자

    @GetMapping("members")
    public String memberList(Model model){ //여기서의 Model 은 spring 이 제공하는 인터페이스,
        List<Member> members = memberService.findMembers(); //map 의 values를 전부 가져옴
        model.addAttribute("members",members);
        return "members/memberList";
    }

memberService의 findMembers() 메서드를 통해서, Map에 저장해놨던 values를 

List형태의 members 인스턴스에 담아준다.

model에 members를 담아서memberList.html로 전달한다.

memberList.html 에서는 thymeleaf each 구문을 통해 members 리스트를 순회하며, 순회할때마다 id와 name을 가져 온다.

 

memberList.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>memberList</title>
</head>
<body>
    <div class="container">
        <table>
            <thead>
                <tr>
                    <th>#</th>
                    <th>이름</th>
                </tr>
            </thead>
            <tbody>
<!-- 스프링이 get id, get name (property 접근 방식)을 해서 가져와준다-->
            <tr th:each="member : ${members}">
                <td th:text="${member.id}"></td>
                <td th:text="${member.name}"></td>
            </tr>
            </tbody>
        </table>
    </div>
</body>
</html>

 

결과

 

 

TODO

더보기

thymeleaf 템플릿 엔진을 쓰기 위해 <html>의 attribute 에 선언 해줘야하는걸로 알고있다.

<html xmlns:th="http://www.thymeleaf.org"> 이렇게 적어줘야 하지만,

memberList.html 에는 작성하지 않았는데 결과로는 잘 나온다. 이유를 찾아야 할 것 같다.

반응형

댓글