본문 바로가기
기록/인프런

스프링 핵심 원리 - 고급편 | 쓰레드 로컬 및 디자인 패턴

by 신발사야지 2023. 3. 15.

ThreadLocal

 

traceId 를 파라미터로 넘기지 않고 로그 트레이스를 할 수 있는 방법은 없을까?

 

필드 파라미터로 traceId를 관리 → 동시성 이슈 발생

 

자바는 언어차원에서 쓰레드 로컬을 지원하기 위한 ‘java.lang.ThreadLocal’ 클래스를 지원한다.

 

주의점: 해당 쓰레드가 쓰레드 로컬을 모두 사용하고 나면 ThreadLoca.remove() 를 통해 메모리를 해제 해주어야 한다.

스프링에서는 비용 절감 차원에서 쓰레드풀을 사용하여 쓰레드를 사용하기 때문에 ThreadLocal.remove() 를 해주지 않는다면 이전 쓰레드가 사용했던 데이터를 다음 쓰레드에서 재사용하게 되는 문제점이 발생할 수 있다.

 

(UserA가 로그인 했는데 UserA 가 사용하던 ThreadLocal 에 담긴 UserA의 정보를 그 쓰레드를 다시 사용하게된 UserB가 사용하는 문제)

 

템플릿 메서드 패턴

로그 추적기를 프로젝트에 도입하려고 보니까 개발자들의 반대의 목소리가 높다.

왜냐면 로그 추적기를 프로젝트에 도입하게 되면 코드가 더러워지기 때문이다.

 

v3를 핵심 기능과 부가기능 코드가 섞여있다.

그리고 클래스가 수백개라면?

 

v3를 잘 보면 로그 추적기를 사용하는 구조는 모두 동일

그런데 try ~ catch 는 물론이고 핵심 기능 부분이 중간에 있어서 단순하게 메서드로 추출하는 것은 어렵다.

→ 템플릿 메서드 패턴 사용

 

근데 이렇게 추상 클래스로 하면…. 기존 코드가 수백개면, 수백개 클래스에서 extends 를 해야 된다는 건데

→ 익명 내부 클래스 사용하기

 

‘변하는 것과 변하지 않는 것을 분리’

좋은 설계는 변하는 것과 변하지 않는 것을 분리하는 것이다.

좋은 설계는 변경이 일어날 때 자연스럽게 드러난다.

 

“단일 책임 원칙(SRP)”

변경 지점을 하나로 모아서 변경에 쉽게 대처할 수 있는 구조를 만든것이다.

템플릿 메서드 패턴의 목적

“작업에서 알고리즘의 골격을 정의하고 일부 단계를 하위 클래스로 연기합니다.

템플릿 메서드를 사용하면 하위 클래스가 알고리즘의 구조를 변경하지 않고도 알고리즘의 특정 단계를 재정의 할 수 있습니다.”

 

“하지만”

템플릿 메서드 패턴은 상속을 사용한다. 따라서 상속에서 오는 단점들을 그대로 안고간다. 특히 자식 클래스가 부모 클래스와 컴파일 시점에서 사용하게 결합되는 문제가 발생한다.

자식 클래스가 상속받은 부모 클래스의 기능을 사용한 것이 있었던가?

그럼에도 불구하고 템플릿 메서드 패턴을 사용하기 위해 자식 클래스는 부모 클래스를 상속 받고 있다.

 

전략패턴

전략패턴은 변하지 않는 부분은 context 에 두고, 변하지 않는 부분을 Strategy 라는 인터페이스에 둔다.

디자인 패턴에서 중요한건 의도, 의도를 구현했는지가 중요

 

템플릿 콜백 패턴

“콜백정의”

프로그래밍에서 콜백 또는 콜애프터 함수는 다른 코드의 인수로서 넘겨주는 실행 가능한 코드를 말한다. 콜백을 넘겨받는 코드는 이 콜백을 필요에 따라 즉시 실행할 수도 있고 아니면 나중에 실행할 수도 있다.

 

코드가 호출(call)은 되는데 코드를 넘겨준 곳의 뒤(back) 쪽에서 실행된다는 뜻이다.

 

코드로 최대한 최적화 했는데, 결국 이 코드에는 한계가 있다.

로그추적기를 사용하기 위해서는 어쩄든 원본코드에 손을 대야 하는 것이다.