본문 바로가기

분류 전체보기

(109)
빈 생명주기 콜백 빈 생명주기 콜백 시작 애플리케이션 시작 시점에 필요한 연결을 미리 해두고, 애플리케이션 종료 시점에 연결을 모두 종료하는 작업을 진행하려면, 객체의 초기화와 종료 작업이 필요하다.(안전하게 종료 처리시키는 것이 필요하다) (참고 : 마치 TCP/IP 연결할 때 오래 걸리니까 미리 DB 와 연결해놓는 데이터베이스 커넥션 풀과 같은 개념이라고 생각하면 된다.) [예제] 간단하게 외부 네트워크에 미리 연결하는 객체를 하나 생성한다고 가정해보자. (서버가 뜰 때 미리 외부 네트워크에 연결) 실제로 네트워크에 연결하는 것은 아니고, 단순히 문자만 출력하도록 했다. 이 NetworkClient 는 애플리케이션 시작 시점에 connect() 를 호출 -> 연결을 맺어두어야 하고, 애플리케이션이 종료되면 disCon..
같은 타입인 여러 개의 빈들을 조회하고 싶을 때 조회한 빈이 모두 필요할 때 의도적으로 정말 해당 타입의 스프링 빈이 다 필요한 경우도 있다. 예를 들어서 할인 서비스를 제공하는데, 클라이언트가 할인의 종류(rate - 비율로 할인, fix - 고정금액 할인)를 선택할 수 있다고 가정해보자. 스프링을 사용하면 소위 말하는 전략 패턴을 매우 간단하게 구현할 수 있다. package hello.core.autowired; import hello.core.AutoAppConfig; import hello.core.discount.discount.DiscountPolicy; import hello.core.member.Grade; import hello.core.member.Member; //import org.junit.jupiter.api.Assertio..
Lombok 라이브러리의 @RequiredArgsConstructor 롬복과 최신 트랜드 막상 개발을 해보면, 대부분이 다 불변이고, 그래서 다음과 같이 필드에 final 키워드를 사용하게 된다. 그런데 생성자도 만들어야 하고, 주입 받은 값을 대입하는 코드도 만들어야 하고...(매우 귀찮다) 필드 주입처럼 좀 편리하게 사용하는 방법은 없을까? -> 롬복으로 해결 가능하다! [롬복 추가] 프로젝트 시작할 때 롬복을 설치하지 않았기 때문에 build.gradle에 다음과 같은 코드를 추가하자(처음에 롬복을 추가했으면 이 과정을 뛰어넘어도 된다) //lombok 설정 추가 configurations{ compileOnly{ extendsFrom annotationProcessor } } dependencies { implementation 'org.springframework..
의존관계 주입 4가지 방법과 생성자 주입 권장 이유 다양한 의존관계 주입 방법 의존관계 주입은 크게 4가지 방법이 있다. (1) 생성자 주입 (2) 수정자 주입(setter 주입) (3) 필드 주입 (4) 일반 메서드 주입 [1] 생성자 주입 이름 그대로 생성자를 통해서 의존 관계를 주입 받는 방법이다. 지금까지 우리가 진행했던 방법이 바로 생성자 주입이다. private final MemberRepository memberRepository; private final DiscountPolicy discountPolicy; @Autowired public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) { this.memberRepository = memb..
예외 처리(@ExceptionHandler) - 예시 코드를 중심으로 스프링에서 예외 처리하는 3가지 방법 1. try - catch “각 메소드” 안에서 처리 2. 어노테이션 @ExceptionHandler -> 이 방법을 적용하여 설명 예정 “컨트롤러 자체”에서 처리 @controller, @RestController가 적용된 Bean 내에서 발생하는 예외를 잡아서 하나의 메서드에서 처리해주는 기능 Controller 내부에서 호출한 Service에서 예외가 발생 시 에러 처리 대상이 된다. 예외 처리 메시지를 예외 발생마다 새롭게 작성하면 번거롭고 복잡하다ㅜ 이젠 한 번에 처리해보자! 3. Global level에서 처리 → 추천 클라이언트에서 전달되기 직전에 처리 [ 실행흐름 ] [컨트롤러에서 예외 발생] 에러가 터지면 Dispatcher Servlet을 통해 Ex..
@ComponentScan의 탐색 위치와 대상 탐색 위치와 기본 스캔 대상 탐색할 패키지의 시작 위치 지정 모든 자바 클래스를 다 컴포넌트 스캔하면 시간이 오래 걸린다. 그래서 꼭 필요한 위치부터 탐색하도록 시작 위치를 지정할 수 있다. @ComponentScan( basePackages = "hello.core", } basePackages : 탐색할 패키지의 시작 위치를 지정한다. 이 패키지를 포함해서 하위 패키지를 모두 탐색한다. 예를 들어 basePackages = "hello.core.member"라고 한다면 member 패키지를 포함한 하위 패키지들만 탐색한다. basePackages = {"hello.core", "hello.service"} 이렇게 여러 시작 위치를 지정할 수도 있다. basePackageClasses = AutoApp..
@ComponentScan과 @Autowired 스프링은 설정 정보가 없어도 1) 자동으로 스프링 빈을 등록하는 컴포넌트 스캔이라는 기능을 제공한다. 2) 또 의존관계도 자동으로 주입하는 @Autowired 라는 기능도 제공한다. ✔️ 컴포넌트 스캔의 필요성 스프링 빈을 등록할 때는 자바 코드의 @Bean이나 XML의 등을 통해서 설정 정보에 직접 등록할 스프링 빈을 나열하는 방법이 있다. 하지만 등록해야 할 스프링 빈이 많아진다면 하나씩 다 입력하는 것은 한계가 있고 누락할 가능성도 있다. => 스프링은 설정 정보가 없어도 자동으로 스프링 빈을 등록하는 컴포넌트 스캔이라는 기능을 제공한다. ✔️ 컴포넌트 스캔 방법 ✏️[ 1 ] 다음과 같이 설정 정보 클래스에 @ComponentScan 어노테이션을 붙이면 된다. @Configuration @Comp..
@Configuration의 싱글톤 보장 스프링을 배우면 "스프링이 ~하게 관리해준다."와 같이 뭘 알아서 해준다는 것을 많이 들어봤을 것이다. 필자는 '스프링이 알아서 다 해준다고?? 어떻게??' 라는 의문점이 있었다. 뭐 스카이캐슬에 김주영쌤 같은 느낌 하지만 @Configuration 을 배우면서 어떤 식으로 스프링이 관리해준다는 말의 의미를 깨닫게 되었다. 앞으로 이어질 @Configuration에 대한 내용을 통해 독자도 필자와 같은 깨달음을 이해할 수 있길.. @Configuration 을 적용한 AppConfig에는 놀라운 비밀이 있다. @Configuration 을 붙이면 바이트코드를 조작하는 CGLIB 기술을 사용해서 싱글톤을 보장한다. 사실 개발자가 AppConfig라는 설정 정보를 입력하더라도 @Configuration 을 ..
싱글톤 방식 주의점_무상태(stateless) 싱글톤 방식의 주의점!!(완전 중요) 싱글톤 패턴이든, 스프링 같은 싱글톤 컨테이너를 사용하든, 객체 인스턴스를 하나만 생성해서 공유하는 싱글톤 방식은 여러 클라이언트가 하나의 같은 객체 인스턴스를 공유하기 때문에 싱글톤 객체는 상태를 유지(stateful)하게 설계하면 안된다. 💡 무상태(stateless)로 설계해야 한다! 특정 클라이언트에 의존적인 필드가 있으면 안된다. 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안된다! 가급적 읽기만 가능해야 한다.(가급적 수정하지 않도록 해야 한다) 필드 대신에 자바에서 공유되지 않는, 지역변수, 파라미터, ThreadLocal 등을 사용해야 한다. 스프링 빈의 필드에 공유 값을 설정하면 정말 큰 장애가 발생할 수 있다!!! [상태를 유지할 경우 발생..
싱글톤 패턴과 스프링 컨테이너 👍 웹 애플리케이션과 싱글톤 스프링은 태생이 기업용 온라인 서비스 기술을 지원하기 위해 탄생했다. 대부분의 스프링 애플리케이션은 웹 애플리케이션이다. (물론 웹이 아닌 애플리케이션 개발도 얼마든지 개발할 수 있다.) 웹 애플리케이션의 특성 중 하나는 '여러 고객이 동시에 요청을 한다'는 것이다. 만약 요청을 할 때마다 객체가 생성된다면 3명의 사람이 memberService에 대한 요청이 있을 때 객체 3개가 만들어진다.( 만약 요청이 1초에 5만개라면 객체가 5만 객체가 생성되어야 한다. 비효율적이다.) 전 포스팅에서 만들었던 스프링 없는 순수한 DI 컨테이너인 AppConfig는 요청을 할 때 마다 객체를 새로 생성한다. 아래의 코드는 순수한 DI 컨테이너이며, 요청마다 객체를 생성하는 것을 구현하여..