스프링은 EJB의 무겁고 복잡한 플랫폼에서 벗어나 POJO기반의 경량화된 개발 환경을 제공하는 오픈소스 프레임워크
좋은 객체 지향 설계의 5가지 원칙(SOLID)
SOLID
-SRP : 단일 책임원칙(Single Responsibility Principle)
한클래스는 하나의 책임만 가져야 한다.
중요한 기준은 변경! 변경이 있을때 파급효과 적으면 단일 책침 원칙을 잘 따른것!
-OCP: 개방-폐쇄의 원칙(Open/Closed Principle)
소프트웨어 요소는 확장에는 열려있고 변경에는 닫혀있어야 한다.
다형성 활용!
-LSP: 리스코프 치환 원칙(Liskov Substitution Principle)
프로그램의 객체는 프로그램의 정확성을 깨지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다
-ISP: 인터페이스 분리 원칙(Interface Segregation Principle)
특정 클라이언트를 위한 여러개의 인터페이스가 범용 인터페이스 하나보다 낫다
인터페이스가 명확해지고, 대체 가능성이 높아진다
-DIP: 의존관계 역전 원칙(Dependency Inversion Principle)
구현 클래스에 의존하지 말고, 인터페이스에 의존하라는 뜻
역할에 의존하게 해야한다
-----------------------------------------------------------------------------------
Bean Validation은 특정한 구현체가 아니라 Bean Validation 2.0이라는 기술 표준이며 검증 애노테이션과 여러 인터페이스의 모음이다.
Bean Validation 의존관계 추가
build.gradle
implementation 'org.springframework.boot:spring-boot-starter-validation'
spring-boot-starter-validation을 의존관계를 추가하면 라이브러리가 추가된다.
| @NotBlank | 빈값 + 공백만 있는 경우를 허용하지 않는다. |
| @NotNull | null을 허용하지 않는다. |
| @Range(min=?, max=?) | ?에 숫자를 넣으며 범위 안의 값이어야 한다. |
| @Max(?) | 최대 ? 까지만 허용된다. |
스프링 부트는 spring-boot-starter-validation 라이브러리를 넣으면 자동으로 Bean Validator를 인지하고 스프링에 통합
스프링 부트는 자동으로 글로벌 Validator로 등록한다.
LocalValidatorFactoryBean 을 글로벌 Validator로 등록한다. 이 Validator는 @NotNull 같은 애노테이션을 보고 검증을 수행한다. 이렇게 글로벌 Validator가 적용되어 있기 때문에, @Valid , @Validated 만 적용하면 된다.
검증 오류가 발생하면, FieldError , ObjectError 를 생성해서 BindingResult 에 담아준다.
하지만 직접 글로벌 Validator를 직접 등록하면 스프링 부트는 Bean Validator를 글로벌 Validator 로 등록하지 않는다.
@Bean Validation은 등록할때와 수정할때 요구사항이 다를수있어 이를 해결하기 위해 groups, Form 전송 객체 분리 를 사용한다.
BeanValidation groups 기능
인터페이스를 생성하고 어노테이션에 groups를 추가한다.
groups는 실무에서 잘 사용하지 않는다고 한다.
등록시 폼에서 전달하는 데이터가 Item 도메인 객체와 딱 맞지 않기 때문이다.
SaveCheck 인터페이스
package hello.itemservice.domain.item;
public interface SaveCheck {
}
groups 사용
@NotBlank(groups = {SaveCheck.class})
private String itemName;
Controller에 SaveCheck Groups적용
@PostMapping("/add")
public String addItemV2(@Validated(SaveCheck.class) @ModelAttribute Item item,
BindingResult bindingResult, RedirectAttributes redirectAttributes) {
//...
}
Form 전송 객체 분리
폼데이터 잔달에 Item 도메인 객체 사용
HTML Form -> Item -> Controller -> Item -> Repository
장점: Item 도메인 객체를 컨트롤러, 리포지토리 까지 직접 전달해서 중간에 Item을 만드는 과정이 없어서 간단하다.
단점: 간단한 경우에만 적용할 수 있다. 수정시 검증이 중복될 수 있고, groups를 사용해야 한다.
폼 데이터 전달을 위한 별도의 객체 사용
HTML Form -> ItemSaveForm -> Controller -> Item 생성 -> Repository
장점: 전송하는 폼 데이터가 복잡해도 거기에 맞춘 별도의 폼 객체를 사용해서 데이터를 전달 받을 수 있다. 보통 등록과, 수정용으로 별도의 폼 객체를 만들기 때문에 검증이 중복되지 않는다.
단점: 폼 데이터를 기반으로 컨트롤러에서 Item 객체를 생성하는 변환 과정이 추가된다.
저장과 수정의 폼을 분리해서 사용한다.
Controller 예시
public String addItem(@Validated @ModelAttribute("item") ItemSaveForm form,
BindingResult bindingResult, RedirectAttributes redirectAttributes) {
//...
}
ItemSaveForm 를 받아오고 @ModelAttribute("item") 를 통해 item이란 명으로 바꿔준다.
@ModelAttribute vs @RequestBody
HTTP 요청 파리미터를 처리하는 @ModelAttribute 는 각각의 필드 단위로 세밀하게 적용도어서 특정 필드에 타입이 맞지 않는 오류가 발생해도 나머지 필드는 정상 처리할 수 있다.
HttpMessageConverter는 @ModelAttribute와 다르게 각각의 필드 단위로 적용되는 것이 아니라 전체 객체 단위로 적용된다.
@ModelAttribute 는 필드 단위로 정교하게 바인딩이 적용된다. 특정 필드가 바인딩 되지 않아도 나머지 필드는 정상 바인딩 되고, Validator를 사용한 검증도 적용할 수 있다.
@RequestBody 는 HttpMessageConverter 단계에서 JSON 데이터를 객체로 변경하지 못하면 이후 단계 자체가 진행되지 않고 예외가 발생한다. 컨트롤러도 호출되지 않고, Validator도 적용할 수 없다.
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-2/dashboard
스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 - 인프런 | 강의
웹 애플리케이션 개발에 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. MVC 2편에서는 MVC 1편의 핵심 원리와 구조 위에 실무 웹 개발에 필요한 모든 활용 기술들을 학습할 수 있
www.inflearn.com
'Spring' 카테고리의 다른 글
| [Spring JPA] 엔티티 설계 (0) | 2023.04.08 |
|---|---|
| [Spring JPA] 어노테이션 정리 (0) | 2023.04.05 |
| [SpringBoot] 검증1-Validation (0) | 2023.03.30 |
| [SpringBoot] 메시지 국제화 (0) | 2023.03.28 |
| 스프링 JUnit5 어노테이션 정리 (0) | 2022.12.06 |