클라이언트가 웹 브라우저에서 특정 URL로 요청을 보냈을때, 이 요청이 내장 웹서버를 거쳐 스프링 MVC 프레임웤의 컨트롤러에 도달하고 최종적으로 뷰를 통해 클라이언트에게 응답되는 과정을 설명해주세요.
클라이언트가 웹 브라우저에서 특정 URL로 요청을 보내면, 이 요청은 내장 웹 서버를 통해 스프링 애플리케이션에 도달합니다.
내장 웹 서버는 이 요청을 분석하고, 해당 URL과 매핑된 컨트롤러의 메서드를 호출합니다.
이때 메서드는 스프링 프레임워크가 생성한 Model 객체를 인자로 받아, 필요한 데이터를 Model에 저장합니다.
이때 Model 객체는 컨트롤러와 뷰 사이에서 데이터를 주고받는 매개체의 역할을 합니다.
메서드가 뷰의 이름을 문자열로 반환하면, ViewResolver는 기본 설정 디렉토리에서 반환된 문자열에 해당하는 파일을 찾습니다.
찾아진 뷰 파일은 템플릿 엔진에 의해 렌더링 되며, 이 과정에서 Model객체에 저장된 데이터를 사용하여 동적인 웹 페이지를 생성합니다.
최종적으로 생성된 웹 페이지는 클라이언트에게 응답으로 전달되어, 웹 브라우저에 표시됩니다.
@Responsebody 어노테이션의 역할을 무엇인가요?
@ResponseBody 어노테이션은 컨트롤러의 메서드가 반환하는 결과를 HTTP 응답 본문에 직접 작성하는데 사용합니다.
일반적으로 이 어노테이션은 JSON 형태의 데이터를 반환하는 Restful 웹 서비스에서 사용합니다.
참고 - 이 애너테이션이 없다면 뷰 리졸버한테 던져줌
스프링에서는 어떻게 객체를 JSON으로 변환하나요?
스프링에서는 HttpMessageConverter를 사용하여 객체를 JSON으로 변환합니다. 컨트롤러에서 반환한 객체가 있다면, 기본 정책은 이 객체를 JSON으로 변환하여 HTTP 응답 본문에 작성하는 것입니다.
이때 클라이언트의 HTTP Accept 헤더와 서버의 컨트롤러 반환 타입 정보 둘을 조합해서 HttpMessageConverter가 선택됩니다.
참고 - 단순 문자면 StringConverter가 동작하고 객체인 경우엔 jsonConverter가 동작
@Component에 대해 설명해주세요
해당 클래스가 Spring Bean임을 나타내는 어노테이션입니다. 이 클래스는 Spring의 컴포넌트 스캐너에 의해 자동으로 감지되고, ApplicationContext에 등록됩니다.
@SpringBootTest와 @Transactional은 무엇인가요?
전자는 스프링 컨테이너와 테스트를 함께 실행하기 위한 어노테이션으로 통합 테스트시 주로 사용
후자 어노테이션 사용시 테스트 시작 전에 트랜잭션을 시작하고, 테스트 완료 후에 항상 롤백을 진행하는 어노테이션
이는 데이터 조회가 아니라, 데이터 저장 및 변경시에 필요함!!!!
스프링이란 무엇인가요???
스프링은 엔터프라이즈용 자바 애플리케이션 개발을 편하게 할 수 있게 해주는 오픈소스 애플리케이션 프레임워크입니다.
참고 - 스프링이 등장하기 이전에는 EJB(Enterprise Java Bean)이라는 기술이 주로 사용되었고 이 또한 이전 기술의 단점을 보완하기 위해 등장하였습니다.
하지만 여전히 불필요하게 복잡한 코드를 작성해야 했고, 이에 따라 많은 개발자들이 불필요한 코드를 걷어내고 어떻게 코드의 복잡성을 줄일지 고민한 결과 탄생하였습니다.
참고 - 프레임워크란, 어떠한 목적을 쉽게 달성할 수 있도록 해당 목적과 관련된 코드의 뼈대를 미리 만들어 둔것
스프링이 가지고 있는 특징들을 설명해주세요
스프링의 가장 큰 특징은 POJO를 지향한다는 것입니다. 여기서 POJO(Plain Object Java Object)란 순수 자바, 즉 java 및 java 스펙에 정의된 기술만 사용한다는 의미입니다.
예를들어 외부 라이브러리를 import해서 라이브러리 메서드를 사용하고 있다는 객체가 있다고 가정해보겠습니다.
이 객체는 순수 Java외의 외부 기술을 사용하므로, POJO가 아닙니다. 이때 이 객체가 사용하고 있는 기술이 Deprecated가 되거나, 개선된 신기술이 등장하여 기존 기술과 관련된 코드를 모드 고쳐야 한다면
해당 기술을 사용하고 있는 모든 객체들의 코드를 전부 바꿔주어야만 합니다.
반면 POJO는 순수 자바를 사용하여 만든 객체이기에 특정 기술이나 환경에 종속되지 않아, 보다 유연하게 변화와 확장에 대처할 수 있습니다.
이러한 POJO 프로그래밍을 위해 스프링이 지원하는 기술이 IOC/DI, AOP,PSA 등이 있습니다.
애플리케이션 개발 시 구현해야 할 기능들은 크게 공통 관심 사항(모든 핵심 사항에 공통으로 적용되는 관심 사항)과 핵심 관심 사항(애플리케이션의 핵심 기능과 관련된 관심사항)으로 분류됩니다.
이때 AOP란 애플리케이션 전반에 걸쳐 적용되는 공통 관심사항을 핵심 관심 사항인 비즈니스 로직으로부터 분리해 내는 것을 뜻합니다.
ex) 핵심 사항 예시 : 배달앱 기준 메뉴 등록 주문, 주문 변경 등, 공통 관심 사항 예시 : 로깅이나 보안과 관련된 기능을 공통적으로 적용
PSA(Portable Service Abstraction , 일관된 서비스 추상화)는 특정 기술에 종속되지 않도록 서비스를 추상화하여 일관된 방식으로 사용될 수 있도록 한것을 뜻합니다.
ex) PSA 예시
예를들어 스프링 데이터 JPA를 사용하면 특정 데이터베이스 기술에 종속되지 않는 코드를 작성할 수 있고, 이는 다른 DB로 마이그레이션이 필요할때 유용합니다.
어떤 DB를 사용하든 간에 JPA 스펙을 준수하는 DB로 마이그레이션을 하면, 대부분의 코드를 변경하지 않고도 DB를 변경할 수 있습니다.
또는
예를들어 MySQL을 사용하여 개발을 완료했는데 다른 디비로 바꿔야 한다면 기존의 코드를 전부 지우고 새로 작성하거나, 두 디비의 간에 사용방법이 다른 코드를 찾아서 일일히 수정해야 할 수도있습니다.
하지만 스프링은 데이터베이스 접근하는 방법을 규정한 인터페이스인 JDBC를 제공해 주기에 동일한 사용방법을 유지한채로 디비를 바꿀수 있습니다.
각 DB를 만든 회사들은 자신의 DB에 접근하는 드라이버를 JAVA 코드의 형태로 배포하는데, 이 드라이버에 해당하는 Java 코드의 클래스가 JDBC를 구현합니다.
따라서 JDBC를 기반으로 하여 DB접근 코드를 작성해두면, 이후에 DB를 바꿔도 기존에 작성한 DB 접근 로직을 그대로 사용할 수 있습니다.
IOC란 무엇인가요??
IOC란 프로그램의 제어 흐름을 코드 내에서(개발자) 직접 제어한 것이 아니라 외부에서 관리하는 것을 의미합니다.
스프링 애플리케이션에서는 빈의 생성과 의존관계 설정 등의 작업을 애플리케이션 코드 대신 스프링 컨테이너가 담당하고 있습니다.
이를 스프링 컨테이너가 코드 대신 오브젝트에 대한 제어권을 가지고 있다고 해서 IOC 컨테이너라고도 부릅니다.
꼬리질문- IOC 컨테이너란 무엇인가요?
스프링 애플리케이션에서는 객체의 생성과 관계 설정, 사용, 제거 등의 작업을 애플리케이션 코드 대신 스프링 컨테이너가 담당하는데, 이를 IOC 컨테이너라고 합니다.
IOC 컨테이너 장점은 스프링 애플리케이션의 객체(빈)을 IOC 컨테이너가 관리해줌으로써 개발자의 부담이 줄고 비즈니스 로직에 집중할 수 있다는 장점이 있습니다.
스프링 컨테이너는 빈들을 인스턴스 형식으로 관리함, 즉 한번 생성 후 여러 클라이언트가 하나의 같은 객체 인스턴스를 공유함
따라서 상태를 유지하게 끔 설계하면 안됨. restful이 아닌 stateless로 설계해야 함
특정 클라이언트에 의존적인 필드나, 특정 클라이언트가 값을 변경할 수 있는 필드가 존재하면 안됨
BeanFactory와 ApplicationContext의 차이가 무엇인가요??
빈 팩토리는 스프링 컨테이너의 최상위 인터페이스로 스프링 빈을 관리하고 조회하는 역할을 담당하고 있습니다.
애플리케이션 컨텍스트는 빈 팩토리의 기능을 모두 상속받아 제공할 뿐 아니라, 국제화 기능이나, 환경 변수(로컬,개발,운영등을 구분해서 처리) 등의 추가 부가 기능을 제공합니다.
DI가 무엇이죠?
DI란 객체의 의존관계를 객체 내부가 아닌 외부에서 주입해주는 것입니다.
이를 통해 각 객체가 가지는 역할에만 집중하도록 하고, 변경 사항이 생겼을때 유연하게 대처할 수 있게 됩니다.
꼬리질문 - DI이해를 위해 예시를 들어주시겠어요??
예를들어 버거 레시피라는 하나의 인터페이스가 있고 그 구현체로 일반버거 레시피, 치즈 버거 레시피가 있다고 가정해보겠습니다.
이때 버거 요리사라는 클래스가 있고 현재 이 버거 요리사는 구현체인 일반버거 레시피에 의존하고 있다고 해보겠습니다.
근데 만약 일반버거 레시피가 아닌 치즈 버거 레시피를 사용하려면 클라이언트인 버거 요리사 클래스의 코드를 수정해야 합니다.
하지만, 만약 버거 요리사 클래스가 구체적인 일반 버거 레시피 대신에 버거 레시피라는 인터페이스에 의존하게 된다면, 버거 레시피를 구현하는 어떤 객체라도 요리사 클래스는 그것을 사용할 수 있습니다. 이 경우, 요리사 클래스가 사용할 레시피를 바꾸고 싶을 때에는 그저 외부에서 다른 타입의 레시피 객체(예: 치즈 버거 레시피)를 요리사 클래스에 주입하면 됩니다. 이렇게 되면 요리사 클래스 코드 자체는 그대로 두고 외부에서 주입하는 객체만 바꿔서 요리사의 동작을 변경할 수 있게 됩니다
꼬리질문 - DI의 장점은 무엇이죠?
DI를 사용하여 구현을 했다면, 주입받는 대상이 변하더라도 해당 클래스 자체를 수정할 일이 없거나 줄어들기에 의존성이 줄어듭니다.
따라서 서로 결합도가 낮아지기에, 각 구성요소를 독립적으로 개발하고 테스트하는데 유리합니다.
그리고 코드에서 직접적으로 객체를 생성하거나 관리할 필요가 없으므로 코드가 더 간결해 집니다.
그러나 DI는 주로 런타임에 의존성을 주입하기에 컴파일 시점에 발생하는 오류를 잡아내기 어렵습니다(수정자나 필드의 경우)
DI 방법엔 어떤 것들이 있죠??
생성자 주입 방식은 객체가 생성될때 생성자를 통해서 의존성이 주입되는 방법입니다. 이 방식은 주입받을 의존성이 변하지 않아야 할때 주로 사용됩니다.
생성 시점에 의존성을 주입(new로 생성시 생성자 호출)받기에 final 키워드를 사용할 수 있어 불변성을 보장합니다.
세터 주입 방식은 주입받을 의존성이 실행 중에 변경될 수 있는 경우에 주로 사용됩니다. 생성 후에도 의존성을 변경할 수 있으므로 유연성이 있습니다.
필드 주입은 @Autowired를 통해 클래스의 필드에 직접 의존성이 주입하는 방식입니다.
꼬리질문 1 - 필드 주입에 장단점이 무엇이죠??
필드 주입시 코드가 간단해 진다는 장점이 있지만, Solid 원칙 중 단일 책임 원칙을 위반할 수 있고, final 키워드를 사용할 수 없어 불변성이 보장되지 않고, 객체가 변할 수 있습니다.
또한 Unit Test가 어렵습니다.
필드 주입 방식을 사용하면 필드가 변경될 수 있어 해당 클래스가 필드의 상태 관리 책임을 가지게 됩니다.
즉 핵심 비즈니스 로직에 집중하는 것 외에도 필드의 상태를 체크하고 관리하는 부가적인 책임을 가져야 하는 것입니다.
또한 필드 주입방식에서는 객체를 먼저 생성하고, 이후에 필드에 값을 주입하는 과정을 거치기 때문에 final 필드에 값을 주입할 수 없습니다.
final의 경우엔 선언과 동시에 초기화하거나, 생성자에서 초기화하는 것만 허용하기 때문입니다.
꼬리질문 2 - 수정자 주입의 장단점은 무엇이죠?
객체의 생명 주기 중에 의존성을 변경할 수 있고, 의존성이 생성시점에 필요하지 않은 경우 선택적으로 일부 의존성만 주입할 수 있다는 장점을 가집니다.
하지만 수정자 주입 방식시 의존성이 변경될 수 있어, 의존성의 상태를 체크해야 하는 부가적인 책임을 지닐수 있어 SRP에 위배됩니다.
또한 선택적인 의존성을 사용할 수 있기에 필수적이지 않은 의존성을 주입하지 않고도 객체를 생성할 수 있지만, 이렇게 선택적 의존성이 주입되지 않았을때, 해당 의존성을 사용하는 메서드가 호출되면 NPE가 발생할 수 있습니다.
(객체 생성 이후에 별도의 setter 메서드를 호출하여 필요한 의존성을 주입합니다.따라서 final 키워드 사용 불가)
꼬리질문 - 생성자 주입을 사용해야 하는 이유는?
생성자 주입 방법 사용시 객체가 생성되는 지점에 의존성을 생성자 인자로 주입받기에, 필드에 final 키워드를 사용할 수 있어 불변성을 보장할 수 있습니다.
또한 생성자 주입을 사용하면 순환참조를 컴파일 시점에 확인할 수 있습니다.
즉 클래스 생성과 동시에 의존성이 주입되어야 해서, 생성자 호출 시점에 모든 의존성이 주입되어야 하므로 만약 순환참조가 발생한다면 애플리케이션이 실행되지 않습니다.(컴파일 시점에 에러잡음)
(반면 필드 주입이나 수정자 주입은 객체가 생성된 후에 의존성 주입이 일어나므로 ㅇ런타임에 이를 알 수 있따)
그리고 생성자 주입 사용시 테스트 코드 작성 또한 용이합니다.
만약 테스트를 하고자 하는 클래스에 필드 주입이나 수정자 주입으로 빈이 주입되어 있으면 Mockito를 이용해 목킹후 테스트를 진행해야합니다.
하지만 생성자 주입의 경우엔 단순히 원하는 객체를 생성한 후 생성자에 넣어주는 방식으로도 진행이 가능합니다.
(DI Container 없이 직접 의존성 주입 가능)
꼬리질문 - 순환 참조가 무엇이고 언제 발생하는가?
순환 참조란 서로 다른 여러 빈들이 서로를 참조하고 있음을 의미한다. 필드 주입이나 수정자 주입은 객체 생성 후 비즈니스 로직 상에서 순환 참조가 일어나기 때문에 컴파일 단계에서 순환 참조를 잡아낼 수 없다. 반면에 생성자 주입을 사용하면 스프링 컨테이너가 빈을 생성하는 시점에 순환 참조를 확인하기 때문에 컴파일 단계에서 순환 참조를 잡아낼 수 있다
Spring IoC/DI의 동작 과정
먼저, 개발자는 각각의 컴포넌트(빈)와 이들 사이의 의존성에 대한 설정 정보를 XML, Annotation, Java Configuration 등을 통해 정의합니다.
이 설정 정보를 바탕으로 Spring IoC 컨테이너는 빈의 생명주기를 관리하고, 필요한 경우 의존성을 주입합니다.
컨테이너가 구동되면 개발자는 컨테이너로부터 필요한 빈을 가져와 사용합니다. 이때, 개발자는 빈의 생성과 소멸, 그리고 의존성에 대해 걱정할 필요가 없습니다.
DI와 IoC의 차이
IoC(Inversion of Control)는 더 넓은 개념으로, 제어 흐름의 주도권이 사용자(개발자)에서 프레임워크나 컨테이너로 이동한 것을 말합니다.
DI(Dependency Injection)는 IoC의 한 형태로, 객체 간의 의존성을 프레임워크나 컨테이너가 주입해주는 것을 말합니다
그러나 이 둘은 서로 독립적인 개념이며 DI가 반드시 IoC를 요구하는 것은 아닙니다. DI를 구현하는 방법은 여러가지가 있고 그 중 IoC 컨테이너를 사용하는 것이 하나의 방법일 뿐입니다. IoC 컨테이너 없이도 DI는 구현이 가능합니다. 예를 들어, 개발자가 직접 코드 내에서 객체를 생성하고 의존성을 주입하는 방식도 가능합니다. 이런 방식은 IoC의 개념을 적용하지 않지만, 의존성 주입(DI)을 구현하는 것입니다.
IoC는 제어의 역전에 초점을 둔다면, DI는 객체간의 의존성을 어떻게 관리할 것인지에 초점을 두는 것이라고 말할 수 있습니다.
Bean Definition이 무엇이죠?
BeanDefinition은 BeanFactoryPostProcessor가 읽을 수 있는 형태로 Bean 설정 메타데이터를 정의하는 인터페이스입니다.
Bean Definition은 Bean의 클래스 이름, Bean이 생성되는 방법, Bean 사이의 의존성, Bean의 범위(scope) 등을 정의합니다
스프링 컨테이너는 다양한 형식(ex: 자바 코드, XML, Groovy)의 설정 정보를 받아드릴 수 있게 유연하게 설계되어있습니다.
그렇다면 스프링은 어떻게 이런 다양한 설정 형식을 지원하는 것일까요??? 이 중심에는 BeanDefinition이라는 인터페이스가 있습니다.
스프링에서는 빈을 어떤 형식으로 관리하죠?
스프링에서는 빈을 싱글톤 형태로 관리합니다. 즉 스프링 컨테이너에서 생성된 빈은 기본적으로 싱글톤 스코프를 가지고, 같은 타입의 빈을 요청하면 항상 같은 인스턴스를 반환합니다.
이렇게 싱글턴 형태로 빈을 관리하면 메모리 사용량을 줄일 수 있고, 이미 생성된 빈을 재사용할 수 있어서 효율적입니다.
원래 스프링이 적용되어있지 않는 순수한 DI 컨테이너의 경우, 요청이 올때마다 객체를 새로 생성하였습니다.
즉 고객 트래픽이 초당 100이 나오면 초당 최소 100개의 객체가 생성되고 소멸되는 것이죠(메모리 낭비)
이를 해결하려면 해당 객체가 딱 1개만 생성되고, 공유하도록 설계하면 됩니다(싱글톤 적용).
싱글톤 패턴이란 클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴입니다. 이는 객체 인스턴스를 2개 이상 생성하지 못하도록 막기 위해 private 생성자를 사용해서 외부에서 임의로 new 키워드를 사용하지 못하도록 막습니다.
@Configuration과 @Bean의 차이점은 무엇인가요?
@Configuration은 해당 클래스가 빈 설정을 담당하는 클래스임을 스프링에 알려줍니다. 스프링은 이 클래스를 통해 빈을 생성하고 의존성을 주입합니다. 반면, @Bean은 해당 메서드가 빈을 생성하는 책임을 가지며, 이 메서드가 반환하는 객체를 스프링 빈으로 등록하게 됩니다. 이때 @Configuration이 붙은 클래스 내부의 @Bean 메서드는 항상 동일한 인스턴스를 반환하도록 보장하며, 이를 통해 스프링의 싱글톤 빈이 유지되게 합니다.
스프링에서 싱글톤 빈이 유지되는 원리를 설명해주세요.
스프링에서는 @Configuration이 붙은 클래스에 대해 CGLIB 바이트코드 조작 라이브러리를 사용하여 클래스를 상속받은 임의의 다른 클래스를 만듭니다
이 임의의 클래스는 싱글톤 빈이 유지되도록 도와주는 역할을 합니다.
참고 - 바이트 코드 조작이란
Java의 경우, JVM이 이해할 수 있는 바이트코드 형태로 컴파일이 되는데, 이렇게 컴파일된 바이트코드를 조작하여 새로운 클래스를 생성하거나 기존 클래스의 기능을 변경하는 것을 말합니다.
@Component랑 @ComponentScan @Configuration에 대해 설명해주세요.
@Component는 해당 클래스가 Spring에서 관리되는 빈임을 나타냅니다.
이 어노이션이 달린 클래스는 Spring 시작 시 빈으로 등록되고, 필요할때 Spring에 의해 자동으로 주입될 수 있습니다.
@ComponentScan은 Spring에서 @Component나 이로부터 파생된 어노테이션,@Service,@Repository,@Controller, @Configuration와 같은 어노테이션이 붙은 클래스를 찾아 Bean으로 등록하도록 지시하는 어노테이션입니다.
이를 통해 개발자는 직접 빈으로 등록하지 않아도, Spring이 애플리케이션의 구성 요소를 자동으로 찾아내고 관리하도록 할 수 있습니다.
@configuration은 해당 클래스가 Spring의 설정 클래스임을 나타내는 어노테이션입니다.
이러한 어노테이션이 붙은 클래스 안의 Bean 어노테이션이 붙은 메서드들은 각각 하나의 빈 객체를 생성하고 초기화하는 역할을 합니다.
또한 Configuration이 붙은 클래스는 스프링에 의해 CGLIB Proxy로 처리되므로, 같은 설정 클래스 내부에서 Bean 어노테이션이 붙은 메서드를 호출하면 항상 같은 인스턴스를 반환합니다.
조회 대상 빈이 2개 이상일때 해결하는 방법에는 어떤것이 있나
@Qualifier 어노테이션을 통해 추가 구분자를 붙여주거나, @Primary 어노테이션을 통해 우선순위를 정해줌으로서 해결할 수 있습니다.
꼬리질문 - 만약 동적으로 빈을 선택해야 할경우엔 어떻게 하나?
Map을 사용해서 해결 가능!
예를들어 문자열과 그에 대응하는 클래스를 넣어둠
스프링 빈의 생명주기에 대해 설명해주시겠어요?
스프링 애플리케이션의 실행은 스프링 IoC(Inversion of Control) 컨테이너의 생성으로 시작됩니다. 이 컨테이너는 Bean Definition에 정의된 대로 각 Bean 객체를 인스턴스화합니다.
Bean이 인스턴스화 된 후에는, IoC 컨테이너는 Bean Definition에 명시된 의존관계를 참조하여 의존성을 주입합니다.
모든 의존성 주입이 완료되면, 해당 Bean이 InitializingBean 인터페이스를 구현하고 있거나, 커스텀 초기화 메서드가 @Bean 어노테이션에 지정되었거나, @PostConstruct 어노테이션이 붙은 메서드가 있다면, 이들은 초기화 콜백 메서드로 작동하여 호출됩니다.
이 단계가 완료되면, 애플리케이션은 필요에 따라 IoC 컨테이너에서 Bean을 요청하여 사용하게 됩니다.
컨테이너가 종료되는 시점에, IoC 컨테이너는 Bean의 생명주기를 관리하는 과정으로서, 소멸 전 콜백 메서드를 호출합니다. 이 때는 DisposableBean 인터페이스의 destroy() 메서드, @PreDestroy 어노테이션이 붙은 메서드, 또는 @Bean 어노테이션에 지정한 사용자 정의 소멸 메서드가 호출됩니다.
이 단계에서 Bean은 자원 해제, 네트워크 연결 종료 등 소멸과정에 필요한 동작을 수행합니다. 이후, IoC 컨테이너 자체가 종료되며 이 과정에서 Singleton 범위의 모든 Bean들이 소멸됩니다.
빈 생명주기 콜백을 적용하는 방법엔 어떤 방법들이 있죠?
InitalizingBean, Disposable Bean과 같은 인터페이스를 구현하거나, Bean 어노테이션 설정 정보에 초기화 메서드, 종료 메서드를 지정하거나,
@PostConstruct, @PreDestroy 애노테이션을 지정함으로서 콜백을 적용할 수 있습니다.
꼬리질문 - 각 방법의 특징 간단히
인터페이스 방식은 프링 전용 인터페이스에 의존하게 되며, 초기화와 소멸 메서드의 이름을 변경할 수 없고, 외부 라이브러리에 적용할 수 없다는 단점이 있습니다. 이는 초기 스프링에서 사용되던 방식으로, 현재는 권장하지 않습니다.
Bean 어노테이션 설정 정보에서 적용하는 방법은 메서드 이름을 자유롭게 지정할 수 있고, 스프링에 의존하지 않습니다. 설정 정보를 활용하므로 코드를 수정할 수 없는 외부 라이브러리에서도 적용할 수 있습니다
@PostConstruct, @PreDestroy 어노테이션 사용 방식은 최신 스프링에서 가장 권장하는 방법으로, 어노테이션 하나를 붙이는 것으로 편리하게 콜백을 지정할 수 있습니다
이 어노테이션들은 JSR-250이라는 자바 표준을 준수한 것으로, 스프링이 아닌 다른 컨테이너에서도 동작합니다. 다만, 외부 라이브러리에 적용할 수 없다는 단점이 있습니다. 이때는 @Bean의 기능을 활용하는 것이 좋습니다.
빈 스코프에 대해 아시는대로 설명해주세요
빈 스코프는 빈이 존재할 수 있는 범위를 나타내는 개념입니다.
싱글톤 스코프의 경우 기본 스코프로, 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프입니다.
프로토타입 스코프의 경우, 스프링 컨테이너가 빈의 생성과 주입까지만 관여하고 더는 관리하지 않는 매우 짧은 범위의 스코프입니다.
이러한 프로토타입 스코프의 빈을 요청하게 되면, 스프링은 매 요청마다 항상 새로운 프로토타입의 빈을 생성해서 반환합니다.(개발자가 관리할 책임을 가짐)
웹 관련 스코프에는 Request와 Session 스코프가 있습니다.
Request 스코프는 HTTP 요청이 하나 들어오고 나갈때 까지 유지되는 스코프로, 각각의 HTTP 요청마다 별도의 빈 인스턴스가 생성되고, 관리됩니다.
Session 스코프는 웹 세션이 생성되고 종료될떄 까지 유지되는 스코프로 HTTP Session과 동일한 생명주기를 가지는 스코프입니다.
참고
프로토타입 빈과 싱글 톤 함께 사용시 프로토타입 빈이 매번 새로 생성되게 할려면 Provider를 사용함.
Provider는 지정한 빈을 컨테이너에서 대신 찾아주는 역할을 함
리퀘스트 스코프로 로그남길때 Provider를 통해 해결 가능(프록시를 통해서도 가능).
이는 리소스를 효율적으로 사용하고, 동시에 여러 요청이 들어오더라도 각 요청마다 독립적인 빈을 사용할 수 있도록 해줍니다
웹 세션이란 웹 서버에서 사용자가 브라우저를 통해 웹 서버에 접속할 때부터 브라우저를 닫거나 로그아웃하여 접속을 종료할 때까지 유지되는 사용자의 상태를 의미합니다. 웹이 기본적으로 상태를 유지하지 않는(stateless) 특성을 가지고 있는데, 이 상태를 유지하기 위해 사용하는 것이 세션입니다.
세션은 서버에 생성되어 서버 내부에 저장되고, 일정 시간동안 같은 사용자(정확히는 브라우저)로부터 들어오는 요청을 하나의 상태로 보고 유지하게 됩니다. 사용자가 로그인을 하면 해당 사용자의 세션 정보가 서버에 생성되고, 그 세션 정보와 연결되는 세션 ID가 사용자의 웹 브라우저 쿠키로 발급됩니다. 이후 사용자가 웹 서버에 접근할 때마다 이 세션 ID가 함께 전송되어 사용자를 식별하게 됩니다. 이렇게 함으로써, 로그인 정보, 사용자의 이전 작업 내역 등을 유지할 수 있습니다.
세션의 관리(생성, 삭제 등)는 서버의 책임이며, 세션의 유효 시간이 지나거나 사용자가 로그아웃을 하면 세션이 종료되게 됩니다. 이렇게 세션을 사용하여 사용자의 상태 정보를 유지함으로써 사용자 별로 개인화된 서비스를 제공하는 것이 가능해집니다.