프로젝트

스프링 부트 프로젝트 (회원 가입)

이제하네 2024. 5. 29. 17:54

Controller 부분

@Slf4j
@RequiredArgsConstructor
@CrossOrigin
@Controller
@RequestMapping("/api")
public class MemberController {

    private final MemberService memberService;

    @PostMapping("/member/join")
    @ResponseBody
    public ResponseEntity<? super MemberDto> saveMember(@RequestBody @Valid MemberDto memberDto){
            ResponseEntity<? super MemberDto> response = memberService.saveMember(memberDto);
            return response;
    }
}

@Vaild 는 DTO 의 유효성 검사를 위해 작성 
유효성이 통과가 안되면 에러 발생

DTO 부분

@NoArgsConstructor
@Getter
public class MemberDto extends ResponseDto {

    @NotBlank(message = "이름은 필수 입력 값이다.")
    private String name; // 이름

    @NotBlank(message = "이메일은 필수 입력 값이다.")
    @Email(message = "이메일 형식으로 입력해주세요.")
    private String email; // 이메일

    @NotBlank(message = "비밀번호는 필수 입력 값이다.")
    @Pattern(regexp="(?=.*[0-9])(?=.*[a-z])(?=.*\\W)(?=\\S+$).{8,20}",
            message = "비밀번호는 영문 소문자와 숫자, 특수기호가 적어도 1개 이상씩 포함된 8자 ~ 20자의 비밀번호여야 합니다.")
    private String password; // 비밀번호

    @NotBlank(message = "닉네임은 필수 입력 값이다.")
    private String nickname; // 닉네임

    private String gender; // 성별

    @Pattern(regexp="(^\\d{10,11}$)",
            message = "휴대폰 번호는 -를 제외하고 입력해주세요")
    private String phoneNumber; // 휴대폰 번호

    @Builder
    public MemberDto(String name, String email, String password, String nickname, String gender , String phoneNumber) {
        this.name = name;
        this.email = email;
        this.password = password;
        this.nickname = nickname;
        this.gender = gender;
        this.phoneNumber = phoneNumber;
    }

}

 

@Pattern 을 사용하여 정규식과 메시지 입력
@NotBlank 를 사용하여 공백이나 빈 문자열로 설정되는것을 방지

Service 부분

public interface MemberService  {
    ResponseEntity<ResponseDto> saveMember(MemberDto memberDto);
}

 

ServiceImpl 부분

@RequiredArgsConstructor
@Transactional
@Service
@Slf4j
public class MemberServiceImpl implements MemberService {

    private final MemberRepository memberRepository;

    @Override
    public  ResponseEntity<ResponseDto> saveMember(MemberDto memberDto) {
         try {
             Member findMember = memberRepository.findByEmail(memberDto.getEmail());
             if (findMember != null) {
                 log.info("이미 가입된 회원입니다");
                 return ResponseDto.duplicateEmail();
             }
             int count = memberRepository.checkNickname(memberDto.getNickname());
             if (count != 0) {
                 log.info("이미 가입된 닉네임입니다");
                 return ResponseDto.duplicateNickname();
             }

             Member member = Member.createMember(memberDto , passwordEncoder);

             memberRepository.saveMember(member.getName() , member.getEmail() , member.getPassword() ,
                     member.getNickname() , member.getPhoneNumber() , member.getSignType());

         }catch (Exception e){
             e.printStackTrace();
             return MemberDto.databaseError();
         }
        return ResponseDto.success();
    }
}

 

Domain 부분

@NoArgsConstructor
@Getter
@Table(name = "member")
@Entity
@Data
public class Member {

    private String name; // 이름

    @Id
    private String email; // 이메일

    private String password; // 비밀번호

    private String nickname; // 닉네임

    private String phoneNumber; // 휴대폰 번호

    private Date createDate; // 생성일자

    private Date updateDate; // 변경 일자

    private String useYn; // default Y -> 사용중   N-> 탈퇴


    private String role;  // 관리자 ADM , 사용자 USER

    private String signType; // 회원 가입할때 타입  웹페이지 WEB , 카카오 KAKAO , 네이버 NAVER

    @Builder
    public Member(String name, String email, String password, String nickname,
                  String phoneNumber, Date createDate, Date updateDate, String useYn, String role , String signType) {
        this.name = name;
        this.email = email;
        this.password = password;
        this.nickname = nickname;
        this.phoneNumber = phoneNumber;
        this.createDate = createDate;
        this.updateDate = updateDate;
        this.useYn = useYn;
        this.role = role;
        this.signType = signType;
    }

    public static Member createMember(MemberDto memberDto, PasswordEncoder passwordEncoder) {
        Member member = Member.builder()
                .name(memberDto.getName())
                .email(memberDto.getEmail())
                .phoneNumber(memberDto.getPhoneNumber())
                .password(passwordEncoder.encode(memberDto.getPassword()))      // 암호화 처리
                .nickname(memberDto.getNickname())
                .signType("WEB")
                .build();

        return member;
    }
}

 

Repository 부분

public interface MemberRepository extends JpaRepository<Member, Long> {

    @Transactional
    @Modifying
    @Query(value = "INSERT INTO member " +
                   "(name, email, password,nickname,phone_number, create_date, update_date, use_yn ,role , sign_type) " +
                   "VALUES " +
                   "(:name, :email, :password, :nickname, :phoneNumber, NOW(), NOW(), 'Y' , 'USER' , :signType)", nativeQuery = true)
    void saveMember(@Param("name") String name, @Param("email") String email,
                    @Param("password") String password, @Param("nickname") String nickname,
                    @Param("phoneNumber") String phoneNumber, @Param("signType") String signType); // 회원 가입

    Member findByEmail(String mbrEmail);       // 중복 회원 검사

}

 

 

 

 

==============================

ResponseCode 부분

public interface ResponseCode {

    String SUCCESS = "SU";  //성공

    String VALIDATION_FAIL = "VF"; // 유효성 실패
    String DUPLICATE_EMAIL = "DE"; // 이메일 중복
    String DUPLICATE_NICKNAME = "DN"; // 닉네임 중복

    String SIGN_IN_FAIL = "SF"; // 로그인 실패

    String CERTIFICATION_FAIL = "CF"; // 인증 실패

    String DATABASE_ERROR = "DBE"; // 데이터베이스 오류
}

 

ResponseMessage 부분

public interface ResponseMessage {

    String SUCCESS = "Success.";  // 성공

    String VALIDATION_FAIL = "Validation failed."; // 유효성 실패
    String DUPLICATE_EMAIL = "Duplicate Email."; // 이메일 중복
    String DUPLICATE_NICKNAME = "Duplicate Nickname."; // 닉네임 중복

    String SIGN_IN_FAIL = "Login information mismatch."; // 로그인 실패

    String CERTIFICATION_FAIL = "Certification failed."; // 인증 실패

    String DATABASE_ERROR = "Datebase error."; // 데이터베이스 오류
}

 

ResponseDto 부분

@AllArgsConstructor
@Getter
public class ResponseDto {

    private String code;
    private String message;

    public ResponseDto(){
        this.code = ResponseCode.SUCCESS;
        this.message = ResponseMessage.SUCCESS;
    }

    public static ResponseEntity<ResponseDto> databaseError(){
        ResponseDto responseBody = new ResponseDto(ResponseCode.DATABASE_ERROR , ResponseMessage.DATABASE_ERROR);

        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(responseBody);
    }

    public static ResponseEntity<ResponseDto> validationFail(){
        ResponseDto responseBody = new ResponseDto(ResponseCode.VALIDATION_FAIL , ResponseMessage.VALIDATION_FAIL);

        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(responseBody);
    }

    public static ResponseEntity<ResponseDto> success () {
        ResponseDto responseBody = new ResponseDto(ResponseCode.SUCCESS , ResponseMessage.SUCCESS);
        return ResponseEntity.status(HttpStatus.OK).body(responseBody);
    }

    public static ResponseEntity<ResponseDto> duplicateEmail () {
        ResponseDto responseBody = new ResponseDto(ResponseCode.DUPLICATE_EMAIL , ResponseMessage.DUPLICATE_EMAIL);
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(responseBody);
    }

    public static ResponseEntity<ResponseDto> duplicateNickname () {
        ResponseDto responseBody = new ResponseDto(ResponseCode.DUPLICATE_NICKNAME , ResponseMessage.DUPLICATE_NICKNAME);
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(responseBody);
    }

    public static ResponseEntity<ResponseDto> certificationFail () {
        ResponseDto responseBody = new ResponseDto(ResponseCode.CERTIFICATION_FAIL , ResponseMessage.CERTIFICATION_FAIL);
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(responseBody);
    }
}

 

포스트맨을 사용하여 결과

성공할 경우

 

이메일 중복일 경우

닉네임이 중복일 경우 

'프로젝트' 카테고리의 다른 글

스프링 부트 프로젝트(소셜로그인)  (0) 2024.06.16
스프링 부트 프로젝트(로그인)  (0) 2024.06.03