Spring/스프링 핵심 원리 - 기본편 18

빈 스코프 - 웹 스코프

지금까지 싱글톤과 프로토타입 스코프를 학습했다. 싱글톤은 스프링 컨테이너의 시작과 끝까지 함께하는 매우 긴 스코프이고, 프로토타입은 생성과 의존관계 주입, 그리고 초기화까지만 진행하는 특별한 스코프이다. 이번에는 웹 스코프에 대해서 알아보자 웹 스코프의 특징 웹 스코프는 웹 환경에서만 동작한다. 웹 스코프는 프로토타입과 다르게 스프링이 해당 스코프의 종료 시점까지 관리한다. 따라서 종료 메서드가 호출된다. 웹 스코프 종류 request: HTTP 요청 하나가 들어오고 나갈 때 까지 유지되는 스코프, 각각의 HTTP 요청마다 별도의 빈 인스턴스가 생성되고, 관리된다. session: HTTP Session과 동일한 생명주기를 가지는 스코프 application: 서블릿 컨텍스트( ServletContext..

빈 스코프 - 프로토타입 스코프와 싱글톤 빈 함께 사용시 Provider로 해결

ObjectFactory, ObjectProvider 의존관계를 외부에서 주입(DI) 받는 게 아니라 이렇게 직접 필요한 의존관계를 찾는 것을 Dependency Lookup (DL) 의존관계 조회(탐색) 이라 한다. 지정한 빈을 컨테이너에서 대신 찾아주는 DL 서비스를 제공하는 것이 바로 ObjectProvider이다. 참고로 과거에는 ObjectFactory가 있었는데, 여기에 편의 기능을 추가해서 ObjectProivder가 만들어졌다. package hello.core.scope; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.ObjectProvider; import org.springframework.bea..

빈 스코프 - 프로토타입 스코프, 싱글톤 빈과 함께 사용시 문제점

빈 스코프란? 스코프는 번역 그대로 빈이 존재할 수 있는 범위를 뜻한다. 스프링은 다음과 같은 다양한 스코프를 지원한다. 싱글톤 : 기본 스코프, 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프이다. 프로토타입 : 스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는 매우 짧은 범위의 스코프이다. 웹 관련 스코프 request : 웹 요청이 들어오고 나갈 때까지 유지되는 스코프이다. session : 웹 세션이 생성되고 종료될 때 까지 유지되는 스코프이다. application : 웹의 서브릿 컨텍스트와 같은 범위로 유지되는 스코프이다. 프로토타입 스코프 싱글톤 스코프의 빈을 조회화면 스프링 컨테이너는 항상 같은 인스턴스의 스프링 빈을 반환한다. 반..

빈 생명주기 콜백

빈 생명주기 콜백 시작 데이터베이스 커넥션 풀이나, 네트워크 소켓처럼 애플리케이션 시작 시점에 필요한 연결을 미리 해두고, 애플리케이션 종료 시점에 연결을 모두 종료하는 작업을 진행하려면, 객체의 초기화와 종료 작업이 필요하다. 간단하게 외부 네트워크에 미리 연결하는 개체를 생성한다고 가정해보자. 단순히 문자만 출력하도록 했다. 아래 예제를 보자 1) 네트워크 클라이언트 객체 생성 package hello.core.lifecycle; public class NetworkClient { private String url; public NetworkClient() { System.out.println("생성자 호출, url" + url); connect(); call("초기화 연결 메세지"); } publi..

의존관계 자동 주입 - 자동, 수동의 올바른 실무 운영 기준

편리한 자동 기능을 기본으로 사용하자 스프링이 나오고 시간이 갈수록 점점 자동을 선호하는 추세다. 스프링은 @Componet 뿐만 아니라, @Controller, @Service, @Repository처럼 계층에 맞추어 일반적인 애플리케이션 로직을 자동으로 스캔할 수 있도록 지원한다. 거기에 더해서 최근 스프링 부트는 컴포너틑 스캔을 기본으로 사용하고, 스프링 부트의 다양한 스프링 빈들도 조건이 맞으면 자동으로 등록하도록 설계했다. 그러면 수동 빈 등록은 언제 사용하면 좋을까? 애플리케이션은 크게 업무 로직과 기술 지원 로직으로 나눌 수 있다. 업무 로직 빈: 웹을 지원하는 컨트롤러, 핵심 비즈니스 로직이 있는 서비스, 데이터 계층의 로직을 처리하는 리포지토리 등이 모두 업무 로직이다. 보통 비즈니스 요..

의존관계 자동 주입 - 애노테이션 직접 만들기

@Qualifier("mainDiscountPolicy") 이렇게 문자를 적으면 컴파일 시 타입 체크가 안된다. 이렇게 될 경우 mainDisccountPolicy처럼 오타가 나도 해당하는 코드가 문제가 발생했는지 모르고 진행될 경우가 발생한다. 애노테이션을 직접 만들어서 변경을 해주자. 1) MainDiscountPolicy를 만들자 애노테이션은 상속이라는 개념이 없다. 이렇게 여러 애노테이션을 모아서 사용하는 기능은 스프링이 지원해 주는 것이다. package hello.core.annotation; import org.springframework.beans.factory.annotation.Qualifier; import java.lang.annotation.*; @Target({ElementTyp..

의존관계 자동 주입 - 조회 빈 이 2개 이상으로 충돌이 났을때

@Autowired는 타입(Type)으로 조회한다. 때문에 부모 클래스를 상속받은 자식 클래스라면 @Componet를 통해서 언제든지 충돌이 나는 경우가 발생한다. 아래 예를 보자. package hello.core.order; import hello.core.discount.DiscountPolicy; import hello.core.member.*; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @Component @RequiredArgsConstructor public class OrderServiceImpl implements OrderService{ private final Member..

의존관계 자동 주입 - 생성자 주입을 선택해라! & 롬복과 최신 트랜드

1) DI를 사용할 때 생성자 주입을 선택해라! 과거에는 수정자 주입과 필드 주입을 많이 사용했지만, 최근에는 스프링을 포함한 DI 프레임워크 대부분이 생성자 주입을 권장한다. 그 이유는 다음과 같다. 불변 대부분의 의존관계 주입은 한번 일어나면 애플리케이션 종료 시점까지 의존관계를 변경할 일이 없다. 오히려 대부분의 의존관계는 애플리케이션 종료 전까지 변하면 안 된다. 수정자 주입을 사용하면 setXxx메서드를 public으로 열어두어야 한다. 이는 누군가의 실수로 변경할 수 도 있고, 변경하면 안 되는 메서드를 열어두는 것은 좋은 설계 방법이 아니다. 생성자 주입은 객체를 생성할 때 딱 1번만 호출되므로 이후에 호출되는 일이 없다. 따라서 불변하게 설계할 수 있다. 2) 롬복 사용법 개발을 해보면, ..

컴포넌트 스캔 - 컴포넌트 스캔과 의존관계 자동 주입 시작하기

지금 까지 우리는 스프링 빈을 등록할 때 @Bean이나 Xml의 Bean을 사용해서 빈을 등록했다 현재 예제는 몇개가 안되어있지만, 이렇게 등록해야 될 스프링 빈이 수십, 수백 개가 된다면 누락 문제와 더불어 너무 귀찮을 것이다. 그래서 스프링은 설정 정보가 없어도 자동으로 스프링 빈을 등록하는 컴포넌트 스캔이라는 기능을 제공한다. 또 의존관계 주입을 자동으로 해주는 @Autowired라는 기능도 제공한다. 1) AutoAppConfig 작성 package hello.core; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import..

싱글톤 컨테이너 - @Configuration과 싱글톤

1) AppConfig를 보자 AppConfig는 일반적으로 자바를 배운 사람이라면 객체가 계속 생성될 것으로 예상한다. 예를 들면 @Bean memberService -> new MemoryMemberRepository() 호출 @Bean orderService -> new MemoryMemberRepository() 호출 하지만 위의 예측은 다르다. 이제부터 어떻게 다른 것인지 확인해보도록 하겠다. package hello.core; import hello.core.discount.DiscountPolicy; import hello.core.discount.RateDiscountPolicy; import hello.core.member.MemberRepository; import hello.core...