Spring 7기 프로젝트/일정관리 프로젝트

Spring Container & Bean 등록부터 Validation까지

JuNo_12 2025. 5. 14. 17:10

Spring Container 란?

  • Spring 애플리케이션의 객체 생명주기를 관리하고, 의존성 주입(Dependency Injection)을 수행하는 컨테이너.
  • Spring이 관리하는 객체를 Bean이라 부른다.

Bean 등록 방법

  1. Component Scan + Component 계열 애너테이션
    • 자동 등록 방식
    • @Component가 핵심이며, 다음 애너테이션도 포함된다. :
      • @Controller: 웹 요청 처리
      • @Service: 비즈니스 로직
      • @Repository: 데이터 접근 계층 (예외 변환 포함)
  2. 수동 등록 (Java Config)
@Configuration
public class AppConfig {
    @Bean
    public UserService userService() {
        return new UserService();
    }
}

의존성 주입 방식

생성자 주입 (권장 방식)

  • 필드에 final 선언 → 컴파일 시점에 누락 방지
  • 테스트, 불변 객체 설계에 유리
  • Lombok의 @RequiredArgsConstructor 사용 시 자동 생성된다.
@RequiredArgsConstructor
@Service
public class UserService {
    private final UserRepository userRepository;
}

Bean Validation (입력값 검증)

Gradle 의존성 추가

implementation 'org.springframework.boot:spring-boot-starter-validation'

자주 사용하는 Validation 애너테이션

애너테이션 설명
@NotBlank null, "", " " 모두 허용 안 함 (문자열만)
@NotEmpty null, "" 허용 안 함 (문자열, Collection 등)
@NotNull null 만 허용 안 함 (모든 타입 사용 가능)
@Size(min, max) 문자열/컬렉션 크기 제한
@Min, @Max 숫자 최소/최대값 지정
@Email 이메일 형식
@Pattern(regexp = "...") 정규식 검사

@Valid vs @Validated

항목 @Valid  @Validated
제공 JSR-380(Java EE) 가 제공 Spring 이 제공
groups 지원  X  O
동작 대상 Java Bean Java Bean + 그룹 조건
용도 단순 검증 그룹 검증, 조건별 검증

@ModelAttribute vs @RequestBody

구분 @ModelAttribute  @RequestBody
바인딩 방식 필드 단위 바인딩 객체 단위 바인딩 (JSON → Object)
실패 시 일부 실패해도 컨트롤러 진입 파싱 실패 시 컨트롤러 진입 X
유효성 검사 위치 필드 단위 Validation 동작 messageConverter 통과 후 객체 검증

 

@ModelAttribute

  • 각각의 필드 단위로 바인딩한다.
  • 특정 필드 바인딩이 실패하여도 나머지 필드는 정상적으로 검증처리 가능
  • 따라서 컨트롤러를 호출, 나머지 필드 validation 적용

@RequestBody

  • 필드별로 적용되는 것이 아니라 객체 단위로 적용된다.
  • messageconveter가 정상적으로 동작하여 object로 변환하여야 validation이 동작한다.
  • 특정필드 변환 실패하면 컨트롤러 미호출, Validation 미적용

BindingResult의 역할

  • @Valid 또는 @Validated와 함께 사용
  • 유효성 실패 시 예외 발생을 막고, 에러 내용을 직접 처리할 수 있게 해준다.
@PostMapping("/example")
public Object save(@Validated @RequestBody ExampleRequestDto dto, BindingResult bindingResult) {
    if (bindingResult.hasErrors()) {
        return bindingResult.getAllErrors(); // JSON 형태로 반환
    }
    return "OK";
}

DTO 분리 vs Groups

DTO 분리 (권장)

  • 용도별로 입력 DTO를 따로 만들어 관리
  • 코드 가독성, 유지보수성 ↑

Groups

  • 하나의 DTO에서 상황별로 다른 유효성 조건을 적용
public interface Create {}
public interface Update {}

@NotBlank(groups = Create.class)
private String name;
@PostMapping("/user")
public void create(@Validated(Create.class) @RequestBody UserDto dto) {}

최종 정리

개념 핵심 내용
Bean 등록 @Component, @Service, @Repository로 등록 가능
DI 방식 생성자 주입 + @RequiredArgsConstructor 권장
Validation @Valid, @Validated, Bean Validation 의존성 필요
바인딩 방식 @ModelAttribute는 필드 단위, @RequestBody는 객체 단위
예외 처리 BindingResult로 수동 처리 가능, @ControllerAdvice로 전역 처리 가능
DTO 설계 상황별로 분리하거나 groups로 관리 가능