Code Connect의 잠재력 활용 (새 탭에서 열림)
The right code for your design system Inside Figma Product updates Engineering News
The right code for your design system Inside Figma Product updates Engineering News
데이터독(Datadog)의 엔지니어링 VP 이보 디미트로프(Ivo Dimitrov)는 30년 이상의 경력을 가진 베테랑으로서, 고성능 저수준 시스템 개발자에서 대규모 분산 시스템을 총괄하는 리더로 성장해 온 인물입니다. 그는 마이크로소프트와 링크드인에서 쌓은 대규모 스토리지 인프라 구축 경험을 바탕으로, 현재 데이터독에서 메트릭과 이벤트 플랫폼의 기술적 혁신을 이끌고 있습니다. 기술적 깊이와 조직적 비전 사이의 균형을 강조하는 그의 여정은 복잡한 데이터 시스템을 다루는 엔지니어와 관리자들에게 중요한 통찰을 제공합니다. ### 저수준 시스템 개발에서 엔지니어링 리더십으로의 전환 * 전기 공학 전공 중 실시간 운영체제(RTOS) 커널 기여를 통해 소프트웨어 개발에 입문했으며, 이후 10년간 C/C++ 기반의 고성능 시스템 프로그래밍에 집중했습니다. * 마이크로소프트의 Azure Blob Storage 초기 팀에서 근무하던 중 조직 개편을 계기로 관리직을 맡게 되었으며, 현장에서의 실무 교육과 멘토링을 통해 리더십 역량을 쌓았습니다. * 자신의 업무에만 집중하는 단계를 넘어 타인의 성장을 촉진하고 조직 간의 경계를 조율하는 '오너십(Ownership)'의 가치를 발견하며 매니지먼트의 매력을 느꼈습니다. ### 대규모 분산 스토리지 플랫폼 구축 경험 * 링크드인 재직 당시, 현재까지 전체 데이터셋의 95% 이상을 처리하는 독점 키-값(Key-Value) 저장소인 'Espresso'를 초기 단계에서 성숙한 플랫폼으로 성장시켰습니다. * 파생 데이터 서빙을 위한 'Venice', 오픈소스 블록 스토리지인 'Ambry', 클러스터 관리자인 'Helix' 등 인터넷 규모의 스토리지 인프라 프로젝트들을 주도했습니다. * 이러한 경험을 통해 대규모 레거시 환경의 제약에서 벗어나, 기술적 위험을 감수하고 빠르게 혁신할 수 있는 문화적 유연성의 중요성을 깨달았습니다. ### 데이터독의 분산 데이터 시스템과 기술적 지향점 * 현재 데이터독에서 메트릭(Metrics), 이벤트(Events), 로그 및 트레이스 등 반정형 데이터를 처리하는 분산 데이터 시스템 조직을 총괄하고 있습니다. * 온라인 분석 워크로드에 최적화된 특수 메인 메모리 데이터베이스인 'Driveline'을 통해 시계열 데이터 처리의 효율성을 극대화하고 있습니다. * 서로 다른 도메인별 API를 통합하는 '교차 플랫폼 쿼리(Cross-Platform Queries)' 팀을 운영하여, 고객과 엔지니어 모두가 통일된 인터페이스로 데이터에 접근할 수 있도록 추상화 계층을 구축 중입니다. * 전체 쿼리의 80% 이상을 차지하는 알람(Alerts) 플랫폼을 메트릭 및 이벤트 플랫폼과 통합하여 시스템의 일관성을 높이고 있습니다. **실용적인 제언** 개인 기여자(IC)에서 관리자로 전환할 때는 기술적 전문성을 포기하는 것이 아니라, 그 전문성을 바탕으로 조직의 비전을 설계하고 팀원들이 역량을 발휘할 수 있는 환경을 조성하는 데 집중해야 합니다. 특히 데이터독의 사례처럼 쿠버네티스(Kubernetes) 기반의 현대적 인프라와 실험을 장려하는 문화를 결합할 때, 기술적 부채를 최소화하면서도 폭발적인 성장을 뒷받침하는 시스템을 구축할 수 있습니다.
Datadog의 .NET 프로파일러는 가비지 컬렉션(GC)의 효율성과 메모리 할당 패턴을 분석하여 애플리케이션의 성능 병목 현상을 진단합니다. 이 시스템은 모든 할당을 추적하는 대신 `AllocationTick` 이벤트를 활용한 샘플링 방식을 채택하여 운영 환경에서의 오버헤드를 최소화하면서도 정밀한 데이터를 제공합니다. 특히 .NET 7의 최신 API를 통해 객체의 생존 주기를 추적함으로써, CPU 부하의 원인이 되는 과도한 GC 작업과 잠재적인 메모리 누수 지점을 정확히 찾아내는 데 결론적인 도움을 줍니다. ### 가비지 컬렉터가 CPU에 미치는 영향 측정 * **전용 스레드 모니터링**: 서버 GC 설정 시 CLR이 생성하는 코어당 전용 스레드(.NET Server GC 및 .NET BGC)의 CPU 소비량을 운영체제로부터 직접 수집합니다. * **Pull 모델 채택**: GC 발생 시마다 이벤트를 받는 Push 방식과 달리, 프로파일러가 1분마다 주기적으로 GC 스레드의 CPU 사용 통계를 가져와 'Garbage Collector'라는 단일 프레임을 가진 네이티브 콜 스택 샘플로 기록합니다. * **버전별 차이**: .NET 5 이상에서는 GC 스레드 식별이 가능하여 정확한 측정이 가능하지만, 이전 버전에서는 스레드 ID 정보 부족으로 인해 이 기능을 완벽히 지원하기 어렵습니다. ### AllocationTick을 활용한 효율적인 할당 추적 * **샘플링 기반 추적**: 모든 객체 할당을 기록하는 `ObjectAllocated` 방식은 성능 저하가 극심하므로, 약 100KB의 할당이 누적될 때마다 발생하는 `AllocationTick` 이벤트를 사용하여 데이터를 수집합니다. * **상세 정보 수집**: 이벤트 페이로드에서 클래스 ID(ClassID), 타입 이름, 메모리 주소, 객체 크기뿐만 아니라 해당 객체가 할당된 힙의 종류(SOH, LOH, POH)까지 식별합니다. * **동기적 콜 스택 캡처**: 해당 이벤트는 할당을 수행한 스레드에서 동기적으로 발생하므로, 즉시 콜 스택을 워킹(Stack Walking)하여 어떤 비즈니스 로직이 메모리 압박을 유발하는지 특정할 수 있습니다. ### Weak Handle을 이용한 생존 객체 및 누수 탐지 * **객체 이동 대응**: GC의 컴팩션(Compaction) 단계에서 객체 주소가 변경되는 문제를 해결하기 위해, 샘플링된 객체에 대해 Weak 핸들을 생성하여 관리합니다. * **ICorProfilerInfo13 활용**: .NET 7에서 추가된 이 프로파일링 API를 통해, GC 이후에도 핸들이 가리키는 객체가 여전히 메모리에 살아있는지(`IsAllocated`)를 확인합니다. * **생명 주기 분석**: GC가 끝날 때마다 참조되지 않는 객체의 핸들은 제거하고, 생존한 객체들은 다음 프로필에 포함시켜 어떤 데이터가 메모리에 오래 머무르며 누수를 유발하는지 추적합니다. 운영 환경에서 메모리 문제를 분석할 때는 단순한 할당량 확인을 넘어, GC로 인한 CPU 점유율과 객체의 생존 기간을 함께 살펴야 합니다. 특히 .NET 7 이상의 최신 런타임을 활용하면 프로파일러의 Weak 핸들 추적 기능을 통해 메모리 누수 탐지의 정확도를 대폭 높일 수 있습니다.
프로덕션 환경에서의 성능 진단은 복잡하지만, Continuous Profiler의 타임라인 뷰를 사용하면 코드 레벨의 비효율성을 시각적으로 즉각 파악할 수 있습니다. 이 도구는 CPU 사용량뿐만 아니라 대기 시간과 런타임 오버헤드를 시간 순서대로 나열하여, 특정 시점에 발생한 성능 저하의 근본 원인을 정확히 짚어냅니다. 이를 통해 개발자는 막연한 추측이 아닌 구체적인 데이터를 바탕으로 애플리케이션의 지연 시간(latency)을 단축하고 리소스 효율을 극대화할 수 있습니다. **타임라인 뷰를 통한 스레드 상태의 시각화** * 개별 스레드의 활동을 밀리초(ms) 단위의 시각적 타임라인으로 제공하여, 특정 시점에 코드가 실제로 실행 중인지(On-CPU) 아니면 외부 요인으로 대기 중인지(Off-CPU)를 명확히 구분합니다. * 전체적인 샘플링 통계만으로는 알 수 없는 스레드 간의 작업 순서와 실행 흐름을 직관적으로 이해할 수 있게 돕습니다. **On-CPU 및 Off-CPU 활동 분석을 통한 병목 식별** * **On-CPU 분석:** 복잡한 알고리즘 연산이나 무한 루프 등 CPU 자원을 과도하게 점유하는 코드 구간을 식별하여 로직 최적화의 근거를 제공합니다. * **Off-CPU 분석:** 네트워크 I/O 대기, 디스크 읽기/쓰기 요청, 혹은 시스템 호출로 인해 코드가 멈춰 있는 구간을 찾아내어 외부 서비스 의존성 문제를 진단합니다. **런타임 오버헤드와 가비지 컬렉션(GC)의 영향 파악** * 가비지 컬렉션(GC)의 발생 시점과 그로 인한 애플리케이션 중단(Stop-the-world) 시간을 타임라인 상에서 직접 확인하여 메모리 할당 패턴을 개선할 수 있습니다. * 뮤텍스(Mutex) 잠금 경합(Lock Contention)이 발생하는 지점을 시각화하여, 멀티스레드 환경에서 스레드들이 서로 자원을 기다리며 낭비되는 시간을 최소화합니다. **분산 추적(Tracing) 데이터와의 연계 진단** * 특정 요청(Trace)이 처리되는 과정과 해당 시점의 프로파일링 데이터를 결합하여, 개별 사용자 요청이 정확히 어떤 코드 라인에서 지연되었는지 정밀하게 추적합니다. * 서비스 전체의 메트릭과 개별 코드의 실행 궤적을 연결함으로써 문제 해결을 위한 컨텍스트 전환 비용을 줄여줍니다. 성능 문제를 해결하기 위해서는 단순히 '느리다'는 현상을 아는 것을 넘어 '왜 느린지'에 대한 실행 맥락을 파악해야 합니다. Continuous Profiler의 타임라인 뷰를 활용해 코드의 실제 실행 동작을 상시 관찰함으로써, 예기치 못한 성능 저하에 선제적으로 대응하고 인프라 비용을 효율화할 것을 권장합니다.
GraphQL, meet LiveGraph: a real-time data system at scale Inside Figma Engineering
마이크로소프트는 '세계 접근성 인식의 날(GAAD)'을 맞아 모든 개발자가 장애 여부와 상관없이 누구나 기술을 누릴 수 있도록 돕는 접근성 도구와 방법론을 제안합니다. 개발자는 복잡한 전문 지식 없이도 'Accessibility Insights'와 'Visual Studio'의 통합 도구를 활용해 개발 수명 주기 내에서 접근성 테스트를 손쉽게 수행할 수 있습니다. 궁극적으로 이러한 도구들은 단순히 규정을 준수하는 것을 넘어, 모든 사용자에게 공평하고 만족스러운 디지털 경험을 제공하는 것을 목표로 합니다. **FastPass를 통한 신속한 고부하 이슈 탐지** * Accessibility Insights for Web의 'FastPass' 기능을 활용하면 5분 이내에 사용자 경험에 큰 영향을 미치는 핵심 접근성 문제를 식별할 수 있습니다. * 오픈소스 엔진인 axe-core를 기반으로 한 자동화 체크를 통해 UI 코드를 작성하는 과정에서 즉각적인 피드백을 제공합니다. * 탭 정지(Tab Stops)와 같은 키보드 내비게이션 테스트를 포함하여, 스크린 리더나 확대 도구 사용자에게 혼란을 줄 수 있는 잘못된 포커스 순서를 바로잡도록 돕습니다. **Visual Studio 통합 접근성 검사기 활용** * Visual Studio 2022(버전 17.5 이상)에 내장된 접근성 검사기를 통해 별도의 도구 이동 없이 IDE 내에서 직접 문제를 발견하고 수정할 수 있습니다. * Accessibility Insights for Windows와 동일한 'Axe-Windows' 엔진을 사용하여 데스크톱 애플리케이션의 일반적인 접근성 오류를 정밀하게 감지합니다. * 개발 흐름을 유지하면서 동시에 접근성 스캐닝을 병행할 수 있어 개발 생산성과 포용성을 동시에 확보할 수 있습니다. **Quick Assess를 통한 정밀한 보조 테스트** * 자동화 도구로 감지하기 어려운 심층적인 이슈를 해결하기 위해 30분 이내로 수행 가능한 10가지 보조 테스트(Assisted tests)를 제공합니다. * 최근 업데이트를 통해 최신 웹 접근성 표준인 WCAG 2.2 기준에 대한 테스트 지원 및 안내 가이드를 도입했습니다. * 헤딩 레벨(Heading Levels) 검사 등 각 테스트 항목마다 해당 이슈가 왜 중요한지(Why It Matters)에 대한 설명과 함께 구체적인 수정 사례 및 리소스를 연결해 줍니다. 접근성 개선은 단순히 체크리스트의 항목을 지우는 작업이 아니라, 기술을 통해 모든 사람에게 평등한 기회를 제공하는 혁신의 과정입니다. 지금 바로 Accessibility Insights와 Visual Studio의 최신 기능을 개발 프로세스에 도입하여, 작은 단계부터 사용자 경험의 질을 높여보시길 권장합니다.
Windows 11의 Dev Drive와 Copy-on-Write(CoW) 링크 기능은 대규모 코드베이스의 빌드 성능을 최대 43%까지 향상시키며, 특히 프로젝트 간 종속성이 깊은 C# 환경에서 탁월한 효율을 발휘합니다. 이 기술은 파일 데이터를 물리적으로 복제하는 대신 동일한 디스크 블록을 참조하는 방식을 통해 I/O 부하를 획기적으로 줄이며, Windows Server 2025 및 Windows 11 24H2에 기본 기능으로 탑재될 예정입니다. 개발자는 전용 도구를 통해 CoW 링크 상태를 모니터링하고 참조 누수를 관리함으로써 최적의 개발 성능을 유지할 수 있습니다. **레포지토리 빌드 성능 테스트 결과** - **C# 및 마이크로서비스 이점:** 프로젝트 간 종속성이 깊어 어셈블리 복사가 빈번한 C# 프로젝트나, 빌드 출력 시 대규모 마이크로서비스 레이아웃을 구성하는 환경에서 최소 10%에서 최대 43%의 빌드 시간 단축 효과가 확인되었습니다. - **언어별 차이:** C++ 프로젝트는 상대적으로 적은 수의 대용량 파일을 생성하고 복사 빈도가 낮아 C#에 비해 성능 향상 폭이 적었으나, 파일 복사 과정이 포함된 경우에는 여전히 이득을 보였습니다. - **병렬성 영향:** 빌드 초기 단계의 병렬 처리는 빨라지지만, 마지막 단계에서 거대 프로젝트들이 선형적으로 빌드되는 구조의 레포지토리는 전체 빌드 시간 단축 효과가 희석될 수 있습니다. **CoW 링크 및 블록 클론 식별 방법** - **참조 상태 확인:** `fsutil file queryExtentsAndRefCounts` 명령어를 사용하여 특정 파일이 CoW 링크인지, 즉 블록 클론(Block Clone) 상태인지 확인할 수 있습니다. - **Ref 카운트의 의미:** 출력 결과 중 `Ref: 0x4`와 같은 값은 해당 디스크 볼륨 내에서 4개의 파일 엔트리가 동일한 물리적 데이터 블록을 공유하고 있음을 나타냅니다. - **메타데이터 관리:** 각 클론된 파일은 참조 추적을 위해 최소 하나 이상의 클러스터를 별도로 사용하여 메타데이터를 관리합니다. **분석 도구(ProcMon, Xperf) 사용을 위한 필터 설정** - **필터 드라이버 허용:** Dev Drive는 보안과 성능을 위해 필터 드라이버 연결을 제한하므로, `fsutil devdrv setfiltersallowed` 명령을 통해 분석 도구 전용 필터를 허용 목록에 추가해야 합니다. - **Xperf 사용 시 주의사항:** 성능 측정을 위해 `FileInfo` 필터를 허용한 경우, 측정이 끝난 후에는 반드시 목록에서 제거하고 드라이브를 재마운트해야 합니다. 이를 방치하면 드라이브 성능이 지속적으로 저하될 수 있습니다. - **상시 허용:** ProcMon 필터와 같은 도구는 실제 분석 도구가 실행 중일 때만 부하를 주므로, 필요에 따라 허용 목록에 상시 유지해도 무방합니다. **참조 누수(Leaked References) 탐지 및 복구** - **클론 한계치:** Dev Drive의 기반인 ReFS는 데이터 블록당 최대 8,176개의 클론을 허용하며, 이를 초과할 경우 복사 오류(`STATUS_BLOCK_TOO_MANY_REFERENCES`)가 발생할 수 있습니다. - **관리 도구 활용:** 장기간 빌드를 반복하여 고립된 참조나 누수가 의심될 경우, 관리자 권한으로 `refsutil leak <드라이브명> /s` 명령을 실행하여 누수된 클러스터를 스캔하고 복구할 수 있습니다. - **사전 감지:** `/d` 파라미터를 사용하면 실제 수정 없이 누수 여부만 미리 파악할 수 있어 시스템 안정성을 점검하는 데 용이합니다. **실용적인 결론 및 제언** 대규모 프로젝트를 운영하는 팀은 Dev Drive 도입 시 NuGet 패키지 캐시를 소스 코드와 동일한 파티션에 배치하여 CoW 이득을 극대화해야 합니다. 또한, 빌드 성능 분석을 위해 필터 드라이버 설정을 변경했다면 성능 유지를 위해 분석 완료 후 불필요한 필터를 반드시 정리하는 습관이 필요합니다.
Linear는 서비스 마비 수준의 DDoS 공격을 단순한 보안 위협이 아닌, 시스템 전반의 기술 부채를 해결하고 성능을 극한으로 끌어올리는 기회로 삼았습니다. 공격자가 악용한 비효율적인 쿼리와 아키텍처의 약점을 근본적으로 개선함으로써, 사건 종료 후 Linear는 공격 전보다 훨씬 더 빠르고 안정적인 서비스로 거듭났습니다. 이는 보안 대응이 단순히 방어벽을 세우는 것을 넘어 시스템의 기초 체력을 강화하는 과정임을 시사합니다. ### DDoS 공격의 양상과 초기 대응의 한계 * 단순한 네트워크 트래픽 과부하가 아니라, 데이터베이스에 과부하를 주는 고비용 API 호출을 집중적으로 노린 정교한 애플리케이션 계층(L7) 공격이었습니다. * IP 차단이나 속도 제한(Rate Limiting) 같은 전통적인 방어 수단은 공격자가 패턴을 지속적으로 변경함에 따라 '두더지 잡기'식의 한계에 부딪혔습니다. * 공격이 지속되는 동안 시스템의 가장 느린 부분들이 병목 현상을 일으키며 전체 서비스 중단으로 이어지는 과정을 목격했습니다. ### 데이터베이스 성능 최적화와 쿼리 개선 * 공격자가 검색 및 필터링 기능을 악용한다는 점에 착안하여, 실행 계획(Query Plan) 분석을 통해 인덱스가 제대로 작동하지 않던 지점들을 대대적으로 수정했습니다. * 특히 '소프트 삭제(Soft Delete)' 처리를 위한 필터 조건이 쿼리 성능을 저하시키는 주요 원인임을 파악하고, 이를 최적화하여 데이터 조회 속도를 획기적으로 높였습니다. * Postgres 데이터베이스의 불필요한 Full Table Scan을 제거하고, 가장 빈번하게 호출되는 엔드포인트의 응답 시간을 밀리초 단위로 단축했습니다. ### 동기화 엔진 및 아키텍처 재설계 * Linear의 핵심인 오프라인 우선(Offline-first) 동기화 아키텍처에서 발생하는 오버헤드를 줄이기 위해 동기화 로직을 전면 재검토했습니다. * 클라이언트와 서버 간의 데이터 상태 비교 프로세스를 효율화하여, 동일한 작업을 수행할 때 발생하는 CPU 및 메모리 점유율을 대폭 낮췄습니다. * 결과적으로 인프라를 증설하지 않고도 이전보다 몇 배나 많은 동시 요청을 처리할 수 있는 구조적 회복 탄력성을 확보했습니다. 보안 사고는 시스템의 가장 취약한 고리를 드러내는 가혹한 테스트 베드가 될 수 있습니다. Linear의 사례처럼 공격에 단순히 방어적으로 대응하기보다 시스템 내부의 효율성을 높여 '공격의 가성비'를 떨어뜨리는 전략은, 보안과 성능이라는 두 마리 토끼를 잡을 수 있는 탁월한 접근 방식입니다. 성능 최적화가 곧 최선의 보안 대책이 될 수 있다는 점을 시사합니다.
단순한 백분위수(Percentile) 선 그래프는 데이터의 전체적인 형상과 그 안에 숨겨진 다양한 패턴(Mode)을 왜곡하거나 가릴 수 있습니다. Datadog은 DDSketch 알고리즘을 활용한 히트맵(Heatmap) 시각화를 통해 수조 개의 데이터 포인트를 성능 저하 없이 고해상도로 구현하여, 집계된 지표 뒤에 숨겨진 시스템의 실제 동작을 명확하게 드러냅니다. 이를 통해 엔지니어는 단순 수치 이상의 풍부한 컨텍스트를 파악하고 대규모 인프라의 복잡한 성능 문제를 효과적으로 해결할 수 있습니다. **집계 데이터 시각화의 한계와 히트맵의 이점** * 선 그래프(p50, p99 등)는 수많은 이벤트를 단일 값으로 집계하여 특정 시점의 성능은 보여주지만, 데이터 분포의 전체적인 모습은 설명하지 못함. * 히트맵은 데이터를 과도하게 집계하지 않고 시각화하여, 서로 다르게 동작하는 여러 시스템 그룹(Modes)을 시각적 아티팩트로 분리해 보여줌. * 이를 통해 특정 벤치마킹 서비스로 인한 주기적 지연이나 헬스 체크 요청의 패턴 등 백분위수 그래프에서는 노이즈로 보일 수 있는 현상을 직관적으로 식별 가능함. **무한한 확장을 위한 엔지니어링: DDSketch** * DDSketch를 사용하여 정밀도를 미세하게 희생하는 대신, 방대한 양의 데이터를 '실제 값에 충분히 가까운' 형태로 효율적으로 표현함. * 프론트엔드 전송 시 전체 포인트 목록 대신 '빈(bin)과 카운트(count)' 구조를 사용하여 데이터 페이로드 크기를 일정하게 유지함. * 각 빈의 카운트 저장에 `float32` 타입을 채택하여, 이론적으로 수조 년 동안 매초 발생하는 호출도 수용할 수 있는 수치적 확장성을 확보함. **고해상도 구현 및 데이터 정렬 기술** * 수백조 개의 데이터 포인트를 시각화하기 위해 각 시간 범위(Time bucket)의 경계 값을 일렬로 정렬하고 저장 구조를 최적화함. * 데이터 보고 주기와 히트맵의 시간 버킷 간격이 일치하지 않을 때 발생하는 에일리어싱(Aliasing) 현상을 방지하기 위해 데이터 정렬 알고리즘을 적용함. * 선형 스케일 외에도 로그 스케일을 지원하여 소스 데이터의 해상도에 근접한 시각적 정밀도를 제공함. **색상 설계와 인지적 다이내믹 레인지 유지** * 색상 팔레트는 가독성을 위해 연한 파란색에서 보라색을 거쳐 주황색(Hot)으로 전환되도록 설계하며, 경고 느낌을 주는 빨간색은 의도적으로 배제함. * 인간의 시각이 밝기 차이를 비선형적으로 인지한다는 '스티븐스의 멱법칙(Stevens' Power Law)'을 시각화 로직에 반영함. * 데이터가 멱법칙 분포(롱테일)를 따를 때 선형 색상 보간을 사용하면 정보가 손실되므로, 비선형 보간법을 통해 미세한 빈도의 차이도 눈으로 식별할 수 있게 함. **실용적인 제언** 성능 분석 시 단순히 선 그래프의 추세에만 의존하기보다는 히트맵을 병행하여 사용하는 것이 권장됩니다. 특히 대규모 분산 시스템에서 발생하는 간헐적인 지연이나 특정 노드 그룹의 이상 행동은 히트맵을 통해서만 명확한 '시각적 패턴'으로 드러나기 때문에, 근본 원인 분석(RCA) 시간을 획기적으로 단축할 수 있습니다.
Evolving our real-time timeseries storage again: Built in Rust for performance at scale
피그마(Figma)는 자사의 모바일 렌더링 엔진의 핵심 언어였던 자체 개발 언어 'Skew'를 산업 표준인 TypeScript로 완전히 전환하는 데 성공했습니다. 과거 성능 최적화를 위해 도입했던 Skew가 팀 규모 확장에 따라 생산성 저해와 생태계 부재라는 한계에 부딪히자, 피그마는 일상적인 개발 흐름을 방해하지 않으면서도 자동화된 마이그레이션을 완수했습니다. 결과적으로 피그마는 성능 손실 없이 더 나은 개발 환경과 최신 JavaScript 생태계의 이점을 누릴 수 있게 되었습니다. ### 자체 개발 언어 Skew의 도입과 한계 * **성능 중심의 탄생:** 초기 피그마는 웹과 모바일 모두에서 프로토타입 뷰어를 구현하기 위해 Skew를 개발했습니다. 당시 Skew는 정적 타이핑과 더불어 상수 폴딩(constant folding), 가상 함수 호출 최적화(devirtualization) 등 고급 컴파일러 최적화를 통해 JavaScript보다 뛰어난 성능을 제공했습니다. * **확장의 걸림돌:** 하지만 팀이 커지면서 Skew는 신규 입사자의 적응을 어렵게 만들고, 린터(linter)나 정적 분석기 같은 현대적인 개발 도구 생태계를 활용할 수 없다는 단점이 부각되었습니다. * **기능의 부재:** async/await와 같은 현대적인 JavaScript 기능이 부족했고, 피그마 내부의 다른 코드베이스와 통합하는 데에도 높은 비용이 발생했습니다. ### TypeScript 전환이 가능해진 기술적 배경 * **WebAssembly(Wasm)의 보편화:** 2018년 이후 모바일 브라우저에서 WebAssembly 지원이 확대되었고, 2020년경에는 모바일에서도 안정적인 성능을 발휘하게 되었습니다. * **C++ 엔진으로의 교체:** Skew로 작성되었던 파일 로딩 등 핵심 성능 경로를 WebAssembly로 컴파일되는 C++ 엔진으로 대체함으로써, 나머지 로직을 TypeScript로 전환하더라도 전체 성능에 미치는 영향이 미미해졌습니다. * **팀 규모의 성장:** 개발 경험(DX) 개선에 전념할 수 있는 리소스를 확보할 만큼 팀이 성장하면서 자동화된 마이그레이션 도구 개발이 가능해졌습니다. ### 안전한 전환을 위한 3단계 자동화 프로세스 * **1단계 (Skew 작성, Skew 빌드):** 기존 빌드 프로세스를 유지하면서 Skew 코드를 TypeScript로 변환하는 트랜스파일러를 개발했습니다. 변환된 TypeScript 코드를 깃허브에 체크인하여 개발자들이 미래의 코드 모습을 확인할 수 있게 했습니다. * **2단계 (Skew 작성, TypeScript 빌드):** 개발자는 여전히 Skew로 코드를 짜지만, 실제 프로덕션 빌드는 트랜스파일러를 거친 TypeScript 코드로 진행했습니다. 이 과정에서 유닛 테스트를 통과시키고 타입 오류를 점진적으로 수정하며 안정성을 확보했습니다. * **3단계 (TypeScript 작성, TypeScript 빌드):** 특정 시점에 Skew 코드 생성을 중단하고 모든 Skew 소스 파일을 삭제했습니다. 이후 모든 개발자는 TypeScript를 직접 작성하게 되었으며, CI/CD 파이프라인도 TypeScript 기반으로 완전히 전환되었습니다. ### 실용적인 결론 및 시사점 피그마의 사례는 서비스 초기 성능을 위해 도입한 커스텀 기술이 성숙기에는 오히려 부채가 될 수 있음을 보여줍니다. 특히 대규모 코드베이스를 전환할 때는 **'점진적인 롤아웃'**과 **'자동화된 트랜스파일링'**이 핵심입니다. Skew와 TypeScript 간의 시맨틱 차이(예: 네임스페이스 초기화 순서 등)로 발생할 수 있는 런타임 오류를 방지하기 위해, 자체 컴파일러를 수정하여 제어권을 확보한 점은 기술적 난관을 극복한 훌륭한 전략으로 평가됩니다.
피그마(Figma)는 C++ 코드베이스가 10% 증가할 때 빌드 시간이 50%나 급증하는 문제를 해결하기 위해, 컴파일러로 전송되는 데이터 양(바이트)을 줄이는 전략을 채택했습니다. 하드웨어 업그레이드나 캐싱만으로는 한계가 있음을 깨닫고, 불필요한 헤더 포함을 자동으로 찾아내고 방지하는 자체 도구인 'DIWYDU'와 'includes.py'를 개발하여 빌드 시간을 절반으로 단축했습니다. 결과적으로 빌드 시간의 핵심 지표가 전처리 후의 바이트 수에 비례한다는 점을 입증하며 대규모 개발 환경에서의 생산성을 확보했습니다. ### 헤더 포함 방식과 빌드 속도의 상관관계 * C++ 컴파일 과정에서 전처리기(Pre-processor)는 소스 파일에 포함된 모든 헤더 파일을 하나의 거대한 파일로 합치며, 이는 전이적 의존성(Transitive dependency)을 포함해 컴파일러가 처리해야 할 바이트 수를 기하급수적으로 늘립니다. * 피그마의 분석 결과, 실제 추가된 코드량보다 전처리 후 컴파일러로 전달되는 바이트 수의 증가 폭이 훨씬 컸으며, 이것이 빌드 시간 지연의 주요 원인으로 파악되었습니다. * 대형 파일에서 불필요한 헤더를 수동으로 제거하는 실험을 진행한 결과, 컴파일 바이트는 31%, 콜드 빌드 시간은 25% 감소하며 가설이 증명되었습니다. ### DIWYDU: 불필요한 헤더 제거 자동화 * 구글의 IWYU(Include What You Use)가 너무 엄격하여 적용이 어렵자, 피그마는 더 유연한 자체 도구인 DIWYDU(Don’t Include What You Don’t Use)를 개발했습니다. * 이 도구는 `libclang`의 파이썬 바인딩을 사용하여 추상 구문 트리(AST)를 분석하며, 특정 파일이 포함한 헤더에서 함수, 타입, 변수 등을 직접적으로 사용하는지 확인합니다. * 직접적인 의존성이 없는 헤더를 찾아내어 삭제하도록 플래그를 표시함으로써 모든 기능 브랜치에서 빌드 속도 저하를 방지합니다. * 다만, STL(표준 템플릿 라이브러리)의 프라이빗 헤더 구조나 `libclang` 파이썬 바인딩의 AST 노드 접근 제한(UNEXPOSED_EXPR 등)과 같은 기술적 한계는 존재합니다. ### includes.py를 통한 회귀 방지 및 측정 * 헤더를 실제로 사용하더라도 파일 크기가 너무 커서 빌드 속도를 늦추는 경우를 대비해, 전이적 바이트 수를 측정하는 `includes.py`를 구축했습니다. * Clang을 사용하지 않고 순수 파이썬으로 작성되어 실행 속도가 매우 빠르며(수 초 내외), CI(지속적 통합) 시스템에서 각 PR이 빌드 시간에 미치는 영향을 바이트 단위로 측정합니다. * 특정 PR이 컴파일 바이트 수를 과도하게 늘릴 경우 경고를 발생시켜 개발자가 전방 선언(Forward Declaration)을 사용하거나 헤더를 분리하도록 유도합니다. * 표준 라이브러리는 피그마 내부의 래퍼(Wrapper) 디렉토리를 통해 관리되므로, 표준 헤더의 바이트는 계산에서 제외하여 효율성을 높였습니다. C++ 프로젝트의 빌드 속도를 유지하기 위해서는 단순한 캐싱을 넘어 컴파일러가 처리하는 데이터의 총량을 관리해야 합니다. 불필요한 헤더 의존성을 제거하는 자동화 도구를 CI 파이프라인에 통합하고, '컴파일 바이트 수'를 성능 지표로 모니터링하는 것이 대규모 코드베이스의 개발 효율을 높이는 실질적인 방안이 될 수 있습니다.
Datadog은 복잡한 데이터 시각화를 iOS 모바일 앱에 네이티브로 구현하기 위해 자체 SwiftUI 기반 그래프 라이브러리인 'DogGraphs'를 개발했습니다. iOS 14 호환성을 유지해야 하는 제약 속에서 성능 병목을 해결하기 위해 SwiftUI의 렌더링 파이프라인과 디핑(Diffing) 메커니즘을 심도 있게 분석하고 최적화했습니다. 그 결과, 다양한 제품군에서 빠르고 유연하게 동작하며 컴파일 타임에 타입 안정성까지 보장하는 선언형 그래프 프레임워크를 구축할 수 있었습니다. ### DogGraphs 개발 배경과 도전 과제 * **자체 라이브러리 필요성**: 개발 당시 Swift Charts 같은 공식 라이브러리가 없었으며, Datadog 특유의 복잡한 데이터 시각화 요구사항을 충족하기 위해 직접 개발을 결정했습니다. * **하위 호환성 제약**: iOS 14를 지원해야 했기에 성능 최적화에 유리한 최신 `Canvas` API를 사용할 수 없었고, 표준 SwiftUI 뷰 계층 구조만으로 고성능을 구현해야 했습니다. * **선언형 API 설계**: Swift의 Result Builder를 활용해 SwiftUI와 유사한 구문으로 복잡한 그래프를 정의할 수 있게 했으며, 서로 다른 유형의 그래프를 잘못 쌓는 등의 실수를 컴파일 타임에 방지하도록 설계했습니다. ### 성능 분석 및 프로파일링 도구 활용 * **_printChanges() 활용**: 뷰의 `body` 내에서 이 비공개 API를 호출하여 어떤 상태 변화가 불필요한 재렌더링을 유발하는지 로그로 확인하고 디버깅했습니다. * **Xcode Instruments**: 'SwiftUI View body evaluations'를 통해 뷰의 바디가 평가되는 횟수와 평균 소요 시간을 측정했으며, 'Time profiler'로 실행 시간이 긴 함수를 찾아 최적화했습니다. * **주요 측정 시나리오**: 초기 그래프 렌더링 시점, 툴팁 선택이나 레이어 토글 같은 상호작용 발생 시, 기기 회전 및 다크/라이트 모드 전환 시의 성능을 집중적으로 점검했습니다. ### SwiftUI 핵심 개념과 디핑(Diffing) 메커니즘 * **렌더링 원리 이해**: SwiftUI의 성능 최적화를 위해 Identity(정체성), Lifetime(생명주기), Dependencies(의존성)라는 세 가지 핵심 개념을 기반으로 뷰 업데이트 방식을 분석했습니다. * **비트 단위 비교**: SwiftUI는 뷰의 필드를 비트 단위로 비교(memcmp)하여 이전 값과 차이가 없으면 `body`를 다시 계산하지 않고 건너跳는 최적화 방식을 사용합니다. * **의존성 관리**: 불필요한 의존성 전파를 막고 뷰 구조를 효율적으로 설계함으로써, 데이터 변경 시 영향을 받는 뷰만 정확히 다시 그려지도록 유도했습니다. ### 실용적인 권장 사항 복잡한 SwiftUI 애플리케이션의 성능을 높이려면 단순히 최신 기능을 사용하는 것에 그치지 말고, **뷰의 정체성(Identity)과 의존성 관계를 명확히 정의**해야 합니다. 특히 대규모 데이터를 다루는 시각화 도구에서는 SwiftUI의 내부 디핑 엔진이 효율적으로 작동할 수 있도록 뷰 모델과 프로퍼티 구조를 최적화하고, Instruments를 통해 렌더링 비용을 주기적으로 측정하는 과정이 필수적입니다.