backend-engineering

4 개의 포스트

네이버 TV (새 탭에서 열림)

JVM 기반 웹 애플리케이션은 실행 초기 JIT(Just-In-Time) 컴파일러의 최적화 과정에서 발생하는 응답 지연 문제를 해결하기 위해 '웜업' 과정이 필수적입니다. 기존의 API 호출식 웜업은 데이터 오염이나 외부 시스템 부하와 같은 부작용을 초래할 수 있으나, 본 발표에서는 이를 극복하기 위해 핵심 라이브러리만을 직접 예열하는 '라이브러리 웜업' 방식을 제안합니다. 이 기술을 통해 부작용 없이 애플리케이션 배포 직후의 성능을 안정적으로 확보할 수 있습니다. **JVM 웜업의 필요성과 기존 방식의 한계** * JVM은 실행 초기에 인터프리터 방식으로 동작하다가, 반복되는 코드를 JIT 컴파일러가 네이티브 코드로 최적화하는 과정을 거치며 성능이 올라갑니다. * 이 최적화가 완료되기 전까지는 응답 시간이 길어지거나 CPU 사용량이 급증하는 현상이 발생하므로, 실제 트래픽이 들어오기 전 코드를 미리 실행하는 웜업이 필요합니다. * 기존의 API 호출 방식은 가짜 요청을 보내는 과정에서 DB 데이터 정합성을 해칠 수 있고, 외부 API 호출에 따른 불필요한 연동 부하를 발생시키는 단점이 있습니다. **라이브러리 웜업의 핵심 아이디어와 구현** * 비즈니스 로직 전체를 수행하는 대신, 애플리케이션에서 성능 비중이 크고 공통적으로 사용되는 '라이브러리 코드'만을 타겟팅하여 예열합니다. * 예를 들어 JSON 파싱, 암호화, 복잡한 수치 계산 모듈 등 JIT 컴파일 임계치(Threshold)를 넘겨야 하는 핵심 메서드들을 반복 호출하도록 설계합니다. * 애플리케이션 시작 단계(Post-Construct 등)에서 비즈니스 로직과는 독립된 웜업 코드를 실행함으로써 데이터 오염의 위험을 원천적으로 차단합니다. **성능 검증 및 실무적 이점** * 라이브러리 웜업 적용 후, 배포 초기에 발생하는 응답 속도의 '튀는 현상(Spike)'이 현저히 감소하고 전체적인 레이턴시가 안정화됨을 확인했습니다. * API 호출 방식보다 구현이 단순하고 외부 의존성이 적어 관리가 용이하며, 배포 파이프라인의 안정성을 높이는 데 기여합니다. * 다만, 모든 비즈니스 경로를 커버하지는 못하므로 성능 영향도가 높은 핵심 모듈을 선별하여 집중적으로 웜업하는 전략이 유효합니다. 빠른 스케일 아웃이 필요한 마이크로서비스 환경이나 지연 시간에 민감한 실시간 서비스라면, API 기반 웜업의 대안으로 이와 같은 라이브러리 단위의 정밀한 웜업 도입을 적극 권장합니다.

디스코드 업데이트: 2 (새 탭에서 열림)

디스코드의 2025년 9월 업데이트는 사용자 프로필의 시각적 강화와 대규모 커뮤니티를 수용하기 위한 기술적 확장에 초점을 맞추고 있습니다. 활동 스택과 팝아웃 창을 통해 멀티태스킹 환경을 개선했으며, 서버 수용 인원을 무려 2천 5백만 명으로 대폭 늘리는 등 플랫폼의 성능과 확장성을 동시에 확보했습니다. 이번 업데이트를 통해 사용자들은 더욱 개성 있는 테마와 프로필로 자신을 표현하고, 전례 없는 규모의 서버에서 원활하게 소통할 수 있게 되었습니다. ### 사용자 프로필 및 멀티태스킹 고도화 * **프로필 디자인 개편:** 데스크톱 버전의 사용자 프로필이 새롭게 단장되어, 사용자의 자기소개와 최근 플레이한 게임 등의 세부 정보를 더욱 명확하게 보여줍니다. * **활동 스택(Activity Stacking):** 게임 플레이, 음악 감상, 음성 채널 참여 등 여러 활동을 동시에 할 경우, 이를 카드 형태로 쌓아서 프로필에 모두 표시해 주는 기능이 추가되었습니다. * **액티비티 팝아웃:** '함께 보기(Watch Together)'와 같은 액티비티를 별도의 플로팅 창으로 분리할 수 있습니다. 이를 통해 서버 메시지를 확인하거나 DM을 보내면서도 끊김 없이 콘텐츠를 즐길 수 있습니다. * **카메라 활성화 알림음:** 개인 프라이버시 보호를 위해 카메라가 켜질 때마다 소리로 상태를 알려주는 직관적인 피드백이 도입되었습니다. ### 서버 확장성 및 편의 기능 강화 * **서버 수용 인원 대폭 확대:** 서버당 최대 수용 인원 기본값이 2,500만 명으로 늘어났습니다. 이는 대규모 커뮤니티 운영을 지원하기 위한 백엔드 최적화의 결과입니다. * **메시지 고정(Pin) 한도 증설:** 기존 50개였던 메시지 고정 한도가 250개로 5배 늘어나 중요한 정보를 더 많이 보관할 수 있게 되었습니다. * **AV1 코덱 및 임베드 개선:** 비디오 첨부 파일과 임베드에 AV1 코덱 지원을 추가하여 고화질 영상 로딩 속도를 높였으며, 텀블러(Tumblr) 링크 공유 시 태그와 상세 설명이 포함된 세련된 임베드 형식을 제공합니다. ### 개인화 테마 및 서버 배지 * **커스텀 그라데이션 테마:** Nitro 사용자는 최대 5가지 색상을 조합하여 자신만의 그라데이션 테마를 제작할 수 있습니다. 제작된 테마는 모바일 기기와도 실시간으로 동기화됩니다. * **신규 서버 태그 배지:** 서버 태그를 꾸밀 수 있는 '반려동물(Pet)' 팩과 '플렉스(Flex)' 팩이 새롭게 추가되어, 귀여운 동물 아이콘이나 왕관 아이콘으로 개성을 나타낼 수 있습니다. 이번 업데이트는 단순한 기능 추가를 넘어, 대규모 서버 운영자와 멀티태스킹을 즐기는 파워 유저 모두를 만족시킬 수 있는 강력한 인프라 개선을 담고 있습니다. 더욱 정교해진 프로필 설정과 커스텀 테마를 활용해 나만의 디스코드 환경을 구축해 보시기 바랍니다.

Figma 데이터베이스 팀이 대 (새 탭에서 열림)

제시해주신 Figma의 기술 블로그 글 **"The growing pains of database architecture"**는 급격한 성장 과정에서 단일 Postgres 데이터베이스의 한계를 극복하기 위해 Figma 엔지니어링 팀이 수행한 아키텍처 혁신 과정을 다루고 있습니다. 이 글은 수직적 확장이 불가능한 시점에서 어떻게 가동 중단 없이 수평적 확장(Sharding) 체제로 전환했는지에 대한 기술적 여정을 상세히 설명합니다. --- Figma는 사용자 트래픽의 폭발적인 증가로 인해 AWS RDS의 가장 큰 인스턴스조차 감당할 수 없는 병목 현상에 직면했습니다. 이를 해결하기 위해 단순한 읽기 복제본 추가를 넘어, 데이터를 기능별로 나누는 '수직적 분할'과 동일 테이블을 여러 장비에 분산하는 '수평적 샤딩'을 단계적으로 도입했습니다. 결과적으로 Figma는 데이터베이스를 유연하게 확장할 수 있는 구조를 갖추게 되었으며, 이는 서비스 안정성과 성능을 획기적으로 향상시켰습니다. ### 수직적 확장의 한계와 초기 대응 * **단일 DB의 임계치 도달:** 초기에는 단일 AWS RDS 인스턴스에 모든 데이터를 저장했으나, 쓰기 작업량이 r5.24xlarge 등 최고 사양 인스턴스의 처리 용량을 넘어섰습니다. * **읽기 복제본(Read Replicas)의 활용:** 읽기 트래픽은 복제본을 통해 분산했으나, 데이터 수정이 빈번한 작업 특성상 복제 지연(Replication Lag)이 발생하여 사용자 경험에 악영향을 주었습니다. * **수직적 테이블 분할 (Vertical Partitioning):** 첫 번째 해결책으로 관련 있는 테이블들을 묶어 별도의 데이터베이스 인스턴스로 분리했습니다. 이는 단기적으로 부하를 분산했지만, 테이블 간 Join 쿼리가 불가능해지고 트랜잭션 관리가 복잡해지는 비용이 발생했습니다. ### 수평적 샤딩(Horizontal Sharding) 도입 과정 * **샤드 키(Shard Key) 선정:** 특정 테이블(예: 파일, 레이어)이 너무 커져서 단일 인스턴스에 담을 수 없게 되자, 데이터를 행(Row) 단위로 분산하는 샤딩을 결정했습니다. '조직 ID(Org ID)'를 주요 샤드 키로 설정하여 관련 데이터를 동일한 물리적 위치에 배치했습니다. * **쿼리 라우팅 계층 구축:** 애플리케이션과 DB 사이에 쿼리를 적절한 샤드로 전달하는 중간 계층(Query Router)을 직접 구현했습니다. 이를 통해 애플리케이션 코드는 데이터가 어느 물리적 서버에 있는지 몰라도 쿼리를 수행할 수 있게 되었습니다. * **Vitess의 검토와 채택:** 처음에는 자체 솔루션을 사용했으나, 관리의 복잡성을 줄이기 위해 오픈소스 데이터베이스 클러스터링 시스템인 Vitess 도입을 결정하고 이를 Postgres 환경에 맞게 최적화했습니다. ### 무중단 데이터 마이그레이션 전략 * **섀도우 쓰기(Shadow Writes):** 새로운 샤딩 환경을 구축한 후, 실시간 데이터를 기존 DB와 신규 DB에 동시에 기록하며 시스템의 안정성을 검증했습니다. * **데이터 검증(Data Validation):** 스냅샷 비교와 실시간 체크섬 확인을 통해 기존 데이터와 샤딩된 데이터 간의 일관성을 100% 보장했습니다. * **점진적 전환(Canary Rollout):** 전체 트래픽을 한 번에 옮기지 않고, 일부 사용자나 조직부터 단계적으로 신규 아키텍처로 전환하여 리스크를 최소화했습니다. ### 운영 효율화를 위한 도구 및 인프라 * **DBProxy 개발:** 수만 개의 애플리케이션 연결을 효율적으로 관리하기 위해 고성능 커넥션 풀링(Connection Pooling)과 쿼리 분석 기능을 갖춘 DBProxy를 구축했습니다. * **가시성(Observability) 확보:** 샤드별 부하 상태, 쿼리 성능, 복제 지연 등을 실시간으로 모니터링할 수 있는 대시보드를 구축하여 병목 지점을 즉각 파악하도록 했습니다. --- **결론 및 추천** Figma의 사례는 서비스 초기부터 복잡한 샤딩을 도입하기보다는, **수직적 분할 → 논리적 샤딩 → 물리적 샤딩**으로 이어지는 단계적 접근이 실무적으로 유효함을 보여줍니다. 데이터베이스 확장을 고민하는 팀이라면 처음부터 완벽한 분산 시스템을 구축하기보다, 데이터 간의 관계를 분석하여 적절한 샤드 키를 선정하고 쿼리 라우팅 계층을 추상화하는 작업부터 시작할 것을 권장합니다.

포스트모템: 20 (새 탭에서 열림)

2020년 4월 29일 발생한 Figma의 서비스 장애는 메인 데이터베이스인 PostgreSQL의 메모리 부족(OOM)으로 인해 발생했습니다. 근본 원인은 시스템 카탈로그 테이블인 `pg_attribute`의 비정상적인 팽창(Bloat)이었으며, 이는 장기 실행 트랜잭션이 데이터 정리를 방해하면서 발생한 연쇄적인 성능 저하의 결과였습니다. 결과적으로 모든 데이터베이스 연결이 지연되고 메모리가 고갈되면서 전체 서비스가 중단되는 사태에 이르렀습니다. ### 시스템 카탈로그(pg_attribute)의 비정상적 팽창 * PostgreSQL에서 테이블 열(column) 정보를 저장하는 `pg_attribute` 테이블이 약 64GB까지 비대해지는 현상이 발생했습니다. * 모든 SQL 쿼리는 실행 계획을 세울 때 이 시스템 카탈로그를 참조해야 하므로, 이 테이블의 성능 저하는 곧 모든 DB 작업의 지연으로 직결되었습니다. * 평소 1ms 미만이던 메타데이터 조회 시간이 수 초 단위로 늘어났고, 이는 데이터베이스 연결(Connection)의 급증과 메모리 점유율 상승으로 이어졌습니다. ### VACUUM 작동 불능과 장기 실행 트랜잭션 * PostgreSQL의 가비지 컬렉션 역할을 하는 VACUUM 프로세스가 `pg_attribute` 내의 불필요한 행(dead tuples)을 정리하지 못하는 상태였습니다. * 장애 발생 당시 며칠 동안 유지되고 있던 '장기 실행 트랜잭션(Long-lived transaction)'이 원인이었습니다. 이 트랜잭션이 특정 시점의 데이터 스냅샷을 붙잡고 있어, VACUUM이 그 이후에 생성된 쓰레기 데이터를 삭제할 수 없게 방해했습니다. * 이 상태에서 대량의 임시 테이블 생성 및 삭제 작업이 반복되자, 정리되지 못한 행들이 기하급수적으로 쌓이며 테이블 크기가 폭발적으로 증가했습니다. ### 장애 전파 및 복구 과정 * 팽창된 시스템 테이블로 인해 쿼리 분석 단계에서 과도한 메모리가 사용되었고, 결국 Primary DB 인스턴스가 OOM(Out of Memory) 상태에 빠져 모든 서비스를 중단시켰습니다. * Figma 팀은 즉각적인 가용성 확보를 위해 DB 인스턴스를 더 높은 메모리 사양으로 수직 확장(Scale-up)했습니다. * 이후 VACUUM의 정상 작동을 가로막던 오래된 트랜잭션들을 강제로 종료하고, 시스템 테이블에 대한 `REINDEX`를 수행하여 비대해진 인덱스를 정리함으로써 성능을 정상화했습니다. ### 재발 방지를 위한 권장 사항 데이터베이스의 안정성을 유지하기 위해서는 사용자 데이터뿐만 아니라 시스템 메타데이터의 상태를 정기적으로 점검해야 합니다. 특히 장기 실행 트랜잭션은 VACUUM 효율을 떨어뜨려 DB 전체에 치명적인 영향을 줄 수 있으므로, 특정 시간(예: 5분) 이상 지속되는 트랜잭션을 자동으로 종료하는 설정(`idle_in_transaction_session_timeout`)을 도입하고 시스템 테이블 크기에 대한 모니터링 알람을 구축하는 것이 권장됩니다.