본문 바로가기
강의 실습/스프링 핵심 원리 - 기본편

프로토타입 스코프

by jint 2026. 5. 6.

싱글톤 스코프의 빈 조회시, 스프링 컨테이너는 항상 같은 인스턴스의 스프링 빈을 반환하지만,
프로토타입 스코프의 빈 조회시, 스프링 컨테이너는 항상 새로운 인스턴스의 스프링 빈을 생성하여 반환한다.


1. 싱글톤 빈 요청

싱글톤 빈 요청


1) 싱글톤 스코프의 빈을 스프링 컨테이너에 요청
2) 스프링 컨테이너가 관리하는 스프링 빈 반환
3) 이후 같은 요청이 스프링 컨테이너에 와도 같은 객체 인스턴스의 스프링 빈 반환


2. 프로토타입 빈 요청

프로토타입 빈 요청1


1) 프로토타입 스코프의 빈을 스프링 컨테이너에 요청
2) 스프링 컨테이너는 이 시점에 새로운 프로토타입 빈을 생성 후, 필요한 의존관계 주입 + 초기화

 

프로토타입 빈 요청2


3) 스프링 컨테이너는 생성한 프로토타입 빈을 클라이언트에 반환
4) 이후 같은 요청이 스프링 컨테이너에 와도 새로운 객체 인스턴스의 프로토타입 빈을 생성해서 반환


3. 정리
핵심 : 스프링 컨테이너는 프로토타입 빈을 생성, 의존관계 주입, 초기화까지만 처리

스프링 컨테이너는 클라이언트에 빈을 반환한 후, 생성된 프로토타입 빈을 관리하지 않는다.
프로토타입 빈을 관리할 책임은 프로토타입 빈을 받은 클라이언트에 있다.
따라서 @PreDestroy 같은 종료 메서드가 호출되지 않는다. (@PreDestroy 메서드는 스프링 컨테이너가 호출)


4. 싱글톤 스코프 빈 테스트
- src/test/java/hello/core/scope/SingletonTest.java

package hello.core.scope;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Scope;

import static org.assertj.core.api.Assertions.assertThat;

public class SingletonTest {

    @Test
    public void singletonBeanFind() {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SingletonBean.class);
        SingletonBean singletonBean1 = ac.getBean(SingletonBean.class);
        SingletonBean singletonBean2 = ac.getBean(SingletonBean.class);

        System.out.println("singletonBean1 = " + singletonBean1);
        System.out.println("singletonBean2 = " + singletonBean2);

        assertThat(singletonBean1).isSameAs(singletonBean2);

        ac.close(); // 종료
    }

    @Scope("singleton")
    static class SingletonBean {

        @PostConstruct
        public void init() {
            System.out.println("SingletonBean.init");
        }

        @PreDestroy
        public void destroy() {
            System.out.println("SingletonBean.destroy");
        }

    }

}


- 콘솔

SingletonBean.init
singletonBean1 = hello.core.scope.SingletonTest$SingletonBean@45d64d27
singletonBean2 = hello.core.scope.SingletonTest$SingletonBean@45d64d27
22:58:24.187 [Test worker] DEBUG o.s.c.a.AnnotationConfigApplicationContext --Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@50825a02, started on Wed May 06 22:58:24 KST 2026
SingletonBean.destroy


· 싱글톤 빈은 스프링 컨테이너 생성 시점에 초기화 메서드 실행
· 빈 초기화 메서드 1회 실행 후, 같은 인스턴스의 빈 조회, 종료 메서드까지 1회 정상 호출
· 싱글톤 빈은 스프링 컨테이너가 관리하기 때문에, 스프링 컨테이너가 종료될 때 빈 종료 메서드가 실행됨


5. 프로토타입 스코프 빈 테스트
- src/test/java/hello/core/scope/PrototypeTest.java

package hello.core.scope;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Scope;

import static org.assertj.core.api.Assertions.assertThat;

public class PrototypeTest {

    @Test
    public void prototypeBeanFind() {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PrototypeBean.class);
        System.out.println("find prototypeBean1");
        PrototypeBean prototypeBean1 = ac.getBean(PrototypeBean.class);
        System.out.println("find prototypeBean2");
        PrototypeBean prototypeBean2 = ac.getBean(PrototypeBean.class);

        System.out.println("prototypeBean1 = " + prototypeBean1);
        System.out.println("prototypeBean2 = " + prototypeBean2);

        assertThat(prototypeBean1).isNotSameAs(prototypeBean2);

        // 클라이언트에서 직접 호출
        // prototypeBean1.destroy();
        // prototypeBean2.destroy();

        ac.close(); // 종료
    }

    @Scope("prototype")
    static class PrototypeBean {

        @PostConstruct
        public void init() {
            System.out.println("PrototypeBean.init");
        }

        @PreDestroy
        public void destroy() {
            System.out.println("PrototypeBean.destroy");
        }

    }

}


AnnotationConfigApplicationContext 생성자 매개변수에 등록하고자 하는 빈 클래스를 넣으면 @Component 어노테이션이 붙은 것처럼, 컴포넌트 스캔 대상처럼 등록 된다.

- 콘솔

find prototypeBean1
PrototypeBean.init
find prototypeBean2
PrototypeBean.init
prototypeBean1 = hello.core.scope.PrototypeTest$PrototypeBean@45d64d27
prototypeBean2 = hello.core.scope.PrototypeTest$PrototypeBean@34fe326d
23:08:03.218 [Test worker] DEBUG o.s.c.a.AnnotationConfigApplicationContext --Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@50825a02, started on Wed May 06 23:08:03 KST 2026


· 프로토타입 빈은 스프링 컨테이너에서 빈 조회 시점에 생성되고, 초기화 메서드도 실행
· 프로토타입 빈을 2번 조회했으니, 완전히 다른 스프링 빈 2개가 생성되고, 초기화도 2번 실행된다.
· 프로토타입 빈은 스프링 컨테이너가 생성, 의존관계 주입, 초기화까지만 관리하므로, 스프링 컨테이너가 종료될 때 @PreDestroy 같은 빈 종료 메서드가 실행되지 않음


6. 프로토타입 빈의 특징 정리
· 스프링 컨테이너에 요청할 때마다 새로 생성
· 스프링 컨테이너는 프로토타입 빈 생성, 의존관계 주입, 초기화까지만 관여
· 빈 종료 메서드 호출X
· 프로토타입 빈은 조회한 클라이언트가 관리해야 한다. 따라서 빈 종료 메서드 호출 또한 클라이언트가 직접 해야 한다.


참고링크 : https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8?cid=325969

 

스프링 핵심 원리 - 기본편| 김영한 - 인프런 강의

현재 평점 5.0점 수강생 49,596명인 강의를 만나보세요. 스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다. 스프링 기본 기능, 스프

www.inflearn.com

댓글