스프링이해 2 - Spring에서 진짜 헷갈리는 개념 TOP 5
좋아요 👍
Spring Framework에서 가장 많이 헷갈리는 5개 개념을 설계 의도 기준으로 정리해보겠습니다.
(이거 이해하면 Spring 구조가 거의 보입니다)
---
1️⃣ Bean vs Component
Bean
> Spring 컨테이너가 관리하는 모든 객체
즉 결과 개념입니다.
등록 방법은 여러 가지입니다.
@Component
@Service
@Controller
@Repository
@Bean
XML
---
Component
> Bean을 자동 등록하기 위한 어노테이션
@Component
class UserService {}
동작
@ComponentScan
↓
@Component 발견
↓
Bean 등록
✔ 정리
Component ⊂ Bean
---
2️⃣ @Bean vs @Component
이건 등록 방식 차이입니다.
@Component
@Service
class UserService {}
특징
자동 등록
Component Scan 필요
우리가 만든 클래스에 사용
---
@Bean
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
특징
수동 등록
메서드 기반
외부 라이브러리 등록
예: Jackson ObjectMapper
---
✔ 핵심 차이
구분 Component Bean
방식 자동 수동
단위 클래스 메서드
사용 우리가 만든 클래스 외부 라이브러리
---
3️⃣ @Configuration vs @Component
이거 진짜 많이 틀립니다.
@Component
단순 Bean
@Component
class AppConfig {}
특별한 기능 없음
---
@Configuration
@Configuration
class AppConfig {}
특징
✔ CGLIB 프록시 생성
목적
> @Bean 싱글톤 보장
---
왜 필요한가
예
@Bean
public A a() {
return new A(b());
}
@Bean
public B b() {
return new B();
}
문제
a() 호출
↓
b() 호출
그러면 B가 2번 생성될 수도 있음
그래서 Spring이 프록시로 가로채서 싱글톤 유지
이게 CGLIB입니다.
---
4️⃣ @Autowired vs 생성자 주입
필드 주입
@Autowired
UserRepository repo;
문제
테스트 어려움
순환참조 발견 늦음
final 사용 불가
---
생성자 주입 (권장)
private final UserRepository repo;
public UserService(UserRepository repo) {
this.repo = repo;
}
장점
✔ 불변성
✔ 테스트 쉬움
✔ 순환참조 빨리 발견
그래서 **Spring Boot 공식 권장입니다.
---
5️⃣ Spring이 싱글톤을 관리하는 이유
Spring Bean 기본 스코프
Singleton
이유
서버는 요청이 많음
예
1초 1000 요청
객체를 계속 생성하면
GC 폭증
메모리 낭비
성능 저하
그래서
> Spring IoC 컨테이너가 싱글톤으로 관리
---
🔥 Spring 구조 한 장 정리
Spring Container
│
│ Bean 관리
│
┌───────────────┐
│ Bean 등록 방법 │
└───────────────┘
│
┌─────────────┬─────────────┐
│ │ │
@Component @Bean XML
│
@ComponentScan
---
💡 진짜 중요한 Spring 설계 철학
Spring의 핵심은 딱 3개입니다.
1️⃣ IoC (Inversion of Control)
→ 객체 생성은 Spring이 한다
2️⃣ DI (Dependency Injection)
→ 의존성 주입
3️⃣ AOP (Aspect Oriented Programming)
→ 공통 로직 분리
---
원하시면 다음도 설명해드릴게요 (이건 Spring 이해도 급상승 구간입니다)
1️⃣ 왜 @Transactional이 같은 클래스에서 호출하면 안 먹는지 (AOP 프록시)
2️⃣ Spring Bean 생명주기 (면접 단골)
3️⃣ @Configuration이 CGLIB 프록시 쓰는 이유
4️⃣ Spring Boot 자동설정 원리 (@EnableAutoConfiguration)
특히 1번은 Spring 사용하는 사람 70%가 정확히 모르는 개념입니다.
좋습니다 👍
이건 Spring Framework에서 가장 유명한 함정입니다.
> 왜 @Transactional이 같은 클래스 내부 호출에서는 동작하지 않는가?
이건 Spring AOP 프록시 구조 때문입니다.
---
1️⃣ 기본 상황
@Service
public class OrderService {
@Transactional
public void saveOrder() {
// DB 저장
}
public void processOrder() {
saveOrder(); // 내부 호출
}
}
실행
orderService.processOrder()
결과
❌ 트랜잭션 안 걸림
---
2️⃣ 왜 이런 일이 발생할까
Spring의 @Transactional은 Spring AOP 기반입니다.
즉 실제 객체가 아니라
프록시 객체
가 중간에 끼어 있습니다.
구조
Client
↓
Proxy
↓
Real Object
---
3️⃣ 외부 호출일 때
client
↓
proxy
↓
@Transactional 확인
↓
트랜잭션 시작
↓
real method 실행
↓
commit
즉
✔ 프록시가 가로채서 트랜잭션 처리
---
4️⃣ 내부 호출일 때
문제 상황
public void processOrder() {
saveOrder();
}
구조
processOrder()
↓
this.saveOrder()
여기서 중요한 점
Proxy 안 거침
그래서
@Transactional 실행 안됨
---
5️⃣ 그림으로 보면
정상 동작
Client
↓
OrderService Proxy
↓
@Transactional
↓
OrderService.saveOrder()
---
내부 호출
Client
↓
OrderService Proxy
↓
processOrder()
↓
this.saveOrder() ← proxy 안거침
---
6️⃣ 해결 방법
방법 1 (가장 일반적)
클래스 분리
@Service
class OrderService {
private final OrderTxService txService;
public void processOrder() {
txService.saveOrder();
}
}
@Service
class OrderTxService {
@Transactional
public void saveOrder() {}
}
구조
Client
↓
Proxy(OrderService)
↓
Proxy(OrderTxService)
↓
@Transactional
✔ 정상 작동
---
방법 2 (잘 안 씀)
프록시 자기 자신 주입
@Autowired
OrderService self;
하지만
❌ 구조가 더러워짐
---
방법 3
ApplicationContext에서 자기 자신 가져오기
하지만 이것도
❌ 권장 안 함
---
7️⃣ Spring이 프록시를 쓰는 이유
Spring AOP는
JDK Dynamic Proxy
CGLIB
기반입니다.
목적
로깅
트랜잭션
보안
캐싱
같은 공통 로직을 분리하기 위해서입니다.
---
🔥 진짜 중요한 포인트
Spring AOP는
Method Call interception
입니다.
그래서
Proxy를 거치는 호출만 AOP 적용
됩니다.
---
💡 실무에서 많이 터지는 버그
이 패턴
@Transactional
public void a() {
b();
}
@Transactional
public void b() {}
개발자는
b도 트랜잭션 걸릴거라 생각
하지만 실제
안 걸림
그래서 서비스 분리 패턴을 많이 씁니다.
---
원하시면 다음도 설명해드릴게요.
이건 Spring 이해도 레벨을 한 단계 올리는 내용입니다.
1️⃣ Spring Bean 생명주기 (생성 → 초기화 → 사용 → 소멸)
2️⃣ @Configuration이 왜 CGLIB 프록시를 쓰는지 (대부분 정확히 모름)
3️⃣ Spring Boot 자동설정 원리 (@EnableAutoConfiguration)
4️⃣ @SpringBootApplication 안에 뭐가 들어있는지
특히 4번은 Spring Boot 구조를 완전히 이해하게 되는 포인트입니다.
댓글
댓글 쓰기