Spring 7기 프로젝트/일정관리 프로젝트
Spring Container & Bean 등록부터 Validation까지
JuNo_12
2025. 5. 14. 17:10
Spring Container 란?
- Spring 애플리케이션의 객체 생명주기를 관리하고, 의존성 주입(Dependency Injection)을 수행하는 컨테이너.
- Spring이 관리하는 객체를 Bean이라 부른다.
Bean 등록 방법
- Component Scan + Component 계열 애너테이션
- 자동 등록 방식
- @Component가 핵심이며, 다음 애너테이션도 포함된다. :
- @Controller: 웹 요청 처리
- @Service: 비즈니스 로직
- @Repository: 데이터 접근 계층 (예외 변환 포함)
- 수동 등록 (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 | 숫자 최소/최대값 지정 |
| 이메일 형식 | |
| @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로 관리 가능 |