[Lettrip] 회원가입 기능 구현 - form 로그인

subbni·2023년 4월 9일

Lettrip

목록 보기
4/7

비즈니스 로직

  • 사용자가 회원가입 하는 방법은 두 가지이다.
  1. 직접 이메일 & 비밀번호 등을 입력하여 form 회원가입 수행
  2. 소셜로그인을 통해 자동으로 회원가입 수행

오늘은 일단 1번에 해당하는 form 회원가입을 구현한다.

1번에 대한 더 자세한 로직은 다음과 같다.

  1. FE에서 사용자가 입력한 이메일로의 인증번호를 요청한다.
  2. BE는 해당 이메일의 중복 여부를 체크하고, 이메일로 인증번호를 보낸다.
    2-1. Redis를 사용하여 인증번호를 저장하고, expireTime은 3분으로 지정한다.
  3. FE에서 3분 내에 인증번호 검증을 요청한다.
  4. BE에서 인증번호를 검증한 뒤, 검증 결과를 FE로 보낸다.
  5. FE에서는 이메일이 인증되었음을 확인하고, 사용자가 작성한 회원가입 정보를 검증하여 해당 정보를 포함한 회원가입 요청을 BE로 보낸다.
  6. BE는 전달받은 정보를 바탕으로 회원 정보를 DB에 저장하고, 결과를 FE에 전달한다.

BE 로직

회원가입 요청이 들어왔다는 것은 이메일 인증코드 검증이 끝났다는 것이다.
따라서 단순히 DB에 저장하기만 하면 된다.

Dto

SignUpUser


public class SignUpUser {

    @Getter
    @Setter
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    public static class Request {
        @NotNull
        private String email;
        @NotNull
        @Size(min=5, max=20, message="password size must be 5 ~ 20")
        private String password;
        @NotNull
        @Size(min=2, max=20, message="name size must be 2 ~ 20")
        private String name;
        @NotNull
        @Size(min=2, max=20, message="nickname size must be 2 ~ 20")
        private String nickname;
        @NotNull
        private String imageUrl;
    }

    @Getter
    @Setter
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    public static class Response {
        private String email;
        private String name;
        private String nickname;
        private String imageUrl;

        public static Response fromEntity(User user) {
            return Response.builder()
                    .email(user.getEmail())
                    .name(user.getName())
                    .nickname(user.getNickname())
                    .imageUrl(user.getImageUrl())
                    .build();
        }
    }
}

UserRepository


public interface UserRepository extends JpaRepository<User,Long> {
    Optional<User> findByEmail(String email);
}
  • 중복 확인을 위해 Email로 User를 조회하는 메서드를 추가하였다.

AuthService

@Service
@RequiredArgsConstructor
public class AuthService {
    private final UserRepository userRepository;
    
	@Transactional
    public SignUpUser.Response createUser(SignUpUser.Request request) {
        validateCreateUserRequest(request);
        return SignUpUser.Response.fromEntity(createUserFromRequest(request));
    }

    private User createUserFromRequest(SignUpUser.Request request) {
        return userRepository.save(User.builder()
                .email(request.getEmail())
                .password(request.getPassword())
                .name(request.getName())
                .nickname(request.getNickname())
                .imageUrl(request.getImageUrl())
                .providerType(ProviderType.LOCAL)
                .build());
    }

    private void validateCreateUserRequest(SignUpUser.Request request) {
        userRepository.findByEmail(request.getEmail())
                .ifPresent(user->{
                    throw new LettripException(LettripErrorCode.DUPLICATED_EMAIL);
                });
    }

}
  • validateCreateUserRequest : 중복된 Email이 존재하는지 확인한다.
  • createUserFromRequest : request를 바탕으로 user를 만들어 repository에 저장하고 반환한다.

AuthController

@RequiredArgsConstructor
@RestController
@RequestMapping("/api")
public class AuthController {
    private final AuthService authService;

    @PostMapping("/sign-up")
    public SignUpUser.Response signUp(
            @Valid @RequestBody SignUpUser.Request request
    ) {
        return authService.createUser(request);
    }
}

Test

1.회원가입 성공 시나리오

  • 성공적으로 response가 오는 것을 확인

DB 확인

  • 성공적으로 회원 정보가 DB에 저장되었음을 확인

2. 중복된 이메일 시나리오

  • (사실 이메일 인증코드를 검증하는 부분에서 이미 이메일 중복은 검증되기는 하지만 ..)
  • 중복된 이메일로 회원가입을 요청할 경우 error코드와 메세지를 보낸다.

3. 유효성 검증 실패 시나리오

  • log를 보면 name과 nickname의 size가 2~20여야 한다는 것을 알려주고 있다.

  • http response에서도 error 코드와 메세지를 확인할 수 있다.


📌 추가해야하는 것

  • passwordEncoder를 사용하여 비밀번호를 암호화하여 DB에 저장하기
profile
개발콩나물

0개의 댓글