웹 프로그래밍/공부, 연습

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

이 글은 인프런에서 김영한 님의 "스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술"을 수강 후 개인적으로 공부한 내용을 정리한 게시글입니다. 잘못된 점이나 부족한 부분이 있다면 언제든 지적 부탁드립니다.

 

해당 강의는 이곳에서 수강할 수 있습니다.

 

이전 강의에서는 스프링 빈과 의존관계에 대해 학습하였습니다.

이번 강의에서는 회원 관리 예제를 통해 웹 MVC 개발 원리를 학습해 봅니다.

 

 

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

 

이전의 강의에서 작성한 멤버 컨트롤러에서 회원을 등록, 조회하는 기능과 화면을 만들어 봅니다.

 

기존에는 "localhost:8080"으로 홈 화면 접속 시 staticindex.html을 띄웠지만, 이번에는 홈 화면을 띄우는 컨트롤러를 만들어 우리가 직접 작성한 홈 화면을 띄워봅니다.

 

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

 

이전 강의에서 학습한 것처럼 @Controller를 사용해 HomeController를 스프링 컨테이너에 등록하고 @GetMapping을 사용하여 "/"와 같은 url을 입력 시(홈 화면으로 들어올 시) 다음의 메서드를 호출합니다. 해당 메서드는 templates 폴더에서 "home.html"을 찾아 화면을 띄워줍니다.

 

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>

 

위와 같이 파일 생성 후 프로젝트를 실행시키고 "localhost:8080" url을 통해 홈 화면으로 들어가면 다음과 같은 홈 화면을 볼 수 있습니다.

 

 

home.html 파일을 살펴보면 홈 화면에서 회원 가입 링크를 누르면 "/members/new"로 이동, 회원 목록 버튼을 누르면 "/members"로 이동합니다. (이동하는 화면, 기능은 "2. 웹 기능 - 등록"에서 구현합니다.)

 

'2. 스프링 웹 개발 기초'에서 살펴본 것처럼 컨트롤러는 정적 컨텐츠(/static/.html)보다 우선순위가 높습니다. 따라서 클라이언트에서 요청이 오면 먼저 스프링 컨테이너 안의 관련 컨트롤러를 먼저 찾고(해당 예제에서는 HomeController), 컨트롤러가 없을때는 static 폴더 안에서 관련 파일을 찾습니다(해당 예제에서는 index.html).

현재 "/"(홈 화면)에 매핑이 되어있기 때문에(@GetMapping("/")) home.html로 이동(return "home";), 컨트롤러가 없을 때의 기존의 홈 화면이었던 index.html은 무시됩니다. 

 

 

2. 회원 웹 기능 - 등록

 

위에서 구현한 홈 화면에서 회원 가입 버튼을 누르면 'members/new'로 이동합니다.

이 화면에서 회원 가입 기능을 수행하며, 이를 구현하기 위해 기존의 회원 컨트롤러(MemberController)에 다음과 같은 Get방식(url로 화면 지정)의 Mapping을 만들어줍니다. 

 

@GetMapping("/members/new")
public String createForm(){
   	return "members/createMembersForm";
}

 

위 메서드는 url에서 "/members/new"와 같은 요청을 받으면 "members/createMemberForm"화면으로 이동합니다.

 

templates 폴더에 members 폴더(회원과 관련된 html 파일들이 저장됩니다)를 생성, 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> <!-- /container -->
</body>
</html>

 

위와 같이 코드를 작성하고 프로젝트를 실행하면 홈 화면에서 회원가입 버튼을 눌렀을 때 @GetMapping을 통해 "/members/new"로 이동, 리턴된 "/members/createMemberForm" 화면(html)을 볼 수 있습니다.

 

회원 등록 시 볼 수 있는 화면

 

위 html 파일에서 <form> 태그는 값을 입력받을 수 있는 html 태그입니다.

이 form은 input으로 이름(name)을 입력 받고 등록 버튼을 누르면 post 방식으로 action url(members/new)로 이동합니다.

 

이때 <input> 태그 안의 name = "name" 중 "name"은 입력이 서버로 들어올 때의 key값으로, 다음으로 우리는 이 입력 데이터를 전달받을 Form 객체를 만듭니다.

 

controller 폴더 아래 MemberForm 자바 파일을 생성하고 MemberForm 클래스를 작성합니다.

 

package hello.hellospring.controller;

public class MemberForm {
    private String name;

    public String getName() {
        return name;
    }

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

 

스프링은 createMemberForm.html의 "name"을 보고 MemberForm 클래스의 setName()을 호출해 멤버변수 name에 위에서 입력으로 받은 데이터를 넣습니다. 

 

post방식의 "members/new" 요청을 받아 입력받은 데이터로 실제 등록하는 기능을 구현하기 위해 회원 컨트롤러에 @PostMapping을 사용한 메소드를 만듭니다.

 

    @PostMapping("members/new")
    public String create(MemberForm form){

        Member member = new Member();
        member.setName(form.getName());

        memberService.join(member);

        //System.out.println("name is " + member.getName());

        return "redirect:/";
    }

 

이전에 @GetMapping으로 요청받은 주소 "members/new"와 동일하지만, 위 코드는 @PostMapping으로 처리하므로 이전과 다르게 Mapping이 가능합니다.

(데이터를 form에 넣어 전달(등록)할 때는 주로 @PostMapping, 저장된 데이터를 조회할 때는 주로 @GetMapping이 사용됩니다.)

 

실행시 회원 가입에서 볼 수 있는 화면에 입력 값으로 "spring"을 넣고 등록 버튼을 누르면, 매개변수로 받은 MemberForm 객체 form의 name에 우리가 입력한 "spring"이 key가 name으로 저장되어 전달됩니다. 

멤버 객체를 생성하고, form.getName()으로 form객체에서 입력값(name)을 꺼내 회원 객체의 setName() 메서드로 회원의 이름을 설정합니다. 회원 서비스의 join() 메서드를 사용해 회원가입을 진행 후 "redirect:/"을 리턴하여 메서드를 마치면 회원가입 후 홈 화면으로 돌아갑니다.

 

위의 주석을 해제하고 프로젝트를 실행시켜 회원 가입을 진행하면 정상적으로 회원가입이 된 회원의 이름이 다음과 같이 출력되는 것을 확인할 수 있습니다.

 

 

 

3. 회원 웹 기능 - 조회

 

회원 목록 버튼을 눌렀을 때 현재 가입된 모든 회원을 조회할 수 있는 기능을 구현합니다.

회원 목록 버튼을 눌렀을때의 요청 "/members"을 @GetMapping을 사용해 메서드를 구현합니다.

 

회원 컨트롤러에 다음과 같은 코드를 추가로 작성합니다.

 

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

        return "members/memberList";
    }

 

home.html에서 요청 받은 "/members"를 list() 함수와 매핑합니다. list() 함수는 회원 서비스에서 등록된 모든 회원을 리스트로 전달받아 이를 화면으로 보여주는 메서드입니다.

 

먼저 회원 서비스에서 findMembers() 함수를 사용해 등록된 모든 회원들을 리스트 형태인 members로 받고, 모델에 이를 key "members"로 담아 "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>
            <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>

 

여기서부터는 Thymeleaf 템플릿 엔진이 동작합니다.

모델을 넘겨받은 Thymeleaf 템플릿 엔진은 렌더링 후 변환된 html을 웹 브라우저에 띄웁니다.

 

'each'는 자바의 for each와 비슷한 문법으로 루프를 돌며 모델로 넘겨받은 "members"라는 객체 리스트에서 객체를 하나씩 꺼내 member에 담고, .id, .name으로 각 member의 idname을 출력합니다. 이때 각 멤버 변수의 접근은 자바 프로퍼티 방식으로 id, name이 private이므로 property의 getter로 접근하여 값을 가져옵니다.

 

여기까지 코드를 작성하고 프로젝트를 실행합니다.

홈 화면에서 '회원 가입'으로 spring1, spring2의 회원을 등록합니다. 그 후 '회원 목록'을 통해 가입된 회원 전체 목록을 확인하면 회원 가입한 spring1과 spring2를 각각의 id와 함께 확인할 수 있습니다.

 

 

지금까지는 데이터를 메모리 리포지토리에 저장하였기 때문에 서버를 내렸다가 다시 실행하면 이전에 저장된 데이터(회원 정보)가 전부 지워집니다. 실무에서는 이러한 데이터를 파일 또는 데이터 베이스에 저장하여야 하며, 이는 다음 강의에서 다루도록 합니다.

 

 

 

이번 강의에서는 회원 관리 예제를 통해 웹 MVC 개발 원리를 학습해 보았습니다.

다음 강의에서는 스프링의 DB 접근 기술에 대해 알아봅니다.