BindProject

[Backend] AUTH모듈 : 초기 세팅

dding-shark 2025. 6. 18. 21:02
728x90

도입

유저 회원가입 기능을 도입하면서, 흔히 간과되는 입력값 유효성 검증을 시스템적으로 구조화할 필요성을 느꼈다.
예를 들어 이메일 형식이 유효한지, 비밀번호가 보안 정책에 맞는지를 단순 if-else 로직으로 처리하기 시작하면, 곧 유지보수 지옥이 열리기 때문이다.

이번 포스트에서는 다음 내용을 중심으로 회원가입과 유효성 검증을 어떻게 모듈화했는지를 공유한다.


설계 목표

  1. 확장 가능하고 테스트 가능한 유효성 검증 구조
  2. 비즈니스 로직과 검증 로직의 명확한 분리
  3. 검증 실패 시 도메인 특화 예외 처리
  4. DDD 기반 도메인 모델 구성 (User, Provider 등)

설계 고려사항

항목 고려 내용

입력 검증 이메일/비밀번호 형식 규칙을 Validator로 위임
중복 체크 이메일 중복은 DB에 위임하고 예외로 처리
예외 설계 CustomErrorCode 기반으로 HTTP 상태값 매핑
책임 분리 검증은 ValidatorFactory, 비즈니스는 AuthService

구현 설명

1. ValidatorType 기반으로 검증기 식별

Validator<String> emailValidator = validatorFactory.getValidator(ValidatorType.EMAIL);
if (!emailValidator.validate(req.getEmail())) {
    throw new AuthException(AuthErrorCode.INVALID_EMAIL);
}

2. 비밀번호도 동일하게 처리

Validator<String> passwordValidator = validatorFactory.getValidator(ValidatorType.PASSWORD);
if (!passwordValidator.validate(req.getPassword())) {
    throw new AuthException(AuthErrorCode.INVALID_PASSWORD);
}

3. 유저 저장 처리

User user = User.builder()
        .id(snowflake.nextId())
        .email(req.getEmail())
        .password(req.getPassword())
        .provider(ProviderList.SYSTEM)
        .createdAt(LocalDateTime.now())
        .isEmailVerified(false)
        .isDeleted(false)
        .build();
userRepository.save(user);

검증기에서 검증이 실패하면 바로 Exception을 던지며 흐름을 끊는다.


회고 및 확장 가능성

회고

  • 검증기를 enum 기반으로 등록해두니 기억 의존도가 낮아졌고,
  • 테스트가 독립적이라서 단위 테스트 작성도 편리했다.
  • 다만, 현재는 검증기 로직이 동기적으로 동작하기 때문에 성능 문제는 없다.
    나중에 외부 API를 통한 유효성 체크(예: 이메일 실존 확인)가 들어오면 비동기 설계로 바꿔야 할 수 있다.
  • 엔티티 설계는 다음 글에 작성 하도록 하겠다

확장 아이디어

  • 이메일 인증 로직 추가 시, 현재 구조 그대로 EmailVerificationService로 확장 가능.
  • ValidatorFactory도 Map<ValidatorType, Validator<?>> 대신 스프링 빈 주입으로 변경해 유연하게 개선 가능.
  • SignUpRequest의 필드가 늘어나도 서비스 로직은 깔끔하게 유지됨.

728x90