스프링 공부 기록을 남깁니다.
1. IoC (Inversion of Control) & DI (Dependency Injection)
1) 제어의 역전 IoC
- 개념: 객체의 생성 및 생명주기 관리 제어권이 개발자(본인 클래스)가 아닌 외부(스프링 컨테이너)로 넘어간 상태를 말합니다.
- 기존 방식: 클래스 내부에서
new키워드를 사용해 의존할 객체를 직접 생성함. - IoC 방식: 클래스 내부에서 객체를 직접 생성하지 않고, 외부(생성자, 필드, 세터)로 부터 주입받아 사용함.
2) IoC 컨테이너 (ApplicationContext)
- 최상위 인터페이스:
BeanFactory가 최상위에 위치하며 빈의 생성과 가공 등의 역할을 담당합니다. 이를 확장한ApplicationContext를 주로 사용합니다. - 역할: 스프링 빈(Bean)들의 의존성을 관리하고 빈으로 등록하며 필요한 곳에 의존성을 주입(DI)해 줍니다. 추가로 애플리케이션 라이프사이클 인터페이스 등을 제공합니다.
- 싱글톤 스코프(Singleton Scope): 컨테이너는 기본적으로 객체를 단 하나만 생성하여 공유하는
싱글톤방식으로 관리합니다. 덕분에 멀티스레드 환경에서 매번 객체를 생성하는 오버헤드를 줄여줍니다.
3) 스프링 빈 (Bean)
- 정의: 스프링 컨테이너가 직접 생성하고 관리하는 자바 객체입니다. (
new로 생성한 객체는 빈이 아닙니다.) - 등록 방법:
1. 컴포넌트 스캔 (
@ComponentScan):@Conponent어노테이션 및 이를 확장한 아래 어노테이션이 붙은 클래스를 찾아 자동으로 빈 등록을 해 줍니다. -@Controller,@RestController(웹 요청 처리) -@Service(비즈니스 로직 처리) -@Repository(데이터 접근 계층 / Spring Data JPA에서는 특정 인터페이스를 상속 받으면 어노테이션 없이도 내부 프록시 기술을 통해 자동 등록 됨) -@Configuration(설정 정보) 2. 자바 코드로 직접 등록:@Configuration클래스 내부에서 메서드에@Bean을 붙이고 생성된 객체를 리턴(ex: return new MyService();)합니다.
4) 의존성 주입 (DI) 방식과 우선순위
의존성 주입은 스프링 컨테이너에 등록된 빈(Bean)끼리만 가능합니다. 생성자 주입을 사용할 때 final 키워드를 사용할 수 있어 객체의 불변성을 보장하므로 생성자 주입을 스프링 문서에서 권유하고 있습니다.
- 주입 방식 종류:
- 생성자 주입(권장): 생성자가 단 하나만 존재할 경우 스프링 4.3버전 부터
@Autowired를 생략해도 자동 주입됩니다. 순환 참조를 컴파일 시점에 방지할 수 있습니다. - 필드 주입 / Setter 주입: 과거 순환 참조 해결용으로 사용되기도 했으니 변경 가능성이 열려 있거나 (
final불가) 외부 테스트가 어려워 현재는 지양된다고 합니다.
- 생성자 주입(권장): 생성자가 단 하나만 존재할 경우 스프링 4.3버전 부터
-
주입 어노테이션별 매칭/찾는 순서:
어노테이션 우선 매칭 기준 매칭 순서 (우선순위 순 비고 @Autowired타입 (Type) 타입 → 이름 → @Qualifier→ 예외 발생스프링 표준 가능 @Inject타입 (Type) 타입 → @Qualifier→ 이름 → 예외 발생자바 표준(JSR-330) @Resource이름 (Name) 이름 → 타입 → @Qualifier→ 예외 발생자바 표준(JSR-250)
2. AOP (Aspect Oriented Programming)
1) 개념
- 정의: 관점 지향 프로그래밍으로 어플리케이션 전반에 걸처 반복되는 공통 관심사를 비즈니스 로직과 분리하여 모듈화 하는 기술입니다.
- 대표 예시: 메서드 실행 시간 측정, 트랜잭션 관리(
@Transactional), 로깅, 보안 인증 등.
2) AOP 구현 방법 3가지
1. 컴파일 시점 동작: .java 코드가 .class로 컴파일될 때 위빙되어 공통 코드가 삽입됨 (AsoectJ사용)
2. 바이트코드 조작 (클래스 로딩 시점): 컴파일된 .class파일이 메모리에 올라가는 로딩 시점에 가로채서 바이트 코드를 수정함.
3. 런타임 프록시 패턴 (스프링 AOP가 채택한 방식): 스프링은 실제 타겟 객체를 감싸는 프록시(가짜 가공 객체)를 자동으로 생성합니다.
- 클라이언트가 메서드를 호출하면 프록시가 먼저 호출되어 공통 작업(예: 트랜잭션 시작)을 수행한 후 실제 객체의 비즈니스 로직을 호출하는 구조입니다.
3. PSA (Portable Service Abstract)
1) 개념
- 정의: 일관된 서비스 추상화 “환경과 세부 기술이 변경되어도, 나의 비즈니스 코드는 수정하지 않고 그대로 유지할 수 있도록 인터페이스 규격을 맞추어 추상화해 주는 기술”이다
- 개발자는 구현체의 구체적인 메커니즘을 알지 못해도(추상화 레이어 뒤에 숨겨져 있음) 일관된 방식으로 기술을 사용할 수 있습니다.
2) 대표적인 예시
- Spring Web MVC (
@Controller,@RestController)- 개발자는 서블릿 인터페이스 기반의 하부 기술(기본:
Tomcat)을 신경쓰지 않고 어노테이션 기반으로 코드를 작성합니다. 설정을 통해 네티(Netty)나 제티(Jetty) 서버로 구동 기술을 변경하더라도 컨트롤러의 소스 코드는 변경할 필요가 없습니다. - 내부 데이터 접근 기술이
순수 JDBC기술이든,JPA/Hibernate이든,MyBatis이든 상관없이 스프링이 뒤에서 구체적인 트랜잭션 매니저(구현체)를 유연하게 갈아 끼워 주므로 비즈니스 코드는 수정할 필요가 없습니다.
- 개발자는 서블릿 인터페이스 기반의 하부 기술(기본:
- Spring Cache (
@Cacheable)- 구체적인 캐시 라이브러리 (
Encache, Redis, Caffeine등)가 무엇이든 간에 개발자는 동일한 캐시 어노테이션을 사용하여 비즈니스 로직을 구현할 수 있습니다.
- 구체적인 캐시 라이브러리 (