본문 바로가기
Java/Spring입문

Spring 입문(10) 회원 관리 예제 - 웹 MVC 개발

by 이쟝 2023. 5. 4.
인프런의 김영한님의 스프링입문 강의를 듣고 정리한 내용입니다.
1. [회원 웹 기능 - 홈 화면 추가]
2. [회원 웹 기능 - 등록]
3. [회원 웹 기능 - 조회]

1. 회원 웹 기능 - 홈 화면 추가

MemberContrroller를 통해 회원을 등록하고 조회하기

1. 홈 컨트롤러 추가

src > main > java > hello > hellospring > controller > HomeController 
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";
    }
}

2. templates에 home.html생성

src > main > resources > templates > 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>
</body>
</html>

 

회원 가입과, 회원 목록은 아직 맵핑을 하지 않았기 때문에 에러가 뜬다. 

localhost:8080 요청을 하면 예전에 Welcome Page로 index.html(정적 컨텐츠)를 반환했는데 바로 home.html이 뜨는 이유는?
- 우선순위 떄문!!!

정적 콘텐츠 반환 시에 스프링 컨텐이너에 관련 컨트롤러가 있는지 찾고 난 뒤 없다면 정적 컨텐츠(index.html)를 반환하는데 지금은 HomeController의 home( )이 home.html를 맵핑하고 있기에 이 컨트롤러가 호출되는 것이다.(그래서 index.html은 무시된다.)

2. 회원 웹 기능 - 등록

1. 회원 등록 폼 개발

1-1. 회원 등록 폼 컨트롤러 생성(createForm( ))

package hello.hellospring.controller;

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

@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";
    }
}

 1-2. templates에 members 폴더 생성 후 회원 등록 폼 HTML 생성(createMemberForm) 생성

src > main > resources > templates > members > 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>

</body>
</html>

페이지 소스 보기를 하면 작성한 createMemberForm.html 소스가 렌더링 되는 것을 확인할 수 있다. 

members/new
페이지에서 이름을 넣고, 등록을 하면 {name:이름} key {name}와 value {이름}로 서버에 저장된다.

2. 회원 등록 MemberForm.java 클래스 생성

src > main > java > hello > hellospring > controller > MemberForm.java

createMemberForm에서의 name이 setName의 매개변수로 들어가게 되면서 createMemberForm과 MemberForm의 name이 연결된다.

예) Spring이라는 이름을 넣게 되면, MemberForm.getName 하면 Spring을 얻을 수 있다. 
package hello.hellospring.controller;

public class MemberForm {
    private String name;

    public String getName() {
        return name;
    }

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

 

3. MemberForm과 관련해서 실제 Controller 만들기(MemberController에)

create 메서드
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
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 create(MemberForm form){
        Member member = new Member();
        member.setName(form.getName());
        memberService.join(member);
        return "redirect:/"; // 홈으로 이동
    }

}

 

*웹 회원 등록 구조*

  1. 회원 가입 클릭 -> url: members/new -> (url로 데이터를 조회하는 http GET방식) 
  2. @GetMapping("/members/new") createForm 메서드 호출 (MemberController) -> /members/createMemberForm.html로 이동
  3. viewResolver가 templates에서 members/createMemberForm을 찾아 렌더링 (화면에 html이 보이게 된다.)
  4. 이름 입력창에 값을 입력하고 등록 버튼을 누르면 form 태그의 action이 url로 http POST방식
  5. @PostMapping("/members/new") create 메서드 호출
  6.  MemberForm의 name 필드에 setter를 통해 화면에 입력한 name값이 들어오게 된다.
  7.  MemberForm에서 getter로 값을 꺼내 Member 생성 후 저장
  8. 마지막에 home화면 ("/")으로 이동(redirect)

    -> /members/new로 url 주소는 같지만 맵핑 방식이 Get과 Post방식으로 다르다. 

3. 회원 웹 기능 - 조회

1. 회원 컨트롤러에서 조회 기능

MemberController

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

 

2. 회원 리스트 HTML

src > main > resources > 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> <!-- thymeleaf를 사용한다.-->
                <tr th:each="member : ${members}">
                    <td th:text="${member.id}"></td>
                    <td th:text="${member.name}"></td>
                </tr>
            </tbody>
        </table>
    </div>
</div>
</body>
</html>

출력결과&nbsp;
렌더링된 최종 결과물(소스페이지)

 

thymeleaf: 선언부에 주의
${모델 내 attribute} : 컨트롤러에서 넘겨온 모델 내의 attribute를 thymeleaf 템플릿 엔진이 꺼낸다.
th:each => 루프를 돈다. 
${members}에서 객체를 꺼내서 member에 저장 -> 객체의 id와 name을 꺼내기
${member.id} -> Member 도메인의 getId( ) 호출 / ${member.name} -> Member 도메인의 getName( )호출


자바 빈 프로퍼티 방식으로 객체에 접근한다. => 객체의 실제 데이터는 private 하고, 접근할 때 공개된 getter, setter 메서드를 통해 접근한다.

메모리에 있기 때문에 서버를 껐다가 다시 켜게 되면 회원 데이터가 사라지게 된다. -> DB에 저장해야 한다!!!!