BindProject
[Backend] Auth모듈 :사용자 등록 로직의 책임 분리와 유효성 검사 개선
dding-shark
2025. 6. 18. 22:03
728x90
사용자 등록 로직의 책임 분리와 유효성 검사 개선
1. 도입
사용자 등록(Sign-up)은 인증(Auth) 시스템의 핵심이다. 그러나 이 과정을 단순히 "사용자 저장"으로만 처리하면 곧 유지보수와 확장성에서 문제를 겪게 된다.
이 글에서는 다음과 같은 개선을 목표로 AuthService를 리팩토링한 과정을 설명한다:
- 유효성 검사를 Validator 인터페이스로 추상화
- 기본 권한 부여 로직을 별도의
UserRoleGrantService로 분리 - 비즈니스 검증 로직에 따라 커스텀 예외 처리
2. 설계 목표
- 단일 책임 원칙(SRP) 준수를 통한 서비스 계층의 응집도 향상
- 유효성 검사 로직 재사용성 확보 및 테스트 용이성 강화
- 역할(Role) 부여 로직을 별도 서비스로 분리하여 관리 편의성 확보
3. 설계 고려사항
- 유효성 검사 기준은 정책 변경에 따라 바뀔 수 있으므로, 조건들을 하드코딩하지 않고 인터페이스로 추상화
- 역할(Role) 부여 책임은 시스템의 권한 모델 변경과 밀접하므로
UserRoleGrantService로 별도 분리 - 실패 시점에서 적절한 예외를
AuthException으로 추상화하고, 오류 코드를AuthErrorCodeenum으로 관리
4. 구현 설명
유효성 검사 구조
public interface Validator<T> {
boolean validate(T target);
ValidatorType support();
}
ValidatorFactory는 Map<ValidatorType, Validator<?>>으로 주입받은 컴포넌트 중 support()로 타입을 판별해 동작한다.
emailValidator.validate("user@example.com") // true or false
사용자 등록 로직 (AuthService)
@Transactional
public void registerUser(SignUpRequest req) {
validateUser(req);
User user = User.builder()
.id(snowflake.nextId())
.email(req.getEmail())
.password(passwordEncoder.encode(req.getPassword()))
.provider(ProviderList.SYSTEM)
.createdAt(LocalDateTime.now())
.isEmailVerified(false)
.isDeleted(false)
.build();
userRepository.save(user);
userRoleGrantService.grantDefaultRole(user);
}
권한 부여 서비스 분리
public void grantRole(User user, User granter, UserRoleType role) {
ensureGranterHasPrivilege(granter); // 역할 체크
UserRole target = userRoleRepository.findByUser(user)
.orElseThrow(() -> new AuthException(USER_ROLE_NOT_FOUND));
target.setRole(role);
target.setGrantedAt(LocalDateTime.now());
target.setGrantedBy(granter.getId());
userRoleRepository.save(target);
}
5. 테스트 전략
AuthServiceTest에서는 회원가입 유효성 검증 및 중복 이메일, 잘못된 포맷 등 예외 상황 커버UserRoleGrantServiceTest에서는User,Guest사용자가 관리자 권한을 부여하려 할 때 예외 발생 여부 확인ValidatorFactoryTest를 통해 등록된 Validator가 잘 매핑되고 동작하는지 검증
6. 회고 및 확장 가능성
얻은 것
- 역할 부여 책임이 독립되면서 도메인 지식이 분산되지 않고 한 곳에 집중
- 새로운 역할 정책을 도입하거나 변경하더라도
UserRoleGrantService만 수정하면 된다 - 유효성 검증이
Validator패턴으로 추상화되어 테스트가 쉬워지고 확장성이 증가
앞으로의 방향
Validator를 AOP로 감싸거나, 애노테이션 기반으로 추상화 가능 (ex.@ValidPassword)- 권한 부여 시
ROLE_ADMIN이상의 인증이 필요한 정책으로 확장 가능 - 감사(Audit) 로그 저장 또는 이벤트 발행으로
grantRole()동작을 추적할 수 있도록 확장 가능
마무리
이러한 리팩토링을 통해 책임을 명확히 분리하고, 변경에 강한 구조로 전환할 수 있었다.
복잡해지는 인증 시스템에서 핵심은 결국 확장 가능한 구조와 명확한 책임 분리다.
728x90