author
postNo
status
thumbnail
description
category
tags
createdAt
updatedAt
만약 Node.js를 이용하여 백엔드를 개발한다면 HTTP request 로그를 추적하는것이 얼마나 어려운지 알것입니다.
보통 당신의 로그는 이렇게 나올거에요.
로그는 여러명의 호출로 인해 같은 로그가 뒤섞여 있습니다. 어떤것들이 같은 Request인지 알아보기 힘들죠.
HTTP Request추적을 위해 아마 다음과 같은 로그를 원할거에요.
로그를 보면
[request-id:*] 라고하는 식별자가 있습니다. 이 식별자를 통해 같은 사용자의 요청인지에 대한 필터링이 가능합니다. HTTP통신을 하는 애플리케이션의 경우 한 체인에 속한 모든 마이크로서비스에서 생성된 로그를 취합할 수 있습니다.
개발자로서 추적, 로깅하고 Request Id를 생성하고 자동으로 출력하고 싶을것입니다. 하지만 불행히도 Node.js에서는 이것이 조금 힘듭니다.
이 문제를 해결하기 위한 해결책에 대해 얘기해보고자 합니다.
OK, But 이것이 정말 문제인가요?
JVM과 Java Servlet과 같은 다양한 플랫폼과 언어에서는 이는 큰 문제가 되지 않습니다.
왜냐하면 이는 HTTP서버가 멀티쓰레드와 블로킹 I/O기반으로 만들어지기 때문입니다. 이 경우 Request Id를 추적하기 위해서는 쓰레드에 식별자를 넣게 되면
자연스럽게 HTTP Request Id의 추적이 가능합니다. 그리고 이상적이지는 않지만
TLS (Tread-Local Storage)를 통해 해결해볼 수 있습니다. TLS는 기본적으로 키-값 쌍을 이루어 저장하고 검색하는 방법입니다. 쓰레드마다 각각 생성된 Request Id를 TLS를 통해 취합할 수 있는것이죠.하지만 Node.js는 이벤트 루프 기반의 비동기적 특성으로 인해 TLS를 사용할 수 없습니다. 왜냐하면 Java Script는 단일 쓰레기이기 때문이죠.
만약 이런경우 Request Id를 추적하고 싶다면, Request에서 처리되는 모든 Context 객체를 넘겨주어야 합니다.
이는 Express에서 다음과 같은 형태가 될것입니다.
예제에서
req객체를 fakeDbAccess 에 넘겨줬고, 그로 인해 Request Id를 남기는것이 가능해졌습니다. 이 방법은 Routes와 모듈이 훨씬 많은 코드가 지저분해지고, 에러가 많이 발생할 수 있습니다.Node.js 커뮤니티에서는 TLS를 대체할 방법들을 고민해왔고, 가장 좋은 대안으로는 Continuation-Local Storage (CLS)가 있습니다.
CLS로 구원을.
CLS는 라이브러리입니다. 이는 다음과 같이 CLS를 정의합니다.
Continuous-Local Storage는 스레드 프로그래밍에서 thread-local-storage 처럼 작동하지만, 스레드 대신 노드 스타일의 콜백 체인을 기반으로 합니다.
(Continuation-local storage works like thread-local storage in threaded programming, but is based on chains of Node-style callbacks instead of threads.)
이 라이브러리의 API를 확인해보면 JAVA TLS와 비교했을 때 더욱 복잡한것을 볼 수 있습니다. 하지만 핵심은 비슷합니다. Context 객체를 일련의 체인에 연결하여 나중에 접근할 수 있게 하는 것입니다.
CLS는 Node.js >= 8.2.1부터는 node 내장 API인 async_hooks를 사용합니다. API가 여전히 실험적이기는 하지만, polifill을 사용하는것 보다는 훨씬 좋습니다.
CLS를 알게 되었으니, 이제 앱 로그에서 Request Id를 추적하는 방법을 살펴보겠습니다.
여러가지 오픈코드들이 많습니다.
Hello-CLS, cls-rtracer 등 예제에서는 cls-rtracer를 통해 Express를 구성하였습니다.
이는 다음과 같은 로그를 생성할 것입니다.
rTracer.expressMiddleware()함수 호출로 생성 된 Express 미들웨어를 생성하고, 이를 rTracer.id() 호출로 Request Id를 얻고 있습니다.정말 간단하게 HTTP Request Id를 추적할 수 있게 되었습니다.
Async Hooks는 퍼포먼스의 문제가 있습니다. Node 14 에서 이는 개선된다고 하니 Node14를 한번 더 살펴보아야 겠습니다.