Fascination
article thumbnail

[Spring Intro] Section 05. 회원 관리 예제 - 웹 MVC 개발

강의: 김영한의 스프링 입문

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9E%85%EB%AC%B8-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8/


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

1. 홈 컨트롤러 추가

  • java/hello/hellospring/controller/HomeController.java를 다음과 같이 작성한다
    • @GetMapping("/")에서 "/"는 처음의 도메인(localhost:8080) 경로를 의미한다
    • return "home"; 구문은 template 내의 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="/members/new">회원 가입</a> <a href="/members">회원 목록</a>
        </p>
    </div>
</div> <!-- /container -->
</body>
</html>

 

3. 실행

  • 홈 컨트롤러와 홈 html을 추가한 후 실행하면 다음과 같이 페이지가 띄워진다

 

4. 컨트롤러 vs 정적 파일

  • static의 index.html 화면이 아닌 home.html이 띄워지는 이유는 컨트롤러가 정적 파일보다 우선순위가 높기 때문이다
  • 지난 포스팅의 내용을 참고하면 된다 - 정적 컨텐츠 부분을 참고한다
 

[Spring Intro] Section 02. 스프링 웹 개발 기초

[Spring Intro] Section 02. 스프링 웹 개발 기초 강의: 김영한의 스프링 입문 # 스프링 웹 개발 기초 정적 컨텐츠: 파일을 그대로 웹브라우저에서 내려주는 것이다 MVC와 템플릿 엔진: 서버에서 HTML을 프

fascination-euna.tistory.com

  • 내장 톰캣 서버는 스프링 컨테이너에서 관련 컨트롤러가 있는지 먼저 찾고 없다면 static 파일을 찾는다
    • 현재 HomeController에서 매핑된 home화면이 있기 때문에 해당 화면을 호출하는 것이다

 

 

# 회원 웹 기능 - 등록

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 = "/members/new")
    public String createFrom(){
        return "members/createMemberForm";
    }
}

 

2. 회원 등록 폼 개발 - 회원 등록 폼 HTML

  • resources/templates 아래 members라는 폴더를 생성한다

  • 생성한 members 폴더 아래 다음과 같이 createMemberFrom.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>

 

3. 회원 등록 컨트롤러 - 웹 등록 화면에서 데이터를 전달받을 폼 객체

  • 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. 회원 등록 컨트롤러 - 회원 컨트롤러에서 회원을 실제 등록하는 기능

  • 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 = "/members/new")
    public String createFrom(){
        return "members/createMemberForm";
    }
	
    // 여기서부터 추가
    @PostMapping(value = "/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로 이동한다

  • 주어진 textbox에 이름을 spring으로하고 등록 버튼을 누르면 다시 메인 페이지로 리다이렉트 된다
    • 이때 멤버가 저장되는 것을 확인하기 위해서 MemberController.java에 create method 내에 다음과 같은 코드를 추가한다
@PostMapping(value = "/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 내에서 ("/members/new")에 매핑되는 createForm 메서드가 호출된다
    • viewResolver에 의해 createForm이 선택되고, thymeleaf 템플리 엔진이 return 코드에서 반환되는 members/createMemberForm(templates/members/createMemberForm.html)을 랜더링 하여 화면에 보여준다

  • 해당 페이지에서 이름을 spring으로 입력하고 등록 버튼을 누르면 POST 방식으로 입력한 name이 넘어가게 된다
    • createMemberForm.html을 확인해 보면 값을 입력하는 form 태그 내의 input 태그에서 name = "name"을 확인할 수 있다
    • "name" 부분은 서버로 넘어올 때, key 역할을 한다
    • 즉, 컨트롤러 패키지 아래에 있는 MemberForm에 선언된 변수 name과 매핑되고 있어 입력한 값이 name으로 전달되는 것이다

  • 등록 버튼을 누를 시 <form action = "/member/new" method="post">에 의해 action에 적힌 url에 POST 방식으로 입력한 값이 넘어가게 된다
    • memberControlller에서 @Postmapping되어 있는 create() method를 호출한다
    • MemberForm의 setName()은 아까 form 태그를 통해 전달된 이름을 name에 저장하는 역할을 한다
    • MemberForm의 getName()을 통해 MemberController 내 create() 함수에서 등록할 member의 이름을 지정해 줄 수 있다
    • 이렇게 생성된 member를 memberService의 join method를 통해 회원 가입시키고 페이지를 다시 홈 화면으로 리다이렉트 시키는 것이다

 


주로 데이터를 조회할 때는 GET method를, 데이터를 전달(등록)할 때는 POST method를 사용한다

 

 

# 회원 웹 기능 - 조회

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

  • java/hello/hellospring/controller/MemberController.java에 아래 코드를 추가한다
    • model.addAttribute를 통해 HTML에서 사용하는 thymeleaf 엔진에서 members List를 사용할 수 있게 된다
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를 보여주는 페이지는 members/memberList.html이다
    • memberList.html에는 thymeleaf 템플릿 엔진의 문법인 th:each가 사용되어 있고 이는 MemberController의 list method에서 model로 넘겨준 members에 대해 루프를 돌며 members에 저장된 객체에 대한 정보를 가져와 테이블로 표현한다
      • thymeleaf에서 ${}로 표시된 내용들은 model에 저장된 값들을 가져올 수 있게 해 준다
      • list method에서는 memberservice를 통해 모든 회원에 대한 리스트를 members로 저장하고, model.addAttribute를 사용하여 members를 템플릿 엔진(=thymeleaf)에서 활용할 수 있게 한다
      • 현재는 AttributeName이 members, value로 회원 전체에 대한 List를 가지는 데이터를 model이 저장하고 있는 것이다
      • 이때, 각 member의 id와 name은 private로 정의되어 있으므로 Property 방식(Getter/Sette를 통한 접근)으로 데이터를 불러온다
    • 즉, 해당 페이지에 접근하면 스프링은 /member와 관련된 컨트롤러(=MemberController)를 찾아 매핑되는 method(=list)를 실행한다

  • 실제 랜더링된 페이지의 소스코드를 확인하면 HTML로 테이블 내에 두 개의 행이 생성되어 있음을 확인할 수 있다

현재 우리는 메모리에 저장하는 방식을 사용했기 때문에 서버를 종료하고 재실행하면 저장했던 데이터들이 모두 사라진다.
실무에서는 이런 일이 발생하면 안 되므로 데이터베이스를 사용한다

 

profile

Fascination

@euna-319

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!