일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- http
- 스프링
- jpa
- 스프링 핵심 기능
- Exception
- 김영한
- 그리디
- kotlin
- Thymeleaf
- java
- 스프링 핵심 원리
- 자바
- QueryDSL
- Android
- transaction
- db
- AOP
- Greedy
- spring
- springdatajpa
- JDBC
- Servlet
- pointcut
- JPQL
- SpringBoot
- 백준
- 알고리즘
- Proxy
- Spring Boot
- 인프런
- Today
- Total
목록인프런 (528)
개발자되기 프로젝트
FieldLogTrace 에서 발생했던 동시성 문제를 ThreadLocal 로 해결해보자. TraceId traceIdHolder 필드를 쓰레드 로컬을 사용하도록 ThreadLocal traceIdHolder로 변경 필드 대신에 쓰레드 로컬을 사용해서 데이터를 동기화하는 ThreadLocalLogTrace 를 새로 만들자. 1. ThreadLocalLogTrace 기존 TraceId traceIdHolder를 ThreadLocal traceHolder로 변경하였다. @Slf4j public class ThreadLocalLogTrace implements LogTrace{ private static final String START_PREFIX = "-->"; private static final Str..
1. ThreadLocal 사용법 값 저장: ThreadLocal.set(xxx) 값 조회: ThreadLocal.get() 값 제거: ThreadLocal.remove() 해당 쓰레드가 쓰레드 로컬을 모두 사용하고 나면 ThreadLocal.remove() 를 호출해서 쓰레드 로컬에 저장된 값을 제거해주어야 한다. 2. ThreadLocalService @Slf4j public class ThreadLocalService { private ThreadLocal nameStore = new ThreadLocal(); public String logic(String name){ log.info("저장 name={} --> nameStore={}", name, nameStore.get()); nameStor..
1. Thread Local??? 쓰레드 로컬은 해당 쓰레드만 접근할 수 있는 특별한 저장소를 말한다. 쉽게 이야기해서 물건 보관 창구를 떠올리면 된다. 여러 사람이 같은 물건 보관 창구를 사용하더라도 창구 직원은 사용자를 인식해서 사용자별로 확실하게 물건을 구분해준다. 사용자A, 사용자B 모두 창구 직원을 통해서 물건을 보관하고, 꺼내지만 창구 지원이 사용자에 따라 보관한 물건을 구분해주는 것이다. 2. 일반적인 변수 필드 여러 Thread가 같은 인스턴스의 필드에 접근하면 처음 쓰레드가 보관한 데이터는 사라질 수 있다. ThreadB가 저정하면 ThreadA가 저장한 데이터는 사라짐 ㄷㄷ 3. Thread Local Thread Local을 사용하면 각 Thread마다 별도의 내부 저장소를 제공한다...
1. Test에서 lombok 사용 dependancies에 추가. //테스트에서 lombok 사용 testCompileOnly 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok' 2. FieldService FieldService는 logic() 메서드를 제공한다. name을 받으면 name sotre에 저장 후 값을 반환한다. name sotre에 저장하는데 1초가 걸린다고 가정. @Slf4j public class FieldService { private String nameStore; public String logic(String name){ log.info("저장 name={} --> nameStore={}..
1. 동시성 문제 사실 이 문제는 동시성 문제이다. FieldLogTrace 는 싱글톤으로 등록된 스프링 빈이다. 이 객체의 인스턴스가 애플리케이션에 딱 1 존재한다. 이렇게 하나만 있는 인스턴스의 FieldLogTrace.traceIdHolder 필드를 여러 쓰레드가 동시에 접근하기 때문에 문제가 발생한다. 실무에서 한번 나타나면 개발자를 가장 괴롭히는 문제도 바로 이러한 동시성 문제이다. 아래 예시와 같이 동시성 문제를 발생시켜보았다. traceId는 같은데 여러 Thread에서 접근했다. 하나의 객체(싱글톤)에 여러 thread가 접근했다.. [nio-8080-exec-5] h.advanced.trace.logtrace.FieldLogTrace : [9a3bac90] | | | | | | | | |..
1. LogTrace 스프링 빈 등록 FieldLogTrace가 싱글톤으로 스프링 빈으로 등록됨. @Configuration public class LogTraceConfig { @Bean public LogTrace logTrace(){ return new FieldLogTrace(); } } 2. Controller @RestController //@Controller +@ResponseBody @RequiredArgsConstructor public class OrderControllerV3 { private final OrderServiceV3 orderService; private final LogTrace trace; @GetMapping("/v3/request") public String r..
앞서 로그 추적기를 만들면서 다음 로그를 출력할 때 트랜잭션ID 와 level 을 동기화 하는 문제가 있었다. 이 문제를 해결하기 위해 TraceId 를 파라미터로 넘기도록 구현했다. 이렇게 해서 동기화는 성공했지만, 로그를 출력하는 모든 메서드에 TraceId 파라미터를 추가해야 하는 문제가 발생했다. TraceId 를 파라미터로 넘기지 않고 이 문제를 해결할 수 있는 방법은 없을까? 1. LogTrace Interface public interface LogTrace { TraceStatus begin(String message); void end(TraceStatus status); void exception(TraceStatus status, Exception e); } 2. FieldLogTra..
1. V2 적용하기 메서드 호출의 깊이를 표현하고, HTTP 요청도 구분해보자. 이렇게 하려면 처음 로그를 남기는 OrderController.request() 에서 로그를 남길 때 어떤 깊이와 어떤 트랜잭션 ID를 사용했는지 다음 차례인 OrderService.orderItem() 에서 로그를 남기는 시점에 알아야한다. 결국 현재 로그의 상태 정보인 트랜잭션ID 와 level 이 다음으로 전달되어야 한다. 이 정보는 TraceStatus.traceId 에 담겨있다. 따라서 traceId 를 컨트롤러에서 서비스를 호출할 때 넘겨주면 된다. 2. Controller Controller에서 로그를 처음 남김. 현재 status의 TraceId 정보를 Service계층에 넘겨줌. @RestController ..