[CS]Spring관련 질문 및 답변2

Michelle Kim·2025년 2월 23일

CS-지식

목록 보기
3/15

Spring관련 질문

Spring DI/IoC는 어떻게 동작하나요?

IoC: IoC(제어의 역전)은 프로그램의 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것으로 코드의 최종호출은 개발자가 제어하는 것이 아닌 프레임워크의 내부에서 결정된 대로 이루어집니다.

DI: DI(의존관계 주입)은 Spring 프레임워크에서 지원하는 IoC의 형태로 클래스 사이의 의존관계를 빈 설정 정보를 바탕으로 컨테이너가 자동으로 연결해줍니다

✔ 예제 (DI 적용 전 vs 적용 후)

DI 적용 전 (new 키워드 사용)

public class UserService {
    private UserRepository userRepository = new UserRepository();
}

“이 방식은 UserService가 UserRepository에 직접 의존하고 있어, 유지보수 및 테스트가 어렵습니다.”

DI 적용 후 (Spring에서 주입받음)

@Component
public class UserService {
    private final UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

“이제 UserRepository의 생성 및 주입을 스프링이 관리하므로, 유연하고 확장성이 높아집니다.”

DI 방법

1. 생성자 주입 (Constructor Injection)
의존성을 생성자를 통해 주입하는 방법입니다. final 키워드를 사용할 수 있어 불변성을 보장하며, 순환 참조 문제를 방지할 수 있어 가장 권장되는 방식

@Component
public class UserService {
    private final UserRepository userRepository; // final로 불변성 유지

    @Autowired  // 스프링 4.3 이후 생략 가능
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void getUserInfo(Long userId) {
        userRepository.findById(userId);
    }
}

2. 필드 주입 (Field Injection)
의존성을 클래스의 필드(멤버 변수)에 직접 주입하는 방법입니다. 코드가 간결하지만, 테스트가 어려워 유지보수성이 낮고, 순환 참조 문제 발생 가능성이 있어 권장되지 않습니다.

@Component
public class UserService {
    @Autowired
    private UserRepository userRepository; // 필드 주입

    public void getUserInfo(Long userId) {
        userRepository.findById(userId);
    }
}

3. 세터 주입 (Setter Injection)
의존성을 Setter 메서드를 통해 주입하는 방식입니다. 선택적인 의존성을 주입할 때 유용하지만, 객체가 불완전한 상태로 생성될 가능성이 있어 신중하게 사용해야 합니다.

@Component
public class UserService {
    private UserRepository userRepository;

    @Autowired
    public void setUserRepository(UserRepository userRepository) { // 세터 주입
        this.userRepository = userRepository;
    }

    public void getUserInfo(Long userId) {
        userRepository.findById(userId);
    }
}

Spring Bean이란 무엇인가요?

IoC 컨테이너 안에 들어있는 객체로 필요할 때 IoC컨테이너에서 가져와서 사용합니다.
@Bean 을 사용하거나 xml설정을 통해 일반 객체를 Bean으로 등록할 수 있습니다.

Spring Bean은 스프링 IoC 컨테이너가 생성하고 관리하는 객체입니다.
즉, @Component, @Service, @Repository, @Controller 등의 어노테이션을 사용하거나
@Bean을 등록하여 스프링 컨테이너가 객체를 생성하고, 애플리케이션 전반에서 사용할 수 있도록 관리합니다.

✔ 예제 (Spring Bean 등록 예시)

@Component  // 스프링이 관리하는 Bean으로 등록
public class UserService {
}
@Configuration
public class AppConfig {
    @Bean
    public UserService userService() {
        return new UserService();
    }
}

이렇게 등록된 Bean은 스프링 컨테이너가 관리하며, 필요할 때 주입받아 사용할 수 있습니다.

스프링 Bean의 생성 과정을 설명해주세요.

객체 생성 → 의존 설정 → 초기화 → 사용 → 소멸 과정의 생명주기를 가지고 있습니다.
Bean은 스프링 컨테이너에 의해 생명주기를 관리하며 빈 초기화방법은 @PostConstruct 를 빈 소멸에서는 @PreDestroy 를 사용합니다.

생성한 스프링 빈을 등록할 때는 ComponentScan을 이용하거나 @Configuration 의 @Bean 을 사용하여 빈 설정파일에 직접 빈을 등록할 수 있습니다.

Spring Bean의 생명주기 (Lifecycle)
1. 객체 생성: @Component, @Service, @Bean 등을 통해 Bean이 생성됨
2. 의존성 주입: @Autowired, 생성자 주입 등을 통해 필요한 Bean을 주입
3. 초기화: @PostConstruct 또는 InitializingBean을 사용하여 초기 설정 수행
4. 사용: Bean이 애플리케이션에서 사용됨
5. 소멸: @PreDestroy 또는 DisposableBean을 사용하여 정리 작업 수행

✔ 예제 (생명주기 메서드 활용)

@Component
public class UserService {
    @PostConstruct
    public void init() {
        System.out.println("UserService 초기화 완료");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("UserService 소멸");
    }
}

스프링 Bean의 Scope에 대해서 설명해주세요.

빈 스코프는 빈이 존재할 수 있는 범위를 뜻하며 싱글톤, 프로토타입, request, session, application 등이 있습니다.

1. 싱글톤 : 기본 스코프로 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프입니다.
• 스프링 컨테이너에서 기본적으로 적용되는 스코프입니다.
• 스프링 컨테이너가 실행될 때 한 개의 인스턴스만 생성하여 공유합니다.
• 즉, 동일한 빈을 여러 번 요청해도 항상 같은 인스턴스가 반환됩니다.
• 스프링이 자동으로 관리하며, 컨테이너가 종료될 때 자동으로 소멸됩니다.

<<특징>>
• 빈이 한 번만 생성되고, 여러 곳에서 공유됨 → 메모리 절약 가능
• 상태를 가지면 안 됨(공유 객체이므로 변경 가능한 필드는 지양해야 함)
• 스프링 컨테이너가 관리 → 직접 소멸시키지 않아도 됨

2. 프로토타입 : 빈의 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는 매우 짧은 범위의 스코프입니다.
• 빈을 요청할 때마다 새로운 인스턴스를 생성합니다.
• 스프링 컨테이너가 생성과 의존성 주입까지만 관리하고, 이후에는 관리하지 않습니다.
• 즉, 컨테이너가 종료되더라도 프로토타입 빈은 자동으로 소멸되지 않습니다.

<<특징>>
• 새로운 인스턴스가 계속 생성되므로 메모리 사용량 증가 가능
• 상태를 가질 수 있으며, 특정 요청마다 다른 값을 유지 가능
• 컨테이너가 자동으로 소멸시키지 않으므로 수동으로 정리해야 함 (@PreDestroy 사용 불가)
• 주로 독립적인 객체가 필요할 때 사용 (예: 다이나믹한 요청 처리 객체)

3. request : 웹 요청이 들어오고 나갈때까지 유지하는 스코프,
• 웹 애플리케이션에서 HTTP 요청이 시작될 때 생성되고, 요청이 끝나면 소멸됩니다.
• 주로 HTTP 요청에 따라 다른 값을 유지해야 할 때 사용됩니다.

<<특징>>
• HTTP 요청마다 새로운 인스턴스를 생성함
• 요청이 끝나면 자동으로 소멸됨
• Spring MVC 컨트롤러, 필터, 인터셉터에서 주로 사용됨
• @Autowired 로 주입할 경우, 프록시(proxy) 사용을 권장 (@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS))

4. session : 웹 세션이 생성, 종료할때까지,
• HTTP 세션(HttpSession)이 생성될 때 빈도 생성되고,세션이 만료되거나 삭제될 때까지 유지됩니다.
• 로그인 사용자 정보 저장 등에 사용됩니다.

<<특징>>
• 사용자 세션별로 하나의 인스턴스를 유지
• HTTP 세션이 종료되면 자동으로 소멸됨
• 로그인 사용자 정보를 저장하는 객체 등에 유용

5. application : 웹 서블릿 컨텍스트와 같은 범위로 유지하는 스코프입니다.
• 서블릿 컨텍스트(ServletContext)와 같은 범위에서 유지됩니다.
• 즉, 애플리케이션이 시작될 때 생성되고, 애플리케이션이 종료될 때 소멸됩니다.
• 전역적으로 공유되는 빈을 만들 때 사용됩니다.

<<특징>>
• 하나의 애플리케이션에서 단 하나의 인스턴스만 유지됨
• 글로벌 설정 정보, 캐싱 등 어플리케이션 전역에서 공유되는 데이터 저장에 유용

스코프별 차이점 정리

IoC 컨테이너의 역할은 무엇이 있을까요?

애플리케이션 실행시점에 빈 오브젝트를 인스턴스화하고
DI 한 후에 최초로 애플리케이션을 기동할 빈 하나를 제공해준다

DI 종류는 어떤것이 있고, 이들의 차이는 무엇인가요?

DI는 세가지 방법이 있습니다. 생성자 삽입, Setter를 이용한 메소드 매개 변수 삽입, 필드 주입이 있습니다.

1. 생성자 주입 : 생성자 호출시점에 딱 1번만 호출되는 것을 보장하며 불변, 필수 의존관계에 사용합니다.

2. Setter주입 : 선택, 변경 가능성이 있는 의존관계에 사용되며 스프링빈을 선택적으로 등록이 가능합니다.

3. 필드 주입 :@Autowired 를 사용하는데 외부에서 변경이 불가능하여 테스트 하기 힘듭니다.
DI 프레임워크 없이는 작동하기 힘들며, 주로 애플리케이션과 관계없는 테스트코드나 @Configuration 같은 스프링 설정 목적으로 사용합니다.

Autowiring 과정에 대해서 설명해주세요.

컨테이너에서 타입(인터페이스 또는 오브젝트)을 이용해 의존 대상 객체를 검색하고
할당할 수 있는 빈 객체를 찾아 주입한다

profile
🇬🇧영국대학교)Computer Science학과 졸업 📚Data, AI, Backend 분야에 관심이 많습니다. 👉Email: kimbg9876@gmail.com

0개의 댓글