- Spring DI/IoC 동작방식
- Spring Bean
- 스프링 Bean의 생성 과정
- IoC 컨테이너의 역할
- DI 종류와 이들의 차이
1. Spring DI/IoC
IoC (Inversion of Control), 제어의 역전
-
전통적인 프로그래밍 방식 → 개발자가 프로그램의 흐름과 제어를 직접 다룸
-
IoC → 프레임워크가 객체의 생성, 관리, 제어 흐름을 담당하도록 변경하는 개념
-
Spring은 이를 지원하기 위해 ApplicationContext라는 컨테이너 제공
-
Application Context : 애플리케이션의 컴포넌트를 생성하고 조립하며, 객체의 라이프사이클 관리
-
IoC 없이 의존성 직접 관리
public class OrderService {
private PaymentService paymentService = new PaymentService();
// OrderService는 PaymentService의 생성과 관리를 직접 처리
}- IoC 적용 후
public class OrderService {
private PaymentService paymentService;
// PaymentService는 외부에서 주입
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}Question
Spring IoC란 무엇인가요?
IoC는 개발자가 프로그램의 흐름과 제어를 직접 다루던 전통적인 프로그래밍 방식이 아닌 스프링의 IoC 컨테이너가 담당하도록 제어의 흐름을 역전시키는 디자인 원칙입니다.
이를 통해 결합도를 낮추고 유연한 구조를 제공할 수 있습니다.
→ 주요 구현체 : ApplicationContext, BeanFactory
DI (Dependency Injection), 의존성 주입
- IoC를 구현하는 주요 기술
- 객체가 사용할 의존성을 외부에서 주입받는 방식
- 의존성을 명시적으로 관리해 테스트 용이성과 코드 재사용성 향상
- Constructor Injection (생성자 주입)
public class OrderService {
private PaymentService paymentService;
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}- Setter Injection
public class OrderService {
private PaymentService paymentService;
public void setPaymentService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}- Field Injection (@Autowired)
public class OrderService {
@Autowired
private PaymentService paymentService;
}Question
DI란 무엇인가요?
DI는 Dependency Injection으로 IoC를 구현하는 주요 기술입니다. 객체가 사용할 의존성을 외부에서 주입받는 방식으로 생성자 주입, 필드 주입, 세터 주입, 필드 주입, XML 설정, Config 방식 등이 있습니다.
→ 주요 어노테이션 : @Autowired, @Conponent, @Configuration, @Bean
Question
IoC와 DI에 대해 설명해주세요
IoC는 객체의 생성과 제어 흐름을 개발자가 아닌 프레임워크가 담당하도록 제어를 역전시키는 개념입니다. 객체 스스로 의존성을 관리하지 않고 외부에서 주입받는 구조입니다. DI는 IoC를 구현하는 방법 중 하나로 객체의 의존성을 외부에서 주입하는 방식입니다. DI는 IoC의 실질적인 구현 기술입니다.
예를 들어 OrderService가 PaymentService를 직접 생성하는 대신 Spring이 이를 주입함으로써 IoC가 적용되고 이 주입과정이 DI 입니다.
Question
IoC 컨테이너의 역할은 무엇인가요?
IoC 컨테이너는 Spring에서 객체 생성, 관리, 의존성 주입, 객체 생명주기 관리를 담당하는 핵심 컴포넌트입니다.
Question
DI의 주요 방식에는 무엇이 있나요?
DI의 주요 방식은 Constructor Injection, Setter Injection, Field Injection이 있습니다. Constructor Injection은 생성자를 통해 의존성을 주입하는 방식으로 주입받은 의존성이 변경될 가능성이 없고 필수적인 의존성을 주입할 때 적합한 방식입니다. Setter Injection은 Setter 메서드를 통해 의존성을 주입하는 방식으로 선택적 의존성을 주입할 때 적합합니다. Field Injection은 주로 @Autowired 어노테이션을 이용해 필드에 직접 주입하는 방식으로 간결하게 사용이 가능하지만 컨테이너에 강하게 의존해 테스트나 유지보수에 어려움이 있습니다.
Question
@Autowired와 @Qualifier의 차이를 설명해보세요
@Autowired는 타입을 기반으로 의존성을 주입하고, @Qualifier는 특정 이름을 사용해 의존성을 주입합니다.
Autowired는 동일한 타입의 Bean이 여러개일경우 예외가 발생하며, Qualifier는 원하는 Bean을 선택할 수 있습니다.
Question
의존성 주입에서 순환참조 문제가 발생하면 어떻게 해결할 수 있나요?
순환참조는 Bean이 서로를 의존할 때 발생합니다. 이를 해결하기 위해선 Setter Injection을 사용해 Bean 주입 순서를 제어하거나 @Lazy 어노테이션을 사용하여 해결할 수 있습니다.
Question
Spring IoC와 DI의 동작 방식을 설명해주세요
먼저 config나 XML 파일에서 Bean을 정의하거나 어노테이션을 이용해 Bean을 등록합니다. Spring 컨테이너가 초기화되면서 Bean을 로드하고 객체를 생성합니다. 컨테이너가 Bean을 생성할 때 의존 관계를 확인하고 설정된 의존성을 주입합니다.
2. Spring Bean
- Spring 컨테이너에 의해 생성되고 관리되는 객체
- 기본적으로 싱글톤으로 관리되며, 애플리케이션 실행 중에 재사용됨
- 개발자가 명시적으로 등록하거나 어노테이션을 사용해 자동으로 등록할 수 있음
- XML 파일을 사용한 Bean 등록
- Java Config 기반 등록 (@Configuration, @Bean)
- Component Scan 기반 등록 (@Component, @Service, @Repository, @Controller)
Question
Spring Bean이란 무엇인가요?
Spring IoC 컨테이너에 의해 생성되고 관리되는 객체로, 의존성 관리와 생명주기의 중심이되는 요소입니다.
Question
Spring에서 Bean을 등록하는 방법은 무엇인가요?
XML 파일을 이용하거나 configuration 클래스에서 @Bean 어노테이션을 등록하거나, @Component, @Service, @Controller같은 어노테이션을 사용해 자동으로 등록할 수 있습니다.
Question
Bean의 생성 과정에 대해 설명해주세요
Bean을 정의하고 생성한 뒤 의존 관계에 따라 의존성을 주입하고 초기화한 뒤 사용후엔 소멸됩니다.
Question
Bean 초기화와 소멸 시점에 실행되는 메서드를 지정하는 방법?
- 초기화:
@PostConstruct,InitializingBean인터페이스의afterPropertiesSet(). - 소멸:
@PreDestroy,DisposableBean인터페이스의destroy().
Question
Spring에서 Bean Scope를 설명해주세요
scope는 빈이 존재할 수 있는 범위를 의미합니다. 싱글톤, 프로토타입, 리퀘스트, 세션, 어플리케이션 등이 있습니다. 싱글톤은 컨테이너당 하나의 인스턴스가 생성되는것을 뜻하며 프로토타입은 요청마다 새로운 인스턴스, 리퀘스트는 http 요청당 하나의 인스턴스, 세션은 http 세션당 하나의 인스턴스가 생성됨을 의미합니다.
Question
@Bean과 @Component의 차이점은 무엇인가요?
@Bean: 메서드 레벨에서 사용, 개발자가 객체 생성을 직접 제어.@Component: 클래스 레벨에서 사용, Component Scan에 의해 자동으로 관리.
Question
프로토타입 빈을 대량으로 생성하고 사용하는 서비스에서 성능 병목 현상이 발생한다면, 어떤 문제를 의심해야 하고 이를 해결할 설계 방안은 무엇일까?
빈 생성 비용: 프로토타입 빈은 요청마다 새로운 인스턴스를 생성하므로, 대량의 요청이 들어오면 객체 생성 비용이 누적되어 성능 병목이 발생할 수 있습니다. GC(가비지 컬렉션) 부하: 대량의 프로토타입 빈이 생성되고 요청이 끝날 때마다 소멸되므로, 가비지 컬렉션이 잦아지고 애플리케이션 성능에 영향을 미칠 수 있습니다. 스레드 동기화: 프로토타입 빈 생성 과정에서 빈 팩토리나 DI 관련 동기화가 성능 저하를 유발할 가능성이 있습니다. 해결 방안: 빈 재사용 전략: 프로토타입 빈의 객체 생성 비용을 줄이기 위해 객체 풀(Object Pool)을 도입하여 빈을 미리 생성해두고 재사용하는 방식을 사용할 수 있습니다. 예를 들어, Apache Commons Pool 라이브러리를 활용할 수 있습니다. 빈 생성을 지연(Lazy Initialization): 프로토타입 빈이 반드시 모든 요청마다 새로 생성되어야 하는지 검토하고, 필요한 시점에만 생성되도록 지연 초기화(Lazy Initialization)를 적용할 수 있습니다. 대체 설계: 프로토타입 빈의 기능을 지역 변수나 매개변수로 대체할 수 있다면, 빈 사용을 피하고 메서드 내부에서 데이터를 처리하도록 설계합니다.
Question
여러 사용자의 요청에서 상태를 공유해야 하는 경우, 빈의 스코프를 어떻게 설계해야 할지 설명해주세요. , Singleton 빈으로 설계해야 할까? 다른 스코프를 사용해야 한다면 어떤 점을 고려해야 할까?
Singleton 빈은 기본적으로 애플리케이션 전역에서 하나의 인스턴스를 공유하기 때문에 상태를 저장하면 동시성 문제가 발생할 가능성이 큽니다. 여러 사용자의 요청에서 공유 상태가 필요하더라도, Singleton 빈에 상태를 저장하는 것은 위험합니다. 특히, 데이터가 변하는 경우(유상태)라면 사용자 간 데이터가 섞이는 문제가 발생할 수 있습니다.
사용자의 요청 간 공유 상태가 필요한 경우, Session 스코프가 더 적합할 수 있습니다. Session 스코프는 사용자별로 상태를 유지하므로 각 사용자의 데이터가 독립적으로 관리됩니다. 그러나 Session 스코프를 사용하면 HTTP 세션 관리와 데이터 수명 주기를 고려해야 하므로 세션 종료 시 데이터를 정리하는 로직이 필요합니다.
데이터베이스 또는 캐시 사용: 만약 여러 요청 간에 데이터를 공유해야 한다면, 빈의 상태를 직접 관리하기보다는 Redis 같은 외부 캐시 또는 데이터베이스에 상태를 저장하고 필요할 때 가져오는 방식이 안전합니다. Immutable 객체 사용: 공유 상태를 관리해야 하는 경우, 상태 객체를 불변(Immutable)으로 설계하여 동시성 문제를 줄이는 것도 방법입니다.