오늘 진행한 학습 요약
1. Spring 숙련 - 1주차
- 객체 지향 설계
- SOLID 원칙
- Spring과 객체 지향
- Spring의 핵심 개념
- Spring Container
- Spring Bean
- IOC/DI
- IOC(제어의 역전, Inversion Of Control)
- DI(의존성 주입, Dependency Injection)
- Singleton Pattern
- 싱글톤 패턴(Singleton Pattern)
- 싱글톤 패턴의 주의점
- Spring Bean 등록
- @ComponentScan
- @Configuration, @Bean
- Bean 충돌
- @Qualifier, @Primary
- 수동 VS 자동
- 의존관계 주입
- 의존관계 주입
- 생성자 주입
- @RequiredArgsConstructor
- Validation
- 검증(Validation)
- BindingResult
- Bean Validation
- Bean Validation
- Field Error
- Validator
- 에러 메세지
- Object Error
- Bean Validation의 충돌
- groups
- groups VS DTO 분리
- @ModelAttribute, @RequestBody
2. Spring 개념 정리
- 의존성 주입 정리
- Spring Bean 정리
- @Validated 정리
3. 알고리즘 코드카다 Day28(작성 생략)
CodingTest Git-hub 링크 : https://github.com/chews26/CodingTest
학습 정리
1. Spring 숙련 - 1주차
객체 지향 설계
- SOLID 원칙
- 단일 책임 원칙 SRP(Single Responsibility Principle)
- 하나의 클래스는 하나의 책임만 가져야 한다.
- 개방 폐쇄 원칙 OCP(Open Closed Principle)
- 소프트웨어 요소는 확장에는 열려 있어야 하고, 수정에는 닫혀 있어야 한다.
- 리스코프 치환 원칙 LSP(Liskov Substitution Principle)
- 자식 클래스는 언제나 부모 클래스를 대체할 수 있어야 한다.
- 인터페이스 분리 원칙 ISP(Interface Segregation Principle)
- 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.
- 의존관계 역전 원칙 DIP(Dependency Inversion Principle)
- 구체적인 클래스에 의존하지 말고, 인터페이스나 추상 클래스에 의존하도록 설계해야 한다.
- 단일 책임 원칙 SRP(Single Responsibility Principle)
- Spring과 객체 지향
- Spring은 다형성 만으로는 해결하지 못했던 객체 지향 설계 원칙 중 OCP, DIP를 IOC, DI를 통해 가능하도록 만들어준다.
Spring의 핵심 개념
- Spring Container
- Spring으로 구성된 애플리케이션에서 객체(Bean)를 생성, 관리, 소멸하는 역할을 담당
- 애플리케이션 시작 시, 설정 파일이나 Annotation을 읽어 Bean을 생성하고 주입하는 모든 과정을 컨트롤
- 주방의 Chef → 재료 선택, 요리, 완성까지 모든 것을 관리
- Spring Container의 종류
- BeanFactory
- Spring Container의 최상위 인터페이스
- Spring Bean을 관리하고 조회
- ApplicationContext
- BeanFactory의 확장된 형태(implements)
- Application 개발에 필요한 다양한 기능을 추가적으로 제공
- 국제화, 환경변수 분리, 이벤트, 리소스 조회
- BeanFactory
- Spring Bean
- Spring 컨테이너가 관리하는 객체를 의미
- 자바 객체 자체는 특별하지 않지만, Spring이 이 객체를 관리하는 순간부터 Bean이 된다
- Spring은 Bean을 생성, 초기화, 의존성 주입 등을 통해 관리
- Chef인 Spring Container가 요리할 음식에 사용될 재료(Bean)
- Spring 컨테이너에 의해 생성되고 관리
- 기본적으로 Singleton으로 설정
- 의존성 주입(DI)을 통해 다른 객체들과 의존 관계
- 생성, 초기화, 사용, 소멸의 생명주기
- XML, Java Annotation, Java 설정파일 등을 통해 Bean으로 등록
IOC/DI
- IOC(제어의 역전, Inversion Of Control)
- 객체의 생성과 관리 권한을 개발자가 아닌 Spring 컨테이너가 담당
- Spring에서는 컨테이너가 객체 생성, 주입, 소멸을 관리
- 요리사(개발자)는 필요한 재료를 직접 준비하지 않고, Chef가 알아서 필요한 재료(Bean)을 관리하고 요리사에게 가져다준다.
- 객체 간의 결합도를 낮춰 유연한 코드
- IoC는 객체의 제어권을 개발자가 아닌 Spring 컨테이너에게 넘기는 개념으로, Spring이 객체 생성과 관리를 담당
- DI(의존성 주입, Dependency Injection)
- Spring이 객체 간의 의존성을 자동으로 주입해주는 것을 의미
- 한 객체가 다른 객체를 사용할 때, 해당 객체를 직접 생성하지 않고 Spring이 주입해주는 방식
- IOC를 구현하는 방식 중 하나
- 셰프가 요리를 만들 때 필요한 재료(Bean)를 자동으로 요리사에게 가져다주는 과정으로 요리사(개발자)는 재료를 찾을 필요 없이, Chef가 알아서 제공해준다.
- DI는 Spring이 객체 간의 의존성을 자동으로 주입해주는 기법
Singleton Pattern
- 싱글톤 패턴(Singleton Pattern)
- 클래스의 인스턴스가 오직 하나만 생성되도록 보장하는 디자인 패턴
- 객체 인스턴스가 하나만 생성되고 생성된 인스턴스만 사용
- 싱글톤 패턴을 구현하기 위한 코드의 양이 많다
- 구현 클래스에 의존해야 한다.(DIP, OCP 위반)
- Spring Container는 싱글톤 패턴의 문제점들을 해결하면서 객체를 싱글톤으로 관리
- 싱글톤 패턴의 주의점
- 객체의 인스턴스를 하나만 생성하여 공유하는 싱글톤 패턴의 객체는 상태를 유지(stateful)하면 안된다.
- 상태 유지(stateful)의 문제점
- 데이터의 불일치나 동시성 문제가 발생할 수 있다
- Spring Bean은 항상 무상태(stateless)로 설계를 해야한다. 아주 중요!
- 상태 유지(stateful)의 문제점
- 객체의 인스턴스를 하나만 생성하여 공유하는 싱글톤 패턴의 객체는 상태를 유지(stateful)하면 안된다.
Spring Bean 등록
- @ComponentScan
- Spring이 특정 패키지 내에서 @Component, @Service, @Repository, @Controller 같은 Annotation이 붙은 클래스를 자동으로 검색하고, 이를 Bean으로 등록하는 기능
- Bean을 직접 등록하지 않고도 Spring이 자동으로 관리할 객체들을 찾는다.
- Chef가 요리할 재료를 자동으로 식료품 저장고에서 찾아오는 과정, Chef는 스스로 필요한 재료를 찾아 요리에 사용한다. 요리사(개발자)가 직접 재료(Bean)를 찾아서 가져올 필요가 없다.
- @ComponentScan의 동작 순서
- 1. Spring Application이 실행되면 @ComponentScan이 지정된 패키지를 탐색
- 2. 해당 패키지에서 @Component 또는 Annotation이 붙은 클래스를 찾음
- 3. 찾은 클래스를 Spring 컨테이너에 빈으로 등록
- 4. 등록된 빈은 의존성 주입(DI)과 같은 방식으로 다른 빈과 연결
- @Configuration, @Bean
- Spring Bean을 등록하는 방법에는 수동, 자동 두가지가 존재
- 자동 Bean 등록(@ComponentScan, @Component)
- 수동 Bean 등록(@Configuration, @Bean)
- Spring Bean을 등록하는 방법에는 수동, 자동 두가지가 존재
- Bean 충돌
- Bean 등록 방법에는 수동, 자동 두가지가 존재하고 Bean은 각각의 이름으로 생성된다. 이때 이름이 같은 Bean이 설정되고자 한다면 충돌이 발생
- @Qualifier, @Primary
- 같은 타입의 Bean이 중복된 경우 해결하기 위해 사용하는 Annotation
- @Autowired + 필드명 사용
- 타입으로 먼저 주입을 시도하고 같은 타입의 Bean이 여러개라면 필드 이름 혹은 파라미터 이름으로 매칭
- @Qualifier 사용
- Bean 등록 시 추가 구분자 붙임
- 생성자 주입, setter 주입 사용 가능
- @Primary 사용
- @Primary로 지정된 Bean이 우선 순위를 가짐
- 수동 VS 자동
- Annotation 기반의 Spring에서는 자동 Bean 등록과 의존관계 주입을 사용하는 경우를 주로 사용
- 자동 Bean 등록을 사용하는 이유
- 다양한 Annotation으로 편리하게 등록
- Spring Boot는 ComponentScan 방식을 기본으로 사용
- 간단하지만 OCP, DIP를 준수하며 개발
- 수동 Bean 등록을 사용하는 경우
- 외부 라이브러리나 객체를 Spring Bean으로 등록
- 데이터베이스 연결과 같이 비지니스 로직을 지원하는 기술들에 사용
- 같은 타입의 Bean 여러개 중 하나를 명시적으로 선택해야 할 때
의존관계 주입
- 의존관계 주입
- 의존관계 주입을 하는 방법으로 생성자 주입, setter 주입, 필드 주입, 메서드 주입 총 4가지 방법이 존재
- 1. 생성자 주입
- 생성자를 통해 의존성을 주입하는 방법.
- 최초에 한번 생성된 후 값이 수정되지 못한다.[불변, 필수]
- 2. Setter 주입
- Setter 메서드를 통해 의존성을 주입하는 방법.
- 3. 필드 주입
- 필드에 직접적으로 주입하는 방법 (가장 추천되지 않음).
- 코드는 간결하지만 Spring이 없으면 사용할 수 없다.
- 4. 일반 메서드 주입
- 생성자, setter 주입으로 대체가 가능하기 때문에 사용하지 않는다.
- 생성자 주입
- 생성자 주입을 선택하는 이유
- 어떤 요리(Web Application)를 만들지 정해졌다면 이미 재료(Bean)와 의존 관계가 결정된다.
- 객체를 생성할 때 최초 한번만 호출된다.(불변)
- setter 주입을 사용하면 접근제어자가 public 으로 설정되어 누구나 수정할 수 있게된다.
- 순수 Java 코드로 사용할 때(주로 테스트 코드) 생성자의 필드를 필수로 입력하도록 만들어준다.(NPE 방지)
- 컴파일 시점에 오류를 발생 시킨다. 즉, 실행 전에 오류를 알 수 있다.
- 생성자 주입을 선택하는 이유
- @RequiredArgsConstructor
- Web Application을 개발하면 대부분이 불변 객체이고 생성자 주입 방식을 선택
- 이런 반복되는 코드를 편안하게 작성하기 위해 Lombok에서 제공하는 Annotation
- @RequiredArgsConstructor
- final 필드를 모아서 생성자를 자동으로 만들어 주는 역할
- Annotation Processor 가 동작하며 컴파일 시점에 자동으로 생성자 코드를 만들어줌
Validation
- 검증(Validation)
- 특정 데이터(주로 클라이언트의 요청 데이터)의 값이 유효한지 확인하는 단계를 의미
- 식당 메뉴판(specification)에 있는 메뉴만 주문이 가능하다. 안내를 통해 제대로된 주문을 받을 수 있다.
- 검증의 종류
- 프론트 검증
- 서버 검증
- 데이터베이스 검증
- 특정 데이터(주로 클라이언트의 요청 데이터)의 값이 유효한지 확인하는 단계를 의미
- BindingResult
- Spring에서 기본적으로 제공되는 Validation 오류를 보관하는 객체
- 주로 사용자 입력 폼을 검증할 때 많이 쓰이고 Field Error와 ObjectError를 보관
- Errors 인터페이스를 상속받은 인터페이스
- Errors 인터페이스는 에러의 저장과 조회 기능을 제공
- BindingResult는 addError() 와 같은 추가적인 기능을 제공
- Spring이 기본적으로 사용하는 구현체는 BeanPropertyBindingResult
Bean Validation
- Bean Validation
- 특정 필드 검증의 경우 빈값, 길이, 크기, 형식 과 같은 간단한 로직
- 이러한 로직들을 모든 프로젝트에 적용할 수 있도록 표준화 한 것이 Bean Validation
- Bean Validation은 기술 표준 인터페이스
- 다양한 Annotation들과 여러가지 Interface로 구성
- Bean Validation(인터페이스) 구현체인 Hibernate Validator를 사용
- Hibernate Validator 공식문서 : https://hibernate.org/validator/
- 버전별 공식 메뉴얼 : https://docs.jboss.org/hibernate/validator
- Field Error
- 의존성 추가(build.gradle)
- implementation 'org.springframework.boot:spring-boot-starter-validation'
- External Libraries
- 파일경로 jakarta.validation-api-${version}.jar
- jakarta.validation.constraints
- 사용할 수 있는 다양한 Annotation들을 확인
- Annotation 들이 동작하게 만들어주는 Validator
- 파일경로 org.hibernate.validator:hibernate-validator:${version}
- jakarta.validation-api : Interface
- org.hibernate.validator:hibernate-validator : 구현체
- 의존성 추가(build.gradle)
- Validator
- 단순히 Annotation을 선언해주면 검증이 완료되는 이유는 Validator(Validation을 사용하는것)가 존재하기 때문
- Spring Boot는 validation 라이브러리를 설정하면 'org.springframework.boot:spring-boot-starter-validation'자동으로 Bean Validator를 Spring에 통합되도록 설정
- @Valid, @Validated 차이점
- @Valid 는 JAVA 표준
- @Validated 는 Spring 에서 제공하는 Annotation
- 에러 메세지
- Spring의 Bean Validation은 Default로 제공하는 Message들이 존재하고 임의로 수정할 수 있음
- Error Message
- Bean Validation을 적용하고 BindingResult에 등록된 검증 오류를 확인해보면 오류가 Annotation 이름으로 등록
- 에러 메세지 수정하기
- NotNull.Object.fieldName
- NotNull.fieldName(MessageSource)
- NotNull.FieldType(MessageSource)
- NotNull
- Spring의 Bean Validation은 Default로 제공하는 Message들이 존재하고 임의로 수정할 수 있음
- Object Error
- 필드 단위가 아닌 객체 전체에 대한 오류
- 두 필드 간의 관계를 검증할 때 ObjectError를 통해 해당 오류를 BindingResult에 기록할 수 있음
- Object Error는 로직으로 구현하면 됨
- 1. @ScriptAssert
- 2. Java 코드로 구현
- Bean Validation의 충돌
- 등록, 수정 API에서 각각 다른 Validation이 적용된다면?
- HTTP 요청은 사용자가 임의로 변경하여 요청할 수 있음으로 항상 서버에서 최종적으로 추가 검증을 진행 해야함
- 저장할 Object를 직접 사용하지 않고 SaveRequestDto, UpdateRequestDto 따로 사용
- 등록, 수정 API에서 각각 다른 Validation이 적용된다면?
- groups
- Bean Validation의 groups 속성은 다양한 유효성 검사 시나리오를 정의할 때 사용
- 동일한 객체에 대한 검증을 상황에 따라 다르게 적용하고 싶을 때 groups를 활용
- groups VS DTO 분리
- Bean Validation의 충돌이 발생하는 경우 대부분 DTO를 분리하는 방법이 적절
- @ModelAttribute, @RequestBody
- @Valid, @Validated는 @ModelAttribute뿐만 아니라 @RequestBody에도 적용
- @ModelAttribute는 요청 파라미터 혹은 Form Data(x-www-urlencoded)를 다룰 때 사용
- @RequestBody 는 HTTP Body Data를 Object로 변환할 때 사용
2. Spring 개념 정리
- 의존성 주입 정리
의존성 주입 | Notion
스프링 부트에서 의존성 주입은 객체 간의 연결을 자동으로 설정해주는 방식이에요. 예를 들어, A 클래스가 B 클래스의 기능을 사용해야 한다고 해볼게요. 보통은 A 클래스 안에서 B를 직접 생성
shinelee26.notion.site
- Spring Bean 정리
Spring Bean | Notion
Spring에서 **Bean(빈)**은 Spring IoC (Inversion of Control) 컨테이너가 관리하는 객체를 의미합니다. 즉, Spring이 애플리케이션을 실행할 때 필요에 따라 생성하고, 의존성을 주입하며, 필요한 시점에 제공
shinelee26.notion.site
- @Validated 정리
@Validated | Notion
@Validated 어노테이션은 Spring Framework에서 제공하는 유효성 검사(Validation)를 위한 어노테이션입니다. 주로 컨트롤러나 서비스 계층에서 메서드 파라미터나 객체의 유효성을 검증할 때 사용됩니다.
shinelee26.notion.site