-

[스프링부트 Step 13] - 회원 웹 기능 추가 본문

백엔드 기술 정리/스프링 부트

[스프링부트 Step 13] - 회원 웹 기능 추가

흣차 2022. 1. 6. 01:10
728x90
반응형

저번 포스팅에선 Controller도 만들고 DI를 통해 의존성 주입도 했었습니다.

이제 이 MemberController를 통해 회원을 등록하고 조회하는걸 한 번 만들어보려고 합니다.

먼저 홈 화면을 추가를 할 것입니다.

이 Home 화면도 Controller로 만들기 위해 Controller어노테이션을 위에 추가해줍니다.

그리고 GetMapping을 쓸 것입니다.

이 @GetMapping은 데이터를 받아온다고 지난번에 설명했습니다.

그러니까 home()이라는 메서드를 실행할것인데, 이 home을 실행하면 "home"을 리턴해주고 이 때 주소를 /라고 입력하게 되면 기본 8080주소가 home화면입니다.

당연하겠죠? 

메인 화면이 home화면이니까 다른 주소값이 아닌 제일 기본이 되는 주소가 home이니까요.

자 그리고 이 home을 return할 때 보여주어야 할 페이지 View를 만들어야 합니다.

따라서 home.html을 만들어보겠습니다.

밑에 template에서 home.html이라고 만듭시다.

이렇게 만드시는데 회원 가입과 회원 목록을 클릭했을 때 다른 링크로 가야하므로 각각 이름을 이렇게 지정해줍니다.

저는 회원 가입은 members/new, 회원 목록은 /members라고 했습니다.

그럼 실행헀을 때 어떻게 뜨는지 확인해보겠습니다.

자 어때요?

단순히 html단만 만들어도 이렇게 반영이 잘 되었네요.

이렇게 홈 화면을 만들어보았고 원가입이나 회원 목록을 누르면

에러가 뜨겠죠?? 아 이건 서버 끄고 실행해서 연결할 수 없음이 뜬건데 아마 여러분들은 Whitellabel Error가 떠야 합니다.

회원목록도 누르면 에러가 뜰 것입니다.

당연히 아무 것도 안만들었으니까 그렇겠죠?

복습을 잠깐 해보겠습니다.

예전에 정적 컨텐츠를 설명할 때 먼저 스프링Controller안에 있는 스프링 컨테이너 내부에 관련 Controller를 우선적으로 찾는다고 했었습니다. 그런데 만약 없으면 static파일을 찾아서 html이 있는지 확인한다고 했었습니다.

그런데 우리가 이 연습 예제를 통해서 여러가지 html파일들을 많이 만들었었잖아요.

그것들은 우선순위에서 Controller에 밀리기 때문에 실행되지 않습니다.

무슨말이냐하면 homeController에서 @Controller로 걸었던 이 home메서드와 GetMapping되어 return되는 이 home.html파일은 기본적으로 스프링에선 어노테이션이 걸려있는 것을 우선적으로 처리하기 때문에 기존에 실행되었어야할 hello-spring이라던가 hello.html같은 파일들은 실행되지 않는다는 것입니다.

 

음 이렇게 해서 일단 홈 화면만 아주 간단하게 짜봤습니다. 그럼 이제 회원 등록과 회원 조회를 한 번 짜보도록 해봅시다.

바로 코드로 들어가봅시다.

MemberController로 들어갑니다. 여기에 우린 회원 등록 메서드를 만들 것입니다.

자 그래서 MembersController에 members/new라는 주소로 매핑하여 createForm()이라는 메서드를 만들고 return할 때 members/createMembersForm으로 return합시다.

당연히 return할 때 members와 createMemberForm도 따로 만들어야 합니다.

그러므로

이렇게 templates 내부에 members 폴더를 생성하고 html파일도 만듭니다.

자 이렇게 입력해줍니다.

그럼 실제 화면에선 어떤지 확인해보겠습니다.

회원 가입을 누르니까 이런 창이 뜨네요.

정상적으로 회원 가입 폼이 등록 되었습니다.

하지만 버튼을 클릭하면 다시 에러가 뜰 거에요. 왜냐하면 아직 우리가 버튼을 클릭했을 때 로직을 만들지 않았기 때문에 그렇습니다.

이런건 나중에 JS로 만들어줄수도 있습니다.

일단 회원가입 로직을 덜 만들었으니 MemberForm 클래스를 만들어봅시다.

그리고 Getter / Setter를 만들기 위해 Alt+ Insert키를 눌러서 게터 세터를 만듭니다.

우리는 회원가입을 진행함에 있어서 그냥 name만 가지고 만들 것이기 때문에 getName과 setName만 다룹니다.

그래서 비교적 로직이 간단합니다.

자 이렇게 하면 membersForm.html에 있는 html파일에서 우리가 name을 입력하면 button을 클릭했을 때 submit방식으로 로직을 짰었습니다.

이게 무슨 의미냐면

<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 action 은 이 form의 action이 일어나는 주소라고 생각하시면 되고 method는 post. 그러니까 등록하겠다는 의미입니다. 무엇을요? name을요.

그러니 label을 name으로 만들고 input type에는 id와 name을 모두 name이라 했을 때 그 text에 name을 입력하면 이 모든 것을 하나의 form으로 묶어서 button을 클릭했을 때 submit하겠다는 뜻입니다.

그럼 받아온 name을 MemberForm으로 가져오고 Getter / Setter를 이용하여 name을 유지보수할 수 있습니다.

 

이후 MemberController에다가 받아온 이 name을 활용해서 회원가입을 해야합니다.

이렇게 생각하시면 되겠습니다.

MemberForm클래스는 회원가입을 위해 html에서 가져온 name을 하나의 String으로 만들고 그 name을 MemberController 클래스에 넘겨서 회원가입을 진행해야 한다고 생각합시다.

그럼 MemberController에서 어떻게 만들어야 하냐면

이렇게 만들어 봅시다.

보통 GetMapping은 데이터를 얻어올 때, PostMapping은 데이터를 제출할 때 사용합니다.

그리고 받아온 name을 MemberForm의 form이라는 생성자를 통해 create에 주입시킵니다.

Member를 새로 선언하고 선언한 member에 setName을 통해 form을 getName()합니다.

이후 member의 이름 설정을 마치고 memberService에 join하면 회원가입이 끝납니다.

마지막으로 return할 때 "redirect:/"라고 하면 새로고침이 일어나 사이트의 홈으로 이동합니다.

자 그럼 서버를 실행해보겠습니다.

그리고 이름을 이렇게 입력하고 등록해봅니다.

그럼 다시 홈 페이지로 돌아오게 됩니다.

그런데, 이 때 등록했던 이름을 다시 등록하면 어떤 일이 발생할까요?

아마 이런 에러가 뜰 것입니다.

자 MemberService 클래스를 보시면


private void validateDuplicateMember(Member member) {
    memberRepository.findByName(member.getName())
            .ifPresent(m ->{
        throw new IllegalStateException("이미 등록된 회원입니다.");
    });
}

이런 로직을 예전에 만들었었습니다.

당연히 이미 등록되어 있는 상태에서 똑같은 이름으로 가입하려하면 오류가 나야하지만 예전에 에러를 throw 처리했기 때문에 에러는 처리되고 500페이지만 뜬 것입니다.

만약 이 에러를 직접 사용자가 볼 수 있게 하기 위해서는 throw하지 않고 alert창을 띄워 사용자가 알 수 있게 해주는 것이 좋겠습니다.

 

정리를 해보겠습니다.

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

이렇게 members/new 로 와서 url에 직접 들어가는걸 Http에서 Get방식이라고 부릅니다.

그리고 이 GetMapping을 통해 return 되어 createMemberForm.html을 template에서 찾습니다.

뷰리졸버에 의해서 찾아진 이 html은 화면에 뿌려지게 됩니다.

그런데

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

해당 html파일을 보니 form으로 감싸져있습니다.

이 form은 값을 입력할 수 있는 html 태그라고 생각하시면 됩니다.

그리고 밑에 input type을 보시면 type = "text"라고 쓰면 텍스트 메시지를 쓸 수 있는 박스를 의미하고

id와 name이 중요한데, 이 name이 다른 클래스로 넘어갈 key가 됩니다.

그리고 placeholder는 음 안드로이드앱개발할 때 보시면 xml파일 수정할 때 hint와 같습니다.

텍스트 메세지박스 안에 어떤걸 입력해야 하는지 알려주는 용도라고 보시면 되겠습니다. (디폴트값)

그리고 이 name에 우리가 입력값을 입력하고 제출할 때 비로소 form의 action이 동작하는데요.

우리가 button을 클릭하면 이 form의 action이 /members/new니까 해당 사이트로 이동하고 method방식은 post. 그러니까 이 name값을 제출하겠다는 의미를 뜻합니다.

그럼 이렇게 넘어온 것은 MemberForm을 통해 객체가 되고 MemberController로 넘어갑니다.

Post방식과 Get방식에 대해 잘 이해해야 합니다.

Post방식은 form 같은 것에 넣어서 데이터를 전달할 때 사용합니다.

Get은 주로 음... 조회할 때 쓴다고 보면 좋습니다.

그래서 url은 똑같지만 Get이냐 Post냐에 따라서 전혀 다른 성격의 로직이 작성됩니다.

그러므로 회원가입 로직을 완성하기 위해선 PostMapping으로 작성을 해야하는데요.

여기서 재밌는 것이, 아까 작성했던 MemberForm을 통해 name에 값이 들어가서 GetName()과 SetName()메서드를 통해 name이 String으로 반환되어 튀어나옵니다.

그리고 memberService에 member를 join함으로써 비로소 name이 저장되고 회원가입이 완료되는 것입니다.

감사합니다.

728x90
반응형
Comments