2022 11 12
2022-11-12¶
빈 스코프¶
- 참고: https://velog.io/@probsno/Bean-%EC%8A%A4%EC%BD%94%ED%94%84%EB%9E%80
- 정의
- 빈이 사용되어지는 범위
- 빈 스코프 종류
- Singleton : 스프링 IoC 컨테이너당 하나의 인스턴스만 사용
- Prototype : 매번 새로운 빈을 정의하여 사용
- Request : HTTP 라이프사이클 마다 한 개의 빈을 사용
- Session : HTTP 세션마다 한 개의 빈을 사용
- Application : ServletContext 라이프사이클 동안 한 개의 빈을 사용
- Websocket : Websocket 라이프사이클 안에서 한 개의 빈을 사용
-
Prototype 스코프를 사용하는 방법
- 정의하는 법
- 근데... 싱글톤 빈의 컴포넌트로 Prototype 스코프 빈을 쓰면 어쩌지?
- 싱글톤 스코프의 빈이 프로토타입 빈을 주입받으면 싱글톤 프로토타입 빈은 매번 바뀌지 않고 같은 빈이 쓰임
- 프록시 모드로 해결하기!
- ApplicationContext가 빈을 처음 생성시, proto 빈을 주입받지 않고,
- proto 클래스 상속받은 프록시를 빈으로 등록해
- 프록시에서 내부적으로 매번 새로운 proto 빈을 사용하게 끔 설계됨
스프링 사용자들의 주입 방식¶
- 참고: https://velog.io/@sh95119/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%82%AC%EC%9A%A9%EC%9E%90%EB%93%A4%EC%9D%B4-%EC%84%A0%ED%98%B8%ED%95%98%EB%8A%94-%EC%A3%BC%EC%9E%85-%EB%B0%A9%EC%8B%9D
- 생성자로 주입하자
- 순환참조 방지
- 테스트에 용이
- 클린한 코드 유지
- 불변성 보장 가능
@ComponentScan¶
- 참고: https://velog.io/@hyun-jii/%EC%8A%A4%ED%94%84%EB%A7%81-component-scan-%EA%B0%9C%EB%85%90-%EB%B0%8F-%EB%8F%99%EC%9E%91-%EA%B3%BC%EC%A0%95
- 참고: https://jjingho.tistory.com/9
- 정의
- 빈으로 등록될 준비를 마친 클래스들을 스캔하여, 빈으로 등록해주는 것
@Component가 붙은 클래스들이 빈으로 등록 대상이 된다
- ComponentScan 하는 방법
- xml 파일에 설정
<context:component-scan base-package="com.rcod.lifelog"/>- base package 기준으로 클래스들을 스캔하여 빈으로 등록 가능
- include-filter, exclude-filter 등을 통해 특정 객체 포함/제외 설정 가능
- 자바 파일 안에서 설정
- 특정 패키지를 basePackage로 잡고 ComponentScan을 통한 빈 등록
- xml 파일에 설정
- ComponentScan 동작 과정
- ConfigurationClassParser가
@Configuration클래스를 파싱 - ComponentScan 설정을 파싱
- base-package에 명시된 패키지를 기준으로 ComponentScanAnnotationParser가 스캔하기 위한 설정 파싱
- base-pacakge 설정을 바탕으로 모든 클래스를 로딩
- ClassLoader가 로딩한 클래스들을 BeanDefinition으로 정의
- 생성할 빈에 대한 정의를 토대로 빈 생성
- ConfigurationClassParser가
- ComponentScan 동작 원리
@ComponentScan은 BeanFactoryPostProcessor를 구현한 ConfigurationClassPostProcessor에 의해 동작- 컴포넌트 스캔을 해서 Bean으로 등록해줌
- vs
@Autowired@Autowired는 등록된 다른 Bean을 찾아 BeanPostProcessor의 구현체를 적용해 의존성 주입을 적용함@ComponentScan은 다른 Bean들을 찾아 BeanFactoryPostProcessor의 구현체를 적용해 Bean을 등록시켜줌
어플리케이션 컨텍스트¶
- 참고: https://mangkyu.tistory.com/151
- 어플리케이션 컨텍스트
- 빈의 생성과 관계 설정 등의 제어를 담당하는 IoC 컨테이너인 빈 팩토리가 존재
- 빈의 생성/관계 설정 외에 추가적인 기능이 필요! Spring에서는 빈 팩토리를 상속받아 확장한 어플리케이션 컨텍스트를 사용함
- 어플리케이션 컨텍스트는...
- 별도의 설정 정보 참고
- IoC 적용하여 빈의 생성, 관계 설정 등의 제어 작업 총괄
- 직접 오브젝트를 생성하고 관계를 맺어주는 코드가 없고, 그런 생성 정보와 연관관계 정보에 대한 설정을 읽어 처리함
- 생성 정보, 연관관계 정보에 대한 설정을 참고하여 처리함 =>
@Configuration
- 클라이언트의 Bean 요청 시 처리 과정
- ApplicationContext는
@Configuration이 붙은 클래스를 설정 정보로 등록해두고,@Bean이 붙은 메서드의 이름으로 빈 목록 생성 - 클라이언트가 해당 빈 요청
- ApplicationContext는 자신의 빈 목록에서 요청한 이름이 있는지 찾음
- ApplicationContext는 설정 클래스로부터 빈 생성을 요청, 생성된 빈을 돌려줌
- ApplicationContext는
- 어플리케이션 컨텍스트의 장점
- 클라이언트는
@Configuration이 붙은 구체적인 팩토리 클래스를 알 필요가 없음- 원하는 객체를 가져오려면 어떤 팩토리 클래스에 접근해야 하는지 알아야하는데...
- 어플리케이션 컨텍스트를 사용하면 팩토리가 아무리 많아져도 직접 접근할 필요 X
- 어플리케이션 컨텍스트는 종합 IoC 서비스를 제공해줌
- 객체 생성과 관계 설정이 전부가 아님...
- 객체가 만들어지는 방식/시점/전략 등을 다르게 가져갈 수 있고,
- 그 외에도 후처리나 정보의 조합 인터셉트 등과 같은 다양한 기능이 존재
- 어플리케이션 컨텍스트를 통한 다양한 빈 검색 방법을 제공할 수 있음
- 어플리케이션 컨텍스트에서 빈 목록을 관리하여 빈의 이름이나 타입, 어노테이션 설정 등으로 빈을 찾을 수 있음
- dependency lookup!
- 클라이언트는
- Spring에서의 Singleton
- Spring에서 싱글톤
- 여러번 빈을 요청하더라도 매번 동일한 객체
- 대규모 트래픽 처리할 수 있도록 하기 위함
- 대규모 트래픽 처리하려고 Controller, Service, Repository 등 나뉘게 됨
- 매번 클라이언트에서 요청이 올 때 마다 빈 새로 만들면 부하 감당 빡셈
- 빈을 싱글톤 스코프로 관리하여 1개의 요청 왔을 때 여러 쓰레드가 빈을 공유해 처리하도록 하였음
- Spring에서 싱글톤
- Spring Singleton vs Java Singleton
- Java Singleton의 단점
- private 생성자를 가져 상속이 불가능
- 테스트하기 힘듦
- 서버 환경에서는 싱글톤이 1개만 생성됨을 보장하지 못함
- 전역 상태를 만들 수 있기에 객체지향적이지 못함
- Spring은 직접 싱글톤 형태의 오브젝트 만들고 관리하는 기능을 제공 => 싱글톤 레지스트리
- 싱글톤 생성하고, 관리하고, 공급하는 컨테이너
- static 메서드나 private 생성자 등을 사용하지 않아 객체지향적 개발을 할 수 있음
- 테스트 하기 편함!
- Spring singleton은 내부에 상태를 갖지 않는 무상태 방식으로 만들 것!
- Java Singleton의 단점
JVM memory leak¶
GC와 Java Reference¶
- 참고: https://d2.naver.com/helloworld/329631
- GC 개요
- heap 내의 객체 중에서 garbage를 찾아냄
- 찾아낸 garbage를 처리해 힙의 메모리 회수
- GC와 Reachability
- Reachability라는 개념...
- 유효한 참조 O => reachable
- 유효한 참조 X => unreachable
- 객체는 참조 사슬을 이룸
- 유효한 참조 여부를 파악하려면 최초의 참조가 있어야 함 (Root Set)
- 스택 참조
- 네이티브 스택 (JNI 참조)
- Static 영역의 참조

- root set으로 시작한 참조들은 Strong reference
- 유효한 참조 여부를 파악하려면 최초의 참조가 있어야 함 (Root Set)
- Reachability라는 개념...
- Soft, Weak, Phantom Reference
- java.lang.ref 에서 soft reference/weak reference/phantom reference를 클래스 형태로 제공함
- weak reference는 참조 대상인 객체를 캡슐화한 WeakReference 객체를 생성 => GC의 특별 취급 대상
-
코드를 통해 봅시다

new WeakReference(): reference objectnew Sample(): referent
- java.lang.ref 에서 soft reference/weak reference/phantom reference를 클래스 형태로 제공함
- Reference와 Reachability
- 원래 GC 대상 여부는 reachable/unreachable
- java.lang.ref 패키지를 통해 객체들을 더 세분화하여 분류 가능
- strongly reachable
- softly reachable
- weakly reachable
- phantomly reachable
- GC 동작시 unreachable 객체 뿐만 아니라 weakly reachable 객체도 GC에서 회수됨
- weakly의 경우 root set으로 부터 시작된 참조 사슬에 포함되어도 회수됨
- 참조는 가능하지만 반드시 항상 유효할 필요없는 LRU 같은 임시 객체 저장 구조 쉽게 만들 수 있음

- Strengths of Reachability
- strongly reachable: root set으로 시작해서 어떤 reference object도 중간에 끼지 않은 상태로 참조 가능
- 객체까지 도달하는 여러 참조 사슬 중 reference object가 없는 사실이 하나라도 있는 객체
- softly reachable: strongly reachable 객체가 아닌 객체 중에서 weak reference, phantom reference 없이 soft reference만 통과하는 참조 사슬이 하나라도 있음
- soft reference만 통과하는 참조 사슬이 하나라도 있음
- weakly reachable: strongly reachable 객체도, softly reachable 객체도 아닌 객체 중에서 phantom reference 없이 weak reference만 통과하는 참조 사슬이 하나라도 있음
- weak reference만 통과하는 참조 사슬이 하나라도 있음
- phantomly reachable: root로 부터 strongly/softly/weakly reachable 객체 모두 해당되지 않음
- finalize 되었지만, 메모리가 아직 회수되지 않았음
- unreachable: root set으로 부터 시작되는 참조 사슬로 참조되지 않는 객체
- strongly reachable: root set으로 시작해서 어떤 reference object도 중간에 끼지 않은 상태로 참조 가능
- Softly Reachable과 SoftReference
- 오직 SoftReference 객체로만 참조된 객체는 힙에 남아있는 메모리의 크기와 해당 객체의 사용 빈도에 따라 GC 여부가 결정됨
- Softly reachable 객체는 GC가 동작할 때마다 회수되지 않으며, 자주 사용될수록 더 오래 살아남을 것
- Oracle Hotspot VM에서는 softly reachable 객체의 GC를 조절하기 위한 옵션을 제공
-XX:SoftRefLRUPolicyMSPerMB=<N>// 옵션 기본값 1000
- Softly reachable 객체의 GC 여부는 설정한 숫자에 따라 다음 수식에 의해 결정
(마지막 strong reference가 GC된 때로 부터 지금까지의 시간) > (옵션 설정값 N) * (힙에 남아있는 메모리 크기)- 옵션 설정값: 1000
- 메모리: 100MB
- 수식 = 1000ms/MB * 100MB = 100,000ms = 100sec
- 100초 이상 사용되지 않으면 GC가 회수해감!
- Oracle Hotspot VM에서는 softly reachable 객체의 GC를 조절하기 위한 옵션을 제공
- Weakly Reachable과 WeakReference
- weakly reachable 객체는 GC를 수행할 때마다 회수 대상이 됨
- 언제 회수될지는 확실하지 않음 => GC 알고리즘 별로 다 다름
- LRU 캐시와 같은 어플리케이션은 weakly reachable이 유리해서 대체로 WeakReference 사용
- ReferenceQueue
- SoftReference/WeakReference 객체가 참조하는 객체가 GC의 대상이 되면...
- SoftReference/WeakReference의 참조는 null,
- SoftReference/WeakReference 객체 자체는 GC에 의해 ReferenceQueue에 enqueue
- ReferenceQueue의 poll()/remove()를 통해 reference object가 enqueue 되었는지 확인하여 softly reachable, weakly reachable 객체가 GC 되었는지 판단 => 후처리 가능
- ReferenceQueue와 WeakReference를 통한 간단한 캐시 구현 가능
- PhantomReference는 무조건 ReferenceQueue를 사용해야함
- SoftReference/WeakReference 객체가 참조하는 객체가 GC의 대상이 되면...
- Phantomly Reachable과 PhantomReference
- GC 대상 객체를 처리하는 작업 -- 할당된 메모리 회수하는 작업 각각 별도!
- GC 대상 여부를 결정하는 부분에 관여하는 softly reachable, weakly reachable과 달리, phantomly reachable은 파이널라이즈와 메모리 회수 사이에서 관여
- GC가 객체를 처리하는 순서
- Soft References => 메모리 크기/해당 객체의 사용 빈도에 따라 GC 여부 결정
- Weak References => GC 수행시 마다 회수 대상이 되지만, GC 알고리즘 별로 다 다름
- 파이널라이즈 => 회수할 메모리 결정. Strong Reference는 당연히 회수, 1/2번에서 고른것도 대상
- Phantom References
- 메모리 회수
- 요약
- Java GC는 GC 대상 객체를 찾는다
- 대상 객체를 Finalization하고, 할당된 메모리를 회수하는 작업으로 구성된다
- 어플리케이션은 사용자 코드에서 Reachability를 조절하여 Java GC에 일부 관여할 수 있다
- 객체의 Reachablility를 조절하기 위해 java.lang.ref 패키지의 SoftReference, WeakReference, PhantomReference, ReferenceQueue 등 사용
-
참조 유형
- Strong References
- 기본 참조 유형
MyClass obj = new MyClass();
- Soft References
- JVM의 메모리가 부족한 경우에만 힙 영역에서 제거됨
- 아니라면 굳이 제거 안함
- Weak References
- 대상 객체 참조하는 경우 WeakReference만 존재한다면 GC 대상 => 다음 GC에서 무조건 힙 메모리에서 제거
- Phantom References
- Strong References
성능테스트¶
외부 시스템 장애에 대처하는 우리의 자세¶
- 참고: https://techblog.woowahan.com/6447/
- 의존성 제거
- 이 연동이 꼭 필요한지 고민할 것
- 안정성 신뢰도, 연동 목적, 리스크 감수할 만큼의 가치가 있는지를 명확히 할 것!
- 의존 관계를 맺지 않는 것이 우리 서비스의 안정성을 높이는 데 가장 좋은 방법일수도 있음
- 벤더 이중화
- 널리 사용되는 서비스의 경우, 여러 업체에서 비슷한 기능 제공
- 지도, pg, 문자 등이 대표적
- 따라서 이중화 구현해두는 것이 좋은 방식!
- 장애 격리
- 이중화에 비용이 많이 들거나, 다른 벤더가 없으면 이중화 못하잖아?
- 외부 시스템의 장애가 연동과 관련 없는 부분으로 전파되지 않도록 장애를 격리하는 것이 중요
- 특정 기능이 일부 동작하지 않거나 기능이 저하되더라도 사용자가 최소 기능 사용할 수 있도록 하는 것이 핵심!
- 최대한 한 기능의 장애가 다른 기능의 장애까지 이어지지 않도록 고려해야 함!
- 미작동 감내
- AWS, GCP 자체가 뻑나면... 모니터링 열심히하시고, 서비스 담당부서에 빠르게 확인하는 핫라인 운영하자!