spring
스프링 프레임워크의 핵심 철학은 IoC(Inversion of Control) 컨테이너를 통해 객체(빈, Bean)를 관리하고 의존성을 주입(DI, Dependency Injection)하는 것입니다.
스프링은 애플리케이션 실행 과정에서 필요한 빈들을 생성하고 의존 관계를 설정해줍니다. 그리고 이렇게 등록된 스프링 빈을 사용할 때, 빈이 생성되어 있는지, 혹은 생성 시점이 어떤지 등은 크게 신경 쓰지 않아도 됩니다. 대신, 스프링이 제공하는 스코프(Bean Scope) 설정을 통해 각 빈의 라이프사이클과 생성 횟수를 제어할 수 있습니다.
스프링 빈 스코프(Bean Scope)는 스프링 IoC 컨테이너가 빈의 라이프사이클과 생성·사용 범위를 어떻게 관리할 것인지를 결정하는 정책입니다.
스프링은 아래와 같은 여러 스코프를 제공합니다.
사용자 애플리케이션의 동작 요구사항에 맞춰 스코프를 적절히 설정함으로써, 불필요한 리소스를 아끼고 적절한 시점에 필요한 인스턴스를 생성·관리할 수 있습니다.
@Service
public class SingletonService {
public void doSomething() {
// singleton 스코프의 예시
System.out.println("SingletonService: 항상 동일한 인스턴스가 사용됩니다.");
}
}
Java@Configuration
public class AppConfig {
@Bean
// @Scope("singleton") // 생략 시 singleton이 기본값
public SingletonService singletonService() {
return new SingletonService();
}
}
Java@Component
@Scope("prototype")
public class PrototypeService {
public PrototypeService() {
System.out.println("PrototypeService 객체가 생성되었습니다.");
}
}
Java@RestController
public class PrototypeController {
@Autowired
private ApplicationContext context; // 스프링 컨텍스트를 직접 주입 받음
@GetMapping("/prototype-test")
public String prototypeTest() {
PrototypeService service1 = context.getBean(PrototypeService.class);
PrototypeService service2 = context.getBean(PrototypeService.class);
// 두 객체는 다르다
boolean same = service1 == service2;
return "service1 == service2? " + same;
}
}
Java@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestScopeBean {
private final LocalDateTime createdAt = LocalDateTime.now();
public String getCreationTime() {
return createdAt.toString();
}
}
Java@RestController
public class RequestScopeController {
private final RequestScopeBean requestScopeBean;
// 생성자 주입
public RequestScopeController(RequestScopeBean requestScopeBean) {
this.requestScopeBean = requestScopeBean;
}
@GetMapping("/request-scope")
public String getRequestScopeCreationTime() {
return "RequestScope Bean 생성 시간: " + requestScopeBean.getCreationTime();
}
}
Java@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class SessionScopeBean {
private final String sessionId;
public SessionScopeBean() {
// 세션 스코프이므로, 각 사용자 세션마다 인스턴스가 하나씩 생성
this.sessionId = UUID.randomUUID().toString();
}
public String getSessionId() {
return sessionId;
}
}
Java@RestController
public class SessionScopeController {
private final SessionScopeBean sessionScopeBean;
public SessionScopeController(SessionScopeBean sessionScopeBean) {
this.sessionScopeBean = sessionScopeBean;
}
@GetMapping("/session-scope")
public String getSessionScope() {
return "Session ID: " + sessionScopeBean.getSessionId();
}
}
Java@Component
@Scope(value = WebApplicationContext.SCOPE_APPLICATION)
public class ApplicationScopeBean {
private final AtomicInteger counter = new AtomicInteger(0);
public int incrementAndGet() {
return counter.incrementAndGet();
}
}
Java@RestController
public class ApplicationScopeController {
private final ApplicationScopeBean applicationScopeBean;
public ApplicationScopeController(ApplicationScopeBean applicationScopeBean) {
this.applicationScopeBean = applicationScopeBean;
}
@GetMapping("/application-scope")
public String applicationScopeTest() {
int currentCount = applicationScopeBean.incrementAndGet();
return "Application Scope Count: " + currentCount;
}
}
Java@Component
@Scope(value = "websocket", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class WebSocketScopeBean {
private final String id = UUID.randomUUID().toString();
public String getId() {
return id;
}
}
Java@Bean
@Scope("prototype")
public MyBean myBean() {
return new MyBean();
}
Java스프링 빈 스코프는 빈의 생성 시점과 유지·소멸 시점을 결정함으로써, 애플리케이션 동작에 큰 영향을 미칩니다. 알맞은 스코프를 사용하면 메모리 사용 최적화와 동시성 안전성 등을 향상시킬 수 있고, 잘못 사용하면 디버깅이 어려운 상태 관리 문제나 리소스 누수 등 다양한 문제에 직면하게 됩니다.
정리하자면, “어떤 범위의 생명주기를 가진 객체가 필요한가?”라는 질문에 따라 스프링 빈 스코프를 적절히 지정하는 것이 매우 중요합니다. 각 스코프별 특징과 동작 방식을 정확히 이해하고 상황에 맞게 적용하면, 더욱 안정적이고 효율적인 스프링 애플리케이션을 구현할 수 있을 것입니다.
테스트 시 의존성 주입(Dependency Injection)과 Mockito Spring 애플리케이션을 개발하다 보면, 테스트 코드에서 실제 빈(Bean)을 사용하지…
들어가며 스프링 기반 프로젝트에서 좋은 설계 구조와 테스트 전략은 소프트웨어 품질과 유지보수성에 직결됩니다. 최근 학습한…
들어가며 코드를 작성할 때 종종 "이 로직을 어떻게 단순하고 읽기 쉽게 표현할 수 있을까?" 고민하게…
HTTP 상태코드란 무엇인가? HTTP 상태코드(HTTP Status Code)는 서버가 클라이언트의 요청을 처리한 결과를 수치화된 코드로 나타내는…
HTTP란 무엇인가? HTTP(Hypertext Transfer Protocol)는 웹에서 데이터를 주고받기 위해 사용하는 응용 계층 프로토콜입니다. 우리가 브라우저에서…