회원가입 프로세스의 기본 골격을 구현했습니다. Spring MVC의 핵심 컴포넌트인 Controller, Service, DTO(Data Transfer Object)를 사용하여 역할을 분리하고 기능을 구현했습니다.
AuthController: 클라이언트의 HTTP 요청(@PostMapping("/signup"))을 받아들이는 진입점입니다. @RequestBody로 받은 JSON 데이터를 SignUpRequest DTO로 변환하고, @Valid를 통해 유효성 검사를 수행한 뒤 UserService에 처리를 위임합니다.
UserService: 실제 비즈니스 로직(회원 정보 저장, 중복 확인 등)을 처리하는 핵심 계층입니다.
SignUpRequest (DTO): 클라이언트로부터 받은 회원가입 데이터를 담는 객체입니다. @NotBlank, @Email 등의 유효성 검증 어노테이션을 적용하여, Controller 단에서 데이터의 유효성을 1차적으로 보장합니다.
PasswordEncodermatches())하는 방식으로 인증을 수행합니다.BCryptPasswordEncoder를 Bean으로 등록하여 프로젝트 전반에서 주입받아 사용하도록 설정했습니다. BCrypt는 현재 산업 표준으로 널리 사용되는 강력한 해시 알고리즘입니다.// PasswordEncoderConfig.java - Bean 등록
@Configuration
public class PasswordEncoderConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
// UserService.java - 회원가입 시 암호화 적용
User user = User.builder()
.username(request.getUsername())
.password(passwordEncoder.encode(request.getPassword())) // 비밀번호를 암호화하여 저장
.email(request.getEmail())
.build();
userRepository.save(user);
LoginRequest (DTO): 로그인에 필요한 사용자 이름/이메일과 비밀번호를 담는 객체입니다.UserService의 authenticate 메서드:PasswordEncoder.matches() 메서드를 사용하여 클라이언트가 보낸 평문 비밀번호와 DB에 저장된 암호화된 비밀번호를 비교합니다.AuthController의 login 메서드: LoginRequest를 받아 UserService에 인증을 위임하고, 성공 시 ApiResponse에 담아 응답합니다.ApiResponseApiResponse<T>를 도입했습니다. 이를 통해 성공/실패 여부, 메시지, 데이터를 표준화된 구조로 전달할 수 있습니다.| 필드 | 설명 | 예시 |
|---|---|---|
code | 응답 상태를 나타내는 코드 (e.g., 200) | 200 |
message | 응답에 대한 설명 메시지 | "회원가입이 성공적으로 완료되었습니다." |
data | 실제 응답 데이터 (Generic Type T) | UserResponse 객체 또는 null |
GlobalExceptionHandler@RestControllerAdvice 어노테이션을 사용한 GlobalExceptionHandler를 구현했습니다. 이를 통해 Controller마다 중복된 try-catch 블록을 작성할 필요가 없어지고 코드의 가독성과 유지보수성이 향상됩니다.BusinessException: 비즈니스 로직 상의 예외 상황(e.g., 사용자명 중복, 이메일 중복)을 나타내기 위한 커스텀 예외 클래스입니다.ErrorCode (Enum): 애플리케이션에서 발생할 수 있는 모든 에러 상황을 HttpStatus, 코드, 메시지와 함께 열거형으로 정의합니다. 이를 통해 에러 관리가 체계적으로 이루어집니다.ErrorResponse (DTO): 클라이언트에게 반환할 에러 응답의 형식을 정의한 DTO입니다.@Valid) 예외 처리@Valid 어노테이션을 통과하지 못하면 MethodArgumentNotValidException이 발생합니다. GlobalExceptionHandler에서 이 예외를 처리하여, 어떤 필드가 어떤 규칙을 위반했는지 상세한 정보를 담은 ValidationError 객체를 ErrorResponse에 포함시켜 응답합니다.@JsonInclude(JsonInclude.Include.NON_NULL): 응답 DTO를 JSON으로 변환할 때, 값이 null인 필드는 결과에서 제외시키는 어노테이션입니다. 이를 통해 불필요한 정보 없이 깔끔한 응답을 보낼 수 있습니다.// GlobalExceptionHandler.java 예시
@RestControllerAdvice
public class GlobalExceptionHandler {
// 비즈니스 예외 처리
@ExceptionHandler(BusinessException.class)
protected ResponseEntity<ErrorResponse> handleBusinessException(BusinessException e) {
// ... ErrorCode를 기반으로 ErrorResponse 생성 및 반환
}
// 유효성 검증 예외 처리
@ExceptionHandler(MethodArgumentNotValidException.class)
protected ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
// ... BindingResult에서 필드별 에러 정보를 추출하여 ErrorResponse 생성 및 반환
}
}
PasswordEncoder를 도입하여 사용자 비밀번호를 안전하게 암호화했습니다.ApiResponse 클래스를 통해 모든 API 응답을 표준화하여 일관성을 확보했습니다.@RestControllerAdvice를 사용한 GlobalExceptionHandler를 구현하여 예외 처리를 중앙 집중화했습니다.BusinessException과 ErrorCode Enum을 활용하여 비즈니스 예외를 체계적으로 관리하고, @Valid 예외 처리로 사용자에게 친절한 에러 메시지를 제공할 수 있게 되었습니다.