C++에서 텍스트를 빠르고 안전하게 조합하는 방법
로그를 남기거나 데이터를 파일에 저장할 때, 변수 값을 문자열로 바꾸는 과정이 병목이 되곤 합니다. 이 라이브러리는 C++ 표준 라이브러리의 출력 기능보다 빠르게 이 작업을 처리해 줍니다. C++20의 std::format과 C++23의 std::print 표준을 미리 구현해 두어, 최신 표준을 기다리지 않고도 일관된 포맷팅을 사용할 수 있게 합니다.
표준 포맷팅의 조기 구현
C++20과 C++23 표준에 포함된 std::format과 std::print 기능을 이 라이브러리가 먼저 제공합니다. 덕분에 컴파일러가 아직 표준을 지원하지 않아도, Python의 format 메서드와 유사한 문법으로 문자열을 조합할 수 있습니다. 위치 인자를 사용해 로컬라이제이션이 필요한 경우에도 인덱스로 값을 지정하면 됩니다. 이 기능은 기존 C의 printf나 C++의 iostream보다 더 직관적인 문법을 제공합니다.
숫자 변환의 정확도와 속도
부동 소수점 숫자를 문자열로 바꿀 때 가장 중요한 것은 정확도와 속도입니다. 이 라이브러리는 Dragonbox 알고리즘을 사용해 IEEE 754 부동 소수점 값을 변환합니다. 이 방식은 반올림이 정확하고, 결과 문자열이 가장 짧으며, 다시 숫자로 변환했을 때 원래 값과 일치하는 것을 보장합니다. sprintf나 iostream보다 수십 퍼센트에서 20~30배까지 빠르며, 특히 숫자 포맷팅에서 차이가 큽니다. 동적 메모리 할당을 최소화하고, 포맷 문자열을 효율적인 코드로 컴파일할 수 있는 옵션도 제공합니다.
컴파일 타임 안전성
포맷 문자열에 오류가 있으면 컴파일 단계에서 바로 알 수 있습니다. 예를 들어 문자열 변수에 숫자 전용 포맷 스펙을 쓰면 컴파일러가 에러를 보고합니다. 이는 런타임에 버퍼 오버플로가 발생하는 것을 막아 줍니다. 라이브러리는 완전한 타입 안전성을 가지며, 자동 메모리 관리를 통해 메모리 누수나 오버플로 위험을 줄입니다. 광범위한 테스트와 지속적인 퍼징(fuzzing)을 통해 안정성을 유지합니다.
사용 범위와 확장성
기본적인 문자열 포맷팅 외에도 날짜와 시간, 컨테이너, 색상 텍스트 출력 등을 지원합니다. fmt/chrono.h를 포함하면 std::chrono 객체를 직접 출력할 수 있고, fmt/ranges.h를 쓰면 벡터 같은 컨테이너를 [1, 2, 3] 형태로 출력합니다. fmt/color.h를 사용하면 터미널에서 색상과 굵기, 밑줄 등 텍스트 스타일을 적용할 수 있습니다. 사용자 정의 타입도 포맷팅에 쉽게 통합할 수 있어 확장성이 좋습니다. 최소 구성은 core.h, format.h, format-inl.h 세 파일로 이루어져 코드 크기가 작습니다.
적용 전 확인 사항
이 라이브러리는 MIT 라이선스를 사용하며 외부 의존성이 없습니다. 헤더 전용 구성을 원하면 FMT_HEADER_ONLY 매크로를 정의하면 됩니다. 컴파일 시간과 바이너리 크기를 비교했을 때, 모듈 방식으로 빌드하면 최적화 빌드 시 컴파일 시간을 27% 줄일 수 있습니다. Apple M5 Max 환경에서 측정한 결과, printf 대비 컴파일 시간은 비슷하거나 짧고, 바이너리 크기도 유사하거나 더 작습니다. 기존 프로젝트에 도입할 때는 C++ 표준 버전과 컴파일러 호환성을 확인해야 하며, 특히 C++20 이상을 사용해야 컴파일 타임 체크 기능이 완전히 동작합니다.