본문 바로가기

Project

(20)
Log 영속성을 위한 MQ 도입 💡 로그 유실 없는 비동기 로그 수집 아키텍처보안 로그 수집 시스템에서 단일 장애가 발생했을 때 로그 유실 위험이 있다는 문제를 발견했습니다. 기존에는 로그를 바로 DB에 기록하는 동기 구조였습니다. 하지만, 트래픽이 급증하게 되면 다음 문제가 발생할 수 있습니다.DB Connection Pool 고갈DML Lock 경합이를 해결하기 위해 BullMQ 기반의 Queue 시스템과 Redis를 활용한 비동기 아키텍처로 전환하여 DB 부하를 차단하고, 트래픽 버스트를 안정적으로 받아낼 수 있는 비동기 구조로 개선했습니다.Redis의 Eviction 정책, AOF 설정 등 운영 환경에서 고려해야 할 포인트들도 정리했으며, 장애 발생 시 유실 없는 처리를 위해 재처리 및 장애 대응 방안까지 반영했습니다. 이 글..
MySQL에서의 Lock 경합 문제 해결과 성능 개선 💡 MySQL Lock 경합 → Redis + BullMQ 기반 비동기 아키텍처로 해결좋아요 처리 시스템에서 단순 증가 연산만 수행하던 Like 기능이 TPS(초당 처리량)가 증가하면서 MySQL Row-Level Lock 경합을 유발해 시스템 성능 저하가 심화됐습니다.Redis 캐시 도입, Pipeline 최적화, 인덱스 튜닝 등 다양한 성능 개선 시도를 거쳤으나, 결국 DB Connectoin Pool 고갈 및 Lock 경합 현상이 반복 발생되었습니다. 단순 캐시 레벨에서의 해결의 한계가 명확했습니다.BullMQ 기반 비동기 Queue 아키텍처로 전환으로 Lock 경합을 근본적으로 제거했고, 그 결과는 아래와 같습니다. 성능 지표 전환 전 전환 후 개선율 평균 응답 속도580 ms25 ms약 ..
Bullmq Document + CS 관점으로 다시 생각 BullMQ는 왜 Queue로 설계가 되어있을까? Queue는 대표적인 FIFO(First In, First Out) 구조입니다. 비동기 작업처리에 직관적이고 예측이 가능하다는 장점을 갖고 있습니다.장점은 아래와 같습니다. 작업 순서가 명확합니다. 들어오는 순서대로 작업이 처리됩니다. 해당 내용은 큐잉 이론과도 연결됩니다.생산자와 소비자 패턴을 구현할 때 적합합니다. 생산자는 큐에 넣고, 소비자는 큐에서 작업을 빼내서 처리합니다.병렬 처리와 동시성 관리입니다. 여러 소비자가 하나의 큐에서 작업을 꺼내서 처리할 수 있어 병렬 처리가 가능하고, 여러명의 소비자가 하나의 큐에 접근해서 작업을 처리할 수 있어 동시성 관리가 가능합니다.확장성입니다. 큐에 작업이 많이 쌓이면서 Worker를 늘려 처리량을 조절할 ..
멱등성(Idempotency)이란? 멱등성 멱등성(Idempotency)에 관한 이해는 RESTful API 설계에서 매우 중요하다. 멱등성을 만족한다는 것은 같은 요청을 여러 번 반복해서 보내더라도 서버의 최종 상태가 변하지 않는다는 의미다. 예를 들어, ‘좋아요’를 추가하는 API가 멱등성을 지닌다면 PUT 요청을 여러 차례 보내더라도 ‘좋아요’ 상태는 한 번만 반영되어 변하지 않는다. 마찬가지로, DELETE 요청을 여러 번 보내더라도 ‘좋아요 해제’ 상태가 계속 유지된다. RESTful API 원칙에 따르면, PUT 메서드는 리소스를 완전하게 대체하는 역할을 하며, 리소스가 없으면 생성하고 있으면 교체한다. 이러한 특성 덕분에 PUT은 멱등성을 자연스럽게 만족한다. DELETE 역시 멱등성을 가지는데, 리소스가 이미 삭제되었거나 존..
내가 아는 Node.js -4 스레드 풀(Thread Pool)과 워커 스레드(Worker Thread)Node.js는 본질적으로 싱글 스레드 기반의 이벤트 루프 모델을 채택하고 있지만, 내부적으로 멀티 스레드를 활용하여 비동기 I/O와 CPU 집약적인 작업을 효율적으로 처리할 수 있도록 설계되어 있습니다. Node.js에서 멀티 스레드를 사용하는 방식은 크게 두 가지로 나뉩니다: 스레드 풀 (Thread Pool) 과 워커 스레드 (Worker Threads)입니다.스레드 풀 (Thread Pool)Node.js가 특정 작업을 수행할 때 자동으로 멀티 스레드를 사용하는 대표적인 메커니즘이 바로 스레드 풀입니다. 이는 Node.js 내부에서 사용하는 libuv 라이브러리를 통해 구현되어 있으며, 비동기 I/O 작업이나 일부 CPU 연..
내가 아는 Node.js -3 Node에서 실행되는 방식Node.js의 비동기 처리 흐름을 정확하게 이해하려면, Microtask와 Macrotask의 차이를 명확히 아는 것이 중요합니다. 특히 비동기 코드의 실행 순서를 예측하고 디버깅하거나, 성능을 최적화하고 싶다면 이 두 개념을 필수적으로 이해해야합니다.Macrotask는 Event Loop의 각 Phase에서 실행되는 작업을 의미합니다. 예를 들어, setTimeout, setInterval, setImmediate, I/O 콜백, close 콜백 등은 모두 각각의 Phase에 배정되어 순차적으로 실행됩니다. -2 에서 조금은 자세히 설명되어 있습니다.가장 흔히 언급되는 예는 setTimeout(() => {}, 0)인데, 이 코드는 Timer Phase에서 실행되는 대표적인 ..
내가 아는 Node.js -2 Event LoopNode.js는 싱글 스레드 기반의 JavaScript 런타임입니다. 그러나 단일 스레드라는 제약에도 불구하고, 수천 개의 네트워크 요청이나 파일 I/O 작업을 동시에 처리할 수 있는 고성능 서버 애플리케이션을 개발할 수 있습니다. 그 중심에는 바로 Event Loop라는 메커니즘이 존재합니다. Node.js에서 Event Loop는 libuv 라는 C 기반 라이브러리를 통해 구현되며, 이는 이벤트 기반 비동기 I/O를 가능하게 해줍니다.이벤트 루프는 자바스크립트가 단일 스레드에서 동작하는 언어임에도 높은 동시성을 제공할 수 있도록 설계된 핵심 구조입니다. I/O 작업, 타이머, 네트워크 요청, 파일 시스템 접근과 같은 작업이 비동기로 이루어질 수 있도록 지원하며, 작업 완료 후 등록된..
내가 아는 Node.js -1 Node.js는 Chrome V8 자바스크립트 엔진 위에 구축된 자바스크립트 런타임(JavaScript Runtime) 입니다. 흔히 런타임이란 특정 언어로 작성된 코드를 실행할 수 있는 환경을 의미하며, Node.js는 자바스크립트로 작성된 애플리케이션을 웹 브라우저 외부, 즉 서버 환경에서 실행할 수 있게 해주는 플랫폼입니다.원래 자바스크립트는 웹 브라우저 내에서만 동작하는 스크립트 언어였습니다. 이는 브라우저가 자바스크립트 런타임(예: V8, SpiderMonkey 등)을 내장하고 있었기 때문입니다. 하지만 2009년, 라이언 달(Ryan Dahl)이 V8 엔진과 libuv라는 라이브러리를 조합하여 Node.js를 만들어냄으로써, 자바스크립트를 브라우저 밖으로 끄집어낼 수 있게 되었고, 오늘날에는 ..