[Spring Intro]

(Spring Rollout) 섹션 05. 회원 관리 샘플 – 웹 MVC 개발

강의: 김영한의 봄 소개


# 회원 웹 기능 – 홈 화면 추가

1. 홈 컨트롤러 추가

  • 다음과 같이 java/hello/hellospring/controller/HomeController.java를 작성합니다.
    • @GetMapping(“/”)에서 “/”는 첫 번째 도메인(localhost:8080)의 경로를 나타냅니다.
    • return home”; 구문은 템플릿 내에서 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";
    }
    
}

2. 회원관리 홈페이지

  • 다음과 같이 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="http://fascination-euna.members/new">회원 가입</a> <a href="http://fascination-euna.members">회원 목록</a>
        </p>
    </div>
</div> <!-- /container -->
</body>
</html>

3. 달리기

  • 홈 컨트롤러와 홈 html을 추가한 후 실행하면 이렇게 페이지가 열립니다.

4. 컨트롤러 대 정적 파일

  • 정적인 index.html 화면 대신 home.html이 나오는 이유는 컨트롤러가 정적인 파일보다 우선순위가 높기 때문입니다.
  • 저번 포스팅 내용 참고하시면 됩니다 – 정적 내용 부분 참조

(Spring 소개) Section 02. Spring 웹 개발 기초

(Spring Intro) Section 02. Spring Web Development Basic Lecture: Introduction to Spring by Kim Younghan # Spring Web Development Basics Static Content: 웹 브라우저에서 파일을 그대로 다운로드 MVC 및 Template Engine: 서버에서 HTML 생성

매혹-euna.tistory.com

  • 내장된 Tomcat 서버는 먼저 Spring 컨테이너에서 관련 컨트롤러를 찾고 그렇지 않은 경우 정적 파일을 찾습니다.
    • 현재 HomeController에 시작 화면이 나타나므로 해당 화면을 불러옵니다.


# 회원을 위한 웹 기능 – 등록

1. 회원가입 양식 개발 – 회원가입 양식 관리자

  • 다음 코드를 java/hello/hellospring/controller/Membercontroller.java에 추가합니다.
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(value = "http://fascination-euna.members/new")
    public String createFrom(){
        return "members/createMemberForm";
    }
}

2. 회원가입 양식 개발 – 회원가입 양식 HTML

  • “Resources/Templates” 아래에 “Members”라는 폴더를 만듭니다.


  • 생성된 구성원 폴더에 다음과 같이 createMemberFrom.html을 작성합니다.
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
    <form action="http://fascination-euna.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>

3. Member Registration Controller – 웹 등록 화면에서 데이터를 받기 위한 Form 객체

  • 다음과 같이 java/hello/hellospring/controller/MemberForm.java를 작성합니다.
package hello.hellospring.controller;

public class MemberForm {
    private String name;

    public String getName() {
        return name;
    }

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

4. Member Registration Controller – Member Controller에 실제로 회원을 등록하는 기능

  • 다음 코드를 java/hello/hellospring/controller/MemberController.java에 추가합니다.
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;

import javax.swing.text.html.Option;
import java.util.Optional;

@Controller
public class MemberController {
    private final MemberService memberService;

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

    @GetMapping(value = "http://fascination-euna.members/new")
    public String createFrom(){
        return "members/createMemberForm";
    }
	
    // 여기서부터 추가
    @PostMapping(value = "http://fascination-euna.members/new")
    public String create(MemberForm form){
        Member member = new Member(); // 새로운 멤버 생성
        member.setName(form.getName()); // form으로부터 getName

        memberService.join(member); // 생성한 Member를 회원가입 시킴

        return "redirect:/"; // 회원가입이 끝나면 홈으로 리다이렉트
    }
}

5. 회원가입확인

  • 홈 화면에서 로그인을 클릭하면 localhost:8080/members/new로 리디렉션됩니다.
  • 지정된 텍스트 상자에 스프링 이름을 지정하고 등록 버튼을 클릭하면 다시 메인 페이지로 리디렉션됩니다.
    • 이때 MemberController.java의 create 메소드에 다음 코드를 추가하여 멤버가 저장되었는지 확인합니다.
@PostMapping(value = "http://fascination-euna.members/new")
public String create(MemberForm form){
	Member member = new Member();
    member.setName(form.getName());
        
    memberService.join(member);
    
    // 현재 사용되는 memberService 내의 MemberRepository는 SpringConfig.java에 의해 memoryMemberRepository를 호출하므로 그 안에 선언된
    // store 이름을 가지는 Map에 현재 생성한 member가 잘 저장되었는지를 확인한다
    System.out.println("member =" +memberService.findOne(member.getId()).get().getName());
    
    return "redirect:/";
}

6. 회원가입의 원칙

  • http://localhost:8080/members/new에 접속하면 다음과 같은 화면이 나타납니다.
    • 사용된 방법 GET 방식그리고 memberController 내부에서 (“http://fascination-euna.members/new”)에 매핑되는 createForm 메소드가 호출됩니다.
    • createForm은 viewResolver에 의해 선택되고 Thymeleaf 템플릿 엔진은 반환 코드에 의해 반환된 members/createMemberForm(templates/members/createMemberForm.html)을 렌더링하여 화면에 표시합니다.
  • 페이지에 이름을 Spring으로 입력하고 Register 버튼을 클릭하면, POST 방식입력한 이름은
    • createMemberForm.html을 확인하면 값을 입력하는 양식 태그 내부의 입력 태그에 name=”name”이 표시됩니다.
    • “이름” 부분은 서버에 전달할 때 키 역할을 합니다.
    • 즉, 컨트롤러 패키지 아래의 MemberForm에 선언된 변수 이름에 매핑되므로 입력한 값이 name에 전달됩니다.
  • 등록 버튼을 클릭하면,
    작업에 작성된 URL에 POST 방식입력된 값이 전송됩니다.

    • memberController에서 create() 메서드 @Postmapping을 호출합니다.
    • MemberForm의 setName()은 이전에 이름에서 Form 태그를 통해 전달된 이름을 저장하는 데 사용됩니다.
    • MemberForm의 getName()을 통해 MemberController의 create() 함수에 등록할 멤버의 이름을 지정할 수 있습니다.
    • 이렇게 생성된 멤버는 memberService의 Join 메소드를 통해 멤버로 등록되며 홈 화면으로 페이지가 돌아갑니다.

GET 방식은 주로 데이터 검색에 사용되고 POST 방식은 데이터 전송(등록)에 사용됩니다.

# 회원을 위한 웹 기능 – 검색

1. 멤버 컨트롤러의 쿼리 기능

  • 다음 코드를 java/hello/hellospring/controller/MemberController.java에 추가합니다.
    • 멤버 목록은 model.addAttribute를 통해 HTML에서 사용되는 Thymeleaf 엔진에서 사용할 수 있습니다.
import org.springframework.ui.Model;

...

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

2. HTML 회원 목록

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

3. 회원요청의 이행 및 원칙

  • http://localhost:8080에 접속하여 회원 목록을 클릭하면 회원 목록 페이지가 나타납니다.
  • 앞서 생성한 회원등록 기능을 이용하여 spring1, spring2를 등록합니다.
  • 멤버 목록을 확인하는 페이지를 클릭하면 Thymeleaf가 작동합니다.
    • 현재 회원 페이지는 members/memberList.html입니다.
    • memberList.html은 Thymeleaf 템플릿 엔진 구문인 th:each를 사용하고 MemberController의 list 메서드에서 모델에 전달된 멤버를 반복하고 멤버에 저장된 객체에 대한 정보를 검색하여 테이블로 푸시합니다.
      • thymeleaf에서 ${}로 표시된 내용을 통해 모델에 저장된 값을 검색할 수 있습니다.
      • list 메소드는 memberservice를 통해 모든 멤버의 리스트를 멤버로 저장하며, model.addAttribute를 통해 템플릿 엔진(=thymeleaf)에서 멤버를 사용할 수 있다.
      • 그냥 모델은 요소 및 값으로 AttributeName이 있는 모든 요소의 목록을 포함하는 데이터를 저장합니다.오전
      • 이때, 각 구성원의 ID와 이름은 비공개로 정의되어 있으므로 속성 메서드(getter/sette를 통해 액세스)에서 데이터를 검색합니다.
    • 즉, 페이지에 접근할 때 Spring은 /member와 연관된 컨트롤러(=MemberController)를 찾아 연관된 메서드(=list)를 실행합니다.
  • 실제 렌더링된 페이지의 소스 코드를 살펴보면 HTML로 테이블에 두 개의 행이 생성된 것을 확인할 수 있습니다.

현재 메모리에 데이터를 저장하는 방식을 사용하고 있기 때문에 서버를 종료했다가 다시 실행하면 저장된 데이터가 모두 사라집니다.
실제로는 이런 일이 발생하지 않아야 하므로 데이터베이스를 사용합니다.