스프링 프레임워크 기본(spring)
| topics | 300-백엔드개발 301 Spring |
| types | 이론 학습 |
| tags |
3tier 서버
클라이언트 (webserver)
웹어플리케이션서버 (WAS)
데이터베이스 서버
framework와 library차이
제어의 역전!! 제어가 누가 하냐
특징
- POJO(Plain Old Java Object)기반 구성 : 객체 지향적인 원리에 충실하면서 환경과 기술에 종속되지 않고 필요에 따라 재활용될 수 있는 방식으로 설계된 오브젝트이다.
- 제어의 역행(IoC)과 의존성 주입(DI)를 통한 객체간의 구성
- AOP(관점 지향 프로그래밍) 지원
- 종단(핵심)관심사 : 비즈니스
- 장점 : 순수 비즈니스 코드만 작성 가능
- 횡단관심사 : 공통관심사
- 중복 제거, 유지보수 굿
- aspect : 어떤 부가기능을 어디에 적용할지 정의한 것
- 횡단관심사를 캡슐화
- advice : aspect에서 적용되는 메서드
- join point : aspect가 적용되는 시점
- 종단횡단의 교차라고 생각하면 될 듯?
- 종단(핵심)관심사 : 비즈니스
| 구분 | 횡단 관심사(Cross-Cutting Concerns) | 핵심 관심사(Core Concerns) |
|---|---|---|
| 특징 | 여러 모듈·계층에 걸쳐 반복적으로 등장하는 부가 기능 | 애플리케이션의 주요 비즈니스 로직 |
| 예시 | 로깅, 보안, 트랜잭션, 예외 처리, 성능 모니터링 | 사용자 주문 처리, 결제 로직, 상품 관리 |
| 관리 방식 | AOP를 통해 모듈화하여 한 곳에서 관리 | 각 비즈니스 모듈에서 독립적으로 구현 |
| 코드 중복 | 중복 발생 → AOP로 해결 | 중복 없음 |
| 변경 영향도 | 한 번의 수정으로 전체 적용 가능 | 해당 모듈만 수정하면 됨 |
주요 요소
- 빈(Bean) : 스프링 컨테이너가 관리하는 자바 객체이다.
- 기본적으로 싱글톤 방식
- 수동으로 등록 방법
- 설정 클래스 파일을 만들어 @Configuration 적용
- 빈으로 등록할 메서드에 대해 @Bean 적용
- 스프링 컨테이너(Spring Container) : 스프링에서 빈 객체들을 관리하는 공간이다.
- 빈 팩토리라고도 부름
- 빈 팩토리를 부모로 갖는 ApplicationContext 도 있다.
- 부가기능을 추가로 제공함
- 굳이 따지자면 이렇게 두 개로 나눌 수 있음
- 빈 팩토리를 부모로 갖는 ApplicationContext 도 있다.
- 스프링 컨테이너는 빈(Bean)의 생성부터 소멸까지 개발자 대신 관리해준다.
- 스프링 컨테이너에 객체, 빈(Bean)을 등록하는 이유는 객체간의 의존 관계들을 스프링이 관리하도록 하기 위해서다.
- 빈 팩토리라고도 부름
쓰는 기술
- 핵심 기술 : 스프링 IoC 컨테이너, AOP , 기타 등등
- 웹 기술 : 스프링 MVC , 스프링 WebFlux
- 데이터 접근 기술 : 트랜잭션, JDBC, ORM
- 테스트 : 스프링 기반 테스트 지원 등등
solid
https://velog.io/@haero_kim/SOLID-%EC%9B%90%EC%B9%99-%EC%96%B4%EB%A0%B5%EC%A7%80-%EC%95%8A%EB%8B%A4
SRP 단일책임
응집도는 높게 결합도는 낮게
isp 인터페이스 분리 원칙
클라이언트의 목적과 용도에 적합한 인터페이스만을 제공하기 위해 인터페이스를 잘게 분리하는 것
의존성 주입 DI
생성자 주입
@Service
public class OrderService {
private final OrderRepository repository;
// 생성자 주입
@Autowired // (생성자가 하나면 생략 가능)
public OrderService(OrderRepository repository) {
this.repository = repository;
}
}
- final : 불변성 보장
- 생성시 한번만 호출됨(싱글톤으로써서)
- 불변과 필수 의존관계
필드 주입
@Service
public class OrderService {
@Autowired
private OrderRepository repository;
}
스프링의 객체(빈) 관리 vs. 가비지 컬렉터(GC)
| 구분 | 스프링 빈 관리 | 가비지 컬렉터(GC) |
|---|---|---|
| 관리 주체 | 스프링 컨테이너 | JVM(자바 가상 머신) |
| 관리 대상 | 스프링 컨테이너에 등록된 객체(빈) | 모든 자바 객체(참조가 끊긴 객체) |
| 주요 역할 | 객체의 생성, 의존성 주입, 초기화/소멸 콜백 관리 | 사용하지 않는 객체의 메모리 자동 해제 |
| 생명주기 제어 | 개발자가 초기화·소멸 시점에 직접 개입 가능 | 참조가 끊긴 시점에 JVM이 자동으로 처리 |
| 콜백 지원 | @PostConstruct, @PreDestroy 등으로 명확한 콜백 제공 | 별도의 콜백 없음 |
| 현재까지내가느끼기에는 싱글톤을 관리하고자 생긴느낌? | ||
| 싱글톤일때의 주기를제어하기 위해생긴 |
헷갈리는 것
빈 : 구현체
서비스 : 인터페이스
빈과 서비스는 보통 1대1매칭함 이럴경우 자동으로 스프링이 타입기반으로 주입
이건 필드주입임
Q 스프링에서 필드 주입을 안 하고 final을 씀으로서 얻는 이득이 뭔데
여기서의 final을 쓴다 = 생성자 주입을 말함
- 불변성(immutability) 보장
final로 선언된 필드는 한 번만 값이 할당되고, 이후에는 변경이 불가능하다.
생성자 주입을 사용하면 객체가 생성될 때 반드시 의존성이 할당되어야 하므로,
런타임 동안 의존 객체가 바뀌는 일이 없어 안정적이다.
- 필수 의존성 보장
final을 사용하면, 그 필드는 반드시 생성자에서 값을 받아야 한다.
즉, 의존성이 누락될 가능성을 컴파일 시점에 차단할 수 있다.
필드 주입/세터 주입은 의존성을 빼먹어도 컴파일 에러가 나지 않지만,
생성자 주입 + final은 누락 시 컴파일 에러가 발생한다.
- 테스트 용이성
생성자 주입은 스프링 컨테이너 없이도,
직접 new로 객체를 만들며 원하는 의존 객체를 주입할 수 있다.
반면 필드 주입은 리플렉션 등 복잡한 방법을 써야 하므로 테스트가 불편하다.
- 순환 참조/초기화 문제 예방
생성자 주입은 객체 생성 시점에 의존성이 모두 주입되어야 하므로,
순환 참조나 누락된 의존성을 애플리케이션 시작 시점에 바로 발견할 수 있다.
필드 주입은 객체 생성 후에 주입이 이뤄지기 때문에,
런타임에야 문제가 드러나거나, 순환 참조가 감지되지 않을 수 있다.
- 코드 명확성, 유지보수성 향상
생성자 파라미터로 의존성을 모두 명시하므로,
이 클래스가 무엇에 의존하는지 한눈에 파악할 수 있다.
final을 쓰면, "이 의존성은 반드시 필요하다"는 의도를 명확히 드러냅니다
1. 인터페이스 1개 + 구현체 1개 (가장 흔함)
- 대부분의 서비스/레포지토리 구조는 이렇게 설계한다.
- 예시:
public interface OrderRepository { ... }
@Repository
public class JpaOrderRepository implements OrderRepository { ... }
- 이 경우, 스프링이 자동으로 1:1로 매칭해서 주입해준다.
- 대부분의 실무 프로젝트에서 가장 많이 보는 구조이다.
2. 인터페이스 1개 + 구현체 여러개(특수한 경우)
- 예외적으로, 테스트용/특수 상황용 구현체가 추가될 수 있다.
- 예시:
@Repository public class MemoryOrderRepository implements OrderRepository { ... } @Repository public class JpaOrderRepository implements OrderRepository { ... } - 이때는
@Primary나@Qualifier로 어떤 구현체를 쓸지 명확히 지정해야 한다. - 이런 경우는 비교적 드물고, 테스트나 확장성 목적에서만 일부러 두는 경우가 많다.