반응형
요구사항
- 직접 회원가입
- 소셜 로그인
- 기존 가입된 회원이면 해당 이메일을 이용해 로그인
- 기존 가입된 회원이 아니면, 소셜 로그인의 정보를 이용한 간편 회원가입
회원 가입 기능 구현
- GET 방식 : 회원가입 페이지
- POST 방식 : 회원가입 <form>데이터를 전달해 DB에 추가
- GET 방식 화면 출력 -> POST 방식으로 데이터 전달 -> 목록 페이지로 이동
회원 가입 구현 순서
- DTO
- 컨트롤러
- 화면
- 서비스
시큐리티의 DTO와 회원가입 전용 DTO
- 시큐리티가 사용하는 DTO : User UserDetails를 구현한 User클래스를 상속하는 DTO
- 회원가입 전용 DTO : MemberJoinDTO 작성
1. 회원가입 전용 DTO인 MemberJoinDTO 작성
package org.zerock.b01.dto;
import lombok.Data;
@Data
public class MemberJoinDTO {
private String mid;
private String mpw;
private String email;
private boolean del;
private boolean social;
}
2. 회원가입 컨트롤러 작성
//GET 방식으로 회원가입 페이지
@GetMapping("/join")
public void joinGET(){
log.info("join get...");
}
//POST 방식으로 회원가입 form 전송
@PostMapping("/join")
public String joinPOST(MemberJoinDTO memberJoinDTO){
log.info("join post...");
log.info(memberJoinDTO);
return "redirect:/board/list";
}
3. 회원가입 화면 작성
-컨트롤러와 서비스의 파라미터 수집 확인과 이동
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/basic.html}">
<head>
<title>Member Join Page</title>
</head>
<div layout:fragment="content">
<div class="row mt-3">
<div class="col">
<div class="card">
<div class="card-header">
JOIN
</div>
<div class="card-body">
<form id="registerForm" action="/member/join" method="post">
<div class="input-group mb-3">
<span class="input-group-text">MID</span>
<input type="text" name="mid" class="form-control">
</div>
<div class="input-group mb-3">
<span class="input-group-text">MPW</span>
<input type="password" name="mpw" class="form-control">
</div>
<div class="input-group mb-3">
<span class="input-group-text">EMAIL</span>
<input type="email" name="email" class="form-control">
</div>
<div class="my-4">
<div class="float-end">
<button type="submit" class="btn btn-primary submitBtn">Submit</button>
<button type="reset" class="btn btn-secondary">Reset</button>
</div>
</div>
</form>
</div><!--end card body-->
</div><!--end card-->
</div><!-- end col-->
</div><!-- end row-->
</div>
<script layout:fragment="script" th:inline="javascript">
</script>
- '/member/join'을 호출해 화면 출력
-화면 출력-> 입력한 폼을 POST 방식으로 전달 -> '/board/list'로 이동
4. 회원 가입 서비스 계층 처리
-멤버 서비스에서 MidExistException 예외를 static 클래스로 선언해서 사용
package org.zerock.b01.service;
import org.zerock.b01.dto.MemberJoinDTO;
public interface MemberService {
static class MidExistException extends Exception{
}
void join(MemberJoinDTO memberJoinDTO)throws MidExistException;
}
-MemberServiceImpl에서는 mid가 존재할 경우 MidExistException 발생하도록 작성
-정상적으로 회원가입 될 경우, PasswordEncoder를 이용해 입력된 패스워드를 인코딩
서비스 계층 설정
- MemberjoinDTO -> Member
- Password 인코딩
- 권한 설정 (유저, 관리자)
- 아이디 중복체크
: Repository에서 제공하는 existsById()를 이용해 mid 값이 유일한지 체크
package org.zerock.b01.service;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.modelmapper.ModelMapper;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.ui.ModelMap;
import org.zerock.b01.domain.Member;
import org.zerock.b01.domain.MemberRole;
import org.zerock.b01.dto.MemberJoinDTO;
import org.zerock.b01.repository.MemberRepository;
@Log4j2
@Service
@RequiredArgsConstructor
public class MemberServiceImpl implements MemberService{
//의존성 주입
private final ModelMapper modelMapper;
private final MemberRepository memberRepository;
private final PasswordEncoder passwordEncoder;
@Override
public void join(MemberJoinDTO memberJoinDTO) throws MidExistException{
String mid = memberJoinDTO.getMid();
//리포지토리에서 아이디 중복체크를 위해, ID 존재여부 체크
boolean exist = memberRepository.existsById(mid);
//중복된 아이디 존재시 예외처리
if(exist){
throw new MidExistException();
}
//회원 전용 DTO -> Memer 도메인으로 변환
Member member=modelMapper.map(memberJoinDTO, Member.class);
//pw는 인코딩 필요
member.changePassword(passwordEncoder.encode(memberJoinDTO.getMpw()));
//회원 권한 설정
member.addRole(MemberRole.USER);
log.info("---");
log.info(member);
log.info(member.getRoleSet());
memberRepository.save(member);
}
}
5. 멤버 컨트롤러 변경
-컨트롤러에서 아이디 중복 예외 발생시 다시 회원가입 페이지로 이동
변경 전, 컨트롤러
package org.zerock.b01.controller;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.zerock.b01.dto.MemberJoinDTO;
@Controller
@RequestMapping("/member")
@Log4j2
@RequiredArgsConstructor
public class MemberController {
@GetMapping("/login")
//로그인 과정에서 문제 발생 시, 로그아웃 시 사용하기 위한 파라미터
public void loginGET(String error, String logout){
log.info("login get...");
log.info("logout : "+logout);
if(logout!=null){
log.info("user logout...");
}
}
//GET 방식으로 회원가입 페이지
@GetMapping("/join")
public void joinGET(){
log.info("join get...");
}
//POST 방식으로 회원가입 form 전송
@PostMapping("/join")
public String joinPOST(MemberJoinDTO memberJoinDTO){
log.info("join post...");
log.info(memberJoinDTO);
return "redirect:/board/list";
}
}
변경 후, 중복발생시 회원가입 페이지로 이동 처리
package org.zerock.b01.controller;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.zerock.b01.dto.MemberJoinDTO;
import org.zerock.b01.service.MemberService;
import org.zerock.b01.service.MemberServiceImpl;
@Controller
@RequestMapping("/member")
@Log4j2
@RequiredArgsConstructor
public class MemberController {
//의존성 주입
private final MemberService memberService;
@GetMapping("/login")
//로그인 과정에서 문제 발생 시, 로그아웃 시 사용하기 위한 파라미터
public void loginGET(String error, String logout){
log.info("login get...");
log.info("logout : "+logout);
if(logout!=null){
log.info("user logout...");
}
}
//GET 방식으로 회원가입 페이지
@GetMapping("/join")
public void joinGET(){
log.info("join get...");
}
//POST 방식으로 회원가입 form 전송
@PostMapping("/join")
public String joinPOST(MemberJoinDTO memberJoinDTO, RedirectAttributes redirectAttributes){
log.info("join post...");
log.info(memberJoinDTO);
try{
//예외처리를 설정한 메서드의 경우, try{}catch(){}
memberService.join(memberJoinDTO);
}catch (MemberService.MidExistException e){
redirectAttributes.addFlashAttribute("error", "mid");
return "redirect:/member/join";
}
//결과라는 이름으로 성공 메시지 전송
redirectAttributes.addFlashAttribute("result", "success");
//return "redirect:/board/list";
return "redirect:/board/login"; //회원 가입 후 로그인
}
}
6. join.html에서 'error'로 전달된 데이터를 받으면 이를 출력하도록 처리
<script layout:fragment="script" th:inline="javascript">
const error = [[${error}]]
if(error && error === 'mid'){
alert("동일한 MID를 가진 계정이 존재합니다.")
}
</script>
반응형