Project (30) 썸네일형 리스트형 1000ms 쿼리를 2.5ms로: 실행 계획(EXPLAIN)으로 파헤친 튜닝기 1분마다 특정 토큰의 홀더 수를 집계하는 스케줄러 쿼리가 프로덕션 환경에서 1000ms 이상 지연되며 DB 커넥션을 갉아먹고 있었다.데이터 개수를 확인해 보니 Trade 7.5만 건, Swap 3.4만 건. 합쳐서 11만 건밖에 안 되는 아주 작은(?) 데이터였다. 정상적으로 인덱스를 탔다면 5ms 안에 끝나야 할 쿼리가 1초나 걸린다는 것은 명백한 풀 테이블 스캔(Full Table Scan)과 치명적인 병목이 존재한다는 뜻이었다.단순히 DB 스펙을 올려 돈으로 해결하는 대신, 쿼리 실행 계획을 뜯어보며 2.5ms까지 줄여나간 튜닝 과정과 그 속에서 얻은 CS적 깨달음을 기록해 본다.초기 상황가장 먼저 문제의 쿼리와 EXPLAIN ANALYZE를 통해 악성 쿼리의 실행 계획을 까보았다.WITH all_.. K8s 환경의 실시간 소켓 서버 최적화: 스케일아웃 이슈와 백엔드/인프라 설계 전략 상태를 가지는(Stateful) 연결과 스케일아웃의 본질적 한계쿠버네티스(K8s) 환경에서 REST API와 같은 Stateless 애플리케이션은 HPA(Horizontal Pod Autoscaler)를 통한 수평 확장이 자연스럽게 이루어집니다. 하지만 웹소켓(WebSocket) 기반의 실시간 서버는 영구적인 TCP 연결을 유지해야 하는 Stateful 특성상, 인프라 확장에 따른 트래픽 분산이 의도대로 동작하지 않는 경우가 많습니다.특히 서버 배포나 파드 축소 시 수만 개의 커넥션이 일시에 끊어지고 재접속되는 현상은 시스템 전체를 마비시킬 수 있는 가장 큰 리스크입니다. 본 글에서는 백엔드와 데브옵스의 관점에서 K8s 기반 Centrifugo 소켓 서버를 안정적으로 운영하기 위한 커넥션 관리, 자원 효.. Batch 서버가 여러대가 띄워져 있고, 돈복사 버그 방지하기위해 분산락을 끼얹으면? 현재 우리 시스템은 매일 아침 5시, 크리에이터들의 토큰 거래 볼륨을 정산하는 배치 서버 1대가 돌고 있습니다. 대상자가 적을 때는 문제가 없었지만, 서비스가 성장하며 수만 명의 정산 데이터를 처리해야 하는 시점이 다가오고 있다고 가정을 해보겠습니다.자연스럽게 "배치 Worker 서버를 여러 대로 늘려서 병렬 처리하면 되겠지?"라고 생각할 것이고, 저 역시 그랬습니다. 하지만 현재 아키텍처에서는 서버를 10대로 늘리더라도 처리 속도는 단 1초도 줄어들지 않는다는 결론에 도달했습니다. 그 원인은 제가 중복 방지를 위해 걸어두었던 'Redis 분산 락(Distributed Lock)' 때문이었습니다.작업 분배에 Redis 분산 락을 쓰면 안 되는 이유일반적으로 분산 환경에서 동시성을 제어할 때 Redis의 .. 돈 복사 버그 방지 정산 파이프라인 구축기 "돈이 오가는데, 서버가 죽으면 어떡하죠?"저희 시스템은 매일 아침 5시, 크리에이터들의 누적 토큰 거래 볼륨을 정산하여 스마트 컨트랙트로 보상을 지급(Payout)합니다.이 기능을 처음 설계할 때 제 머릿속을 맴돈 가장 큰 공포는 '이중 결제(Double Payout)'였습니다. 블록체인 네트워크는 일반적인 API 통신과 다릅니다.혼잡도에 따라 응답이 몇 초에서 몇 분까지 지연되기도 하고, 뜬금없이 타임아웃이 발생하기도 합니다. 만약 백엔드 서버가 스마트 컨트랙트를 호출해 토큰을 전송해 놓고, DB에 '지급 완료' 처리를 하기 직전 찰나의 순간에 OOM(Out of Memory) 등으로 서버가 뻗어버린다면 어떻게 될까요? 다음 배치 스케줄러가 돌 때, 시스템은 이 유저를 '아직 정산받지 않은 상태'로 .. 소켓 서버 지탱하기: OS 커널부터 K8s 오케스트레이션까지의 선제적 최적화 Amazon EKS 환경에서 대규모 실시간 소켓 서버(Centrifugo)를 운영하는 것은 단순히 서버의 CPU나 메모리 자원을 증설하는 것 이상의 기술적 복잡성을 내포합니다. 이는 운영체제(OS) 커널의 한계, 네트워크 통신의 물리적 비용, 그리고 쿠버네티스(Kubernetes) 생명주기와의 상호작용을 깊이 있게 이해해야만 풀 수 있는 퍼즐과 같습니다.이 글은 장애가 발생한 후 헐레벌떡 수습한 사후 대응 기록이 아닙니다. 컴퓨터 공학(CS)의 기본 이론에 근거하여 대규모 트래픽이 몰렸을 때 발생할 수 있는 잠재적 장애 요인들을 사전에 식별하고, 이를 코드와 인프라 레벨에서 선제적으로 차단한 아키텍처 개선기입니다.DNS와 TCP 핸드쉐이크 제거백엔드 서비스(NestJS)와 소켓 서버 간의 내부 통신 효율.. 매일 아침 9시의 ACU 스파이크: PostgreSQL 최적화에서 CloudFront 오프로딩까지 서비스를 운영하다 보면 종종 '당연하게 여겼던 아키텍처'가 시스템의 발목을 잡는 순간을 마주하게 됩니다.저희 팀은 사용자의 IP를 기반으로 국가 및 지역 정보를 판별하기 위해 MaxMind(GeoLite2) 데이터베이스를 활용하고 있었습니다. 하지만 이로 인해 매일 아침 9시마다 데이터베이스(Aurora PostgreSQL)의 ACU(Aurora Capacity Unit)가 9 이상으로 치솟는 스파이크 현상을 겪어야 했습니다.이번 글에서는 이 불필요한 스파이크를 해결하기 위해 PostgreSQL의 내부 메커니즘을 파헤치며 최적화를 진행했던 과정과, 궁극적으로 CloudFront 인프라로 역할을 오프로딩하여 문제를 원천 차단한 아키텍처 전환기를 공유하고자 합니다.발단: 매일 아침 9시, 튀어 오르는 ACU.. Postgre의 MVCC 문제 해결 PostgreSQL Autovacuum 장애 및 테이블 비대화PostgreSQL에서는 데이터를 쓰고 지우는 과정에서 Dead Tuple이 발생됩니다. 이때 이 Dead Tuple을 제거해주는 존재가 Autovaccum입니다. 만약 이 과정을 제대로 거치지 않는다면 테이블을 계속해서 비대해지고, 느려지고, 마지막엔 멈출 수 도 있습니다. 해당 글에서는 특정 테이블에서 발생한 Autovaccum 장애 사례를 통해, 장기 트랜잭션이 어떻게 데이터베이스를 망가뜨리는지 파악하겠습니다. 아래 글은 시간 순서대로 이어집니다.2026.02.07LOG: automatic vacuum of table "public.GeoIpNetwork": index scans: 1pages: 0 removed, 22377 remain.. 10분마다 치는 spike 평탄화 작업기(feat. ACU 45% 절감) Redis에 쌓인 조회수를 주기적으로 RDB에 동기화하는 작업을 진행중이었습니다.최근 서비스가 성장중이며 DAU가 평균 500명대에서 최고 800명 수준으로 뛰어올랐고, 전체 Request 발생량 역시 평소 3~5만 건에서 피크 기준 15만 건까지 급증했습니다. 물론 이 정도의 절대적인 트래픽 규모나 데이터량이 당장 시스템을 다운되게 만들 만큼의 엄청난 양은 아니었습니다.하지만 모니터링 대시보드에는 눈에 거슬리는 현상이 발생하기 시작했습니다. 이 단순해 보이는 동기화 배치가 돌 때마다 DB의 ACU가 4~5 부근으로 주기적인 스파이크를 치며 '톱날' 모양의 그래프를 그리고 있었습니다.이 글에서는 비록 시스템을 당장 셧다운 시킬 규모는 아닐지라도, 잘못 짠 쿼리 패턴이 어떻게 DB 엔진과 Node.js 런.. 이전 1 2 3 4 다음