스프링 핵심 원리 고급편 (김영한 강의) - 섹션 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

+ Recent posts