스프링 핵심 원리 고급편 (김영한 강의) - 섹션 1 : 예제 만들기
섹션 목적 : 예제 프로젝트를 만들고, 점차 하나씩 발전시켜보자
1. 예제 프로젝트 만들기 - V0
(1) 상품을 주문하는 프로세스를 가정하고, 일반적인 웹 애플리케이션 흐름인 Controller -> Service -> Repository로 이어지는 흐름을 최대한 단순하게 만들어보자
(2) OrderRepository
① 상품을 저장하는데 약 1초정도 걸린다고 가정(Thread.sleep(1000))
② itemId가 "ex"인 경우 예외 발생
(3) OrderService
① OrderRepository에 저장
(4) OrderController
① OrderService에 orderItem 호출
2. 로그 추적기 - 요구사항 분석
(1) 각 메서드마다 실행시간을 로그로 출력하는 기능을 구현해보자
(2) ex)
[11111] Controller
[11111] |--> Service
[11111] |<-- Service time = 1004ms
[11111] Controller time = 1014ms
3. 로그 추적기 V1 - 프로토타입 개발
(1) TraceId : id, level을 필드로 가지고 있음
(2) TraceStatus : TraceId, startTimeMs, message를 필드로 가지고 있음
(3) HelloTraceV1
① begin(message) : 새로운 TraceId를 만들고 이를 이용해서 새로운 TraceStatus를 생성함. 그리고 시작 로그 출력
② end(status) : TraceStatus의 시작시간과 현재시간의 차를 계산해서 로그 출력
③ exception(status, e) : 예외가 발생한 경우 예외 로그도 함께 출력
4. 로그 추적기 V1 - 적용
(1) Controller, Service, Repository에 HelloTraceV1을 주입함
(2) 이 후 try-catch문으로 로그 시작 -> 비즈니스 로직 -> 로그 끝의 프로세스를 거침
① try : trace.begin() -> 로직 -> trace.end(status)
② catch : trace.exception(status, e)를 하고 throw e를 함(예외를 먹어버리면 애플리케이션 흐름에 영향을 주므로)
(3) 이렇게 할 경우 시간 로그는 잘 출력됨
(4) 하지만, Controller, Service, Repository 모두 id가 다르고, level은 항상 0임
(5) id와 level을 동기화해주어야 함
5. 로그 추적기 V2 - 파라미터로 동기화 개발
(1) 트랜잭션 id와 level을 동기화하는 가장 단순한 방법은 다음 로그에 파라미터로 넘겨주면 됨
(2) TraceId에 이 정보가 담겨 있으므로, TraceId를 넘겨주자
(3) HelloTraceV2에 beginSync(beforeTraceId, message)를 만들고, 넘겨받은 traceId로 id를 유지하고 level은 1증가시킴
(4) 이렇게 하면 transaction id를 유지하고 level은 다르게 할 수 있음
6. 로그추적기 V2 - 적용
(1) 이제 Controller -> Service -> Repository로 넘어갈 때, TraceId를 같이 넘겨준다
(2) 이렇게 하면, 모든 요구사항을 만족하는 로그 추적기를 완성
(3) 하지만 문제점
① TraceId의 동기화를 위해 모든 파라미터를 추가해야함. 인터페이스까지 고쳐야함
② 처음 시작할 때는 begin()을 그 다음부터는 beginSync()를 사용해야 함. 만약 바로 Service를 호출할 경우 넘겨진 TraceId가 없음
(4) 이제 앞으로 하나씩 해결해보자
이펙티브 자바 - 아이템 8 : finalizer와 cleaner 사용을 피하라
- 자바는 finalizer와 cleaner라는 두 가지 객체 소멸자를 제공한다
- 하지만 이 둘은 문제가 있다
① Java에서 접근할 수 없게 된 객체를 회수해 가는 역할은 가비지 컬렉터가 하는데, finalizer와 cleaner는 GC가 제때 회수해간다는 보장이 없다 -> 계속 회수되기만을 기다리다가 OutOfMemoryError가 발생할 수 있다
② finalizer를 사용해서 객체를 파괴하면 성능이 낮아진다
③ finalizer는 보안 문제도 발생할 수 있다
- 그렇다면 해결책은?
- AutoCloseable을 implements하고 클라이언트가 try-with-resources를 이용해서 인스턴스를 다 쓰고나면 close 메소드가 호출되게끔 한다
- cleaner나 finalizer는 혹시나 close 메서드가 호출하지 않을 것에 대비하는 안전망 역할 정도로 사용할 수 있다. 물론 언제 GC가 회수하리라는 보장은 없다
- 따라서 finalizer와 cleaner는 사용하지 말자
코테준비
1. 프로그래머스 - 등굣길
- top-down 방식으로 memoization으로 풀이
- dfs로 작성한 후 중복되는 계산을 cache배열에 저장
다음주부터 패캠X야놀자 부트캠프 시작이니깐 꾸준히 공부하자
'TIL(Today I Learned)' 카테고리의 다른 글
2023.07.05 (0) | 2023.07.05 |
---|---|
2023.07.04 (0) | 2023.07.04 |
2023.06.30 (0) | 2023.06.30 |
2023.06.29 (0) | 2023.06.30 |
2023.06.28 (0) | 2023.06.29 |