← SEARCHABLE ARCHIVE
C / C++ · 2026-08-15

C++ 기초부터 마스터까지 — 23화

빌드, 테스트, Sanitizer와 프로파일링으로 마스터 캡스톤 완성하기

INTERACTIVE READING MODE →

본 블로그 작성 글들은, 강의를 목표로 하고 제작되었습니다. 또한 작성된 글의 정보도 틀렸을 수 있으니, 주의해주세요.

마스터 단계는 고급 문법을 많이 사용한 코드가 아니라 요구사항, 수명, 실패, 성능을 재현 가능한 증거로 설명할 수 있는 코드다. 마지막에는 앞선 내용을 통합해 비동기 리소스 스트리밍 시스템을 만든다.

캡스톤의 계약

요청 → 중복 제거 → 파일 읽기 → 디코딩 → GPU 업로드 → 캐시
              │           │             │
           취소/오류    worker pool    메인 스레드 경계

시스템은 다음 조건을 만족해야 한다.

  • 같은 리소스 키의 동시 요청은 하나의 작업을 공유한다.
  • 결과를 기다리는 사용자가 모두 취소하면 불필요한 작업을 중단한다.
  • 파일 바이트, 디코딩 버퍼, GPU 객체의 소유자가 명확하다.
  • worker 종료 뒤 callback이 파괴된 객체를 접근하지 않는다.
  • 실패 종류와 재시도 가능 여부를 보존한다.
  • 대표 workload에서 시간, 메모리와 할당 목표를 측정한다.

의존 방향을 나눈다

include/streaming/     공개 계약, handle, 오류 타입
src/core/              상태 머신과 중복 제거
src/io/                파일 시스템 adapter
src/decode/            이미지 decoder adapter
src/gpu/               렌더 스레드 adapter
tests/                 단위·통합·경쟁 테스트
benchmarks/            재현 가능한 workload

핵심 상태 머신은 그래픽 API와 파일 시스템을 직접 import하지 않는다. Concept이나 작은 인터페이스로 필요한 동작만 받고 테스트에서는 결정적으로 제어할 fake를 전달한다.

헤더에 정의한 inline 함수와 템플릿은 모든 translation unit에서 같은 정의를 가져야 한다. 공개 타입의 크기와 가상 함수 배치를 바꾸면 ABI가 깨질 수 있으므로 공유 라이브러리 경계에서는 버전 정책과 재빌드 범위를 정해야 한다.

실패를 도구로 재현한다

GCC와 Clang 계열에서는 별도 빌드로 Sanitizer를 켤 수 있다.

-fsanitize=address,undefined -fno-omit-frame-pointer
-fsanitize=thread

AddressSanitizer는 use-after-free와 범위 밖 접근을, UndefinedBehaviorSanitizer는 여러 정의되지 않은 동작을, ThreadSanitizer는 data race를 찾는 데 도움을 준다. ASan과 TSan은 보통 같은 실행 파일에서 함께 사용하지 않으며 플랫폼과 컴파일러 지원도 확인해야 한다.

필수 실패 테스트에는 빈 파일, 손상된 데이터, 취소 직후 완료, 두 요청의 동시 등록, worker 종료, allocator 고갈을 포함한다. 테스트는 sleep 시간에 기대기보다 barrier, fake executor와 제어 가능한 callback으로 순서를 고정한다.

프로파일은 가설을 검증한다

성능 보고서에는 CPU와 운영체제, 컴파일러 버전과 옵션, 입력 데이터, 실행 명령, 반복 횟수, 원시 결과를 기록한다. 평균만 보지 말고 p50과 p95 지연, peak memory, 할당 횟수, 처리량을 함께 본다.

프로파일에서 병목 하나를 고른 뒤 한 번에 한 가지를 바꾸고 정확성과 자원 사용을 다시 비교한다. std::move, custom allocator, lock-free 구조는 측정 결과가 필요성을 보여줄 때만 도입한다.

마스터 완료 기준

  • 자원 소유권과 thread affinity를 그림으로 설명할 수 있다.
  • 모든 작업은 정상 완료, 실패, 취소, 종료 경로를 가진다.
  • race와 수명 오류를 자동 테스트와 Sanitizer로 검사한다.
  • 깨끗한 환경에서 configure, build, test가 한 명령 흐름으로 재현된다.
  • 최적화 전후 수치와 포기한 대안을 ADR로 남긴다.
  • 아직 보장하지 않는 한계와 확장 조건을 문서화한다.

C++을 마스터한다는 것은 언어의 모든 구석을 외우는 일이 아니다. 값과 자원의 수명을 타입으로 표현하고, 동시성과 실패의 경계를 통제하며, 컴파일러와 측정 도구의 증거로 설계를 계속 수정할 수 있는 능력에 가깝다.