본문으로 건너뛰기
Previous
Next
C++ Conan 레시피 작성 완벽 가이드 | 패키지·빌드·원격 저장소 [#53-4]

C++ Conan 레시피 작성 완벽 가이드 | 패키지·빌드·원격 저장소 [#53-4]

C++ Conan 레시피 작성 완벽 가이드 | 패키지·빌드·원격 저장소 [#53-4]

이 글의 핵심

C++ Conan 패키지 레시피 작성: conanfile.py 구조, CMake 빌드, test_package, conan create·upload, Artifactory 연동. 자주 발생하는 에러·베스트 프랙티스·프로덕션 패턴까지 실전 예제로 다룹니다.

들어가며: “우리 라이브러리를 Conan 패키지로 배포하고 싶어요”

실제 겪는 문제 시나리오

시나리오 1: 사내 라이브러리 배포 지옥

"lib-core를 프로젝트 A, B, C에서 쓰는데, 각각 다른 경로에 복사해 두고 있어요."
"버전 1.2로 업데이트했는데, 프로젝트 B는 아직 1.1을 쓰고 있어요. 언제 바꿀지 모르겠어요."
"새 팀원이 lib-core를 빌드하려면 README 10페이지를 읽어야 해요."

원인: 수동 복사·빌드·경로 설정으로 버전 관리와 의존성 추적이 어렵습니다. 시나리오 2: Conan Center에 없는 라이브러리

"우리 회사에서 fork한 OpenSSL을 Conan으로 쓰고 싶어요."
"레거시 C 라이브러리를 Conan 패키지로 감싸서 배포해야 해요."
"내부용 유틸리티를 팀 전체가 conan install로 쓰게 하고 싶어요."

원인: Conan Center에 없는 패키지는 직접 레시피를 작성해야 합니다. 시나리오 3: 빌드 설정 불일치

"Windows에서는 shared=True로 빌드했는데, Linux에서는 static으로 빌드돼서 링크 에러가 나요."
"Debug/Release 혼용으로 ABI 호환성 문제가 발생해요."

원인: 레시피에 options·settings가 명확히 정의되지 않아 팀원마다 다른 바이너리가 생성됩니다. 시나리오 4: 패키지 품질 검증 부재

"conan create 했는데, 다른 프로젝트에서 링크하면 undefined reference가 나요."
"헤더 경로가 잘못되어 include가 안 돼요."

원인: test_package로 패키지 소비를 검증하지 않아, 실제 사용 시 문제가 드러납니다.

Conan 레시피로 해결

문제해결
수동 배포conan create + conan upload로 원격 저장소 배포
버전 불일치name/version으로 패키지 식별, conan install로 버전 지정
빌드 설정 차이settings·options로 바이너리 구성 통일
품질 검증test_package로 빌드·링크·실행 검증
flowchart LR
  subgraph Before["수동 배포 (Before)"]
    B1[소스 복사] --> B2[수동 빌드]
    B2 --> B3[경로 설정]
    B3 --> B4[프로젝트마다 다름]
  end
  subgraph After["Conan 레시피 (After)"]
    A1[conanfile.py] --> A2[conan create]
    A2 --> A3[캐시/원격 저장소]
    A3 --> A4[conan install로 통일]
  end

이 글에서 다루는 것

항목내용
레시피 구조conanfile.py 메타데이터, settings, options
완전한 예제헤더 전용, 정적/공유 라이브러리, CMake 연동
빌드·배포conan create, conan upload, test_package
원격 저장소Artifactory, Conan Server 연동
자주 발생하는 에러package_info 누락, exports_sources 오류 등
베스트 프랙티스버전 관리, 옵션 설계, CMake install
프로덕션 패턴CI/CD, 버전 태깅, 사내 레포 워크플로

실무 적용 경험: 이 글은 대규모 C++ 프로젝트에서 실제로 겪은 문제와 해결 과정을 바탕으로 작성되었습니다. 책이나 문서에서 다루지 않는 실전 함정과 디버깅 팁을 포함합니다.

1. 환경 설정

필수 요구사항

항목버전비고
Conan2.xpip install conan
Python3.8+Conan 2.x 요구
CMake3.15+CMake 기반 레시피 시
C++C++14 이상 권장-

Conan 설치 및 프로젝트 템플릿

# Conan 2.x 설치
pip install conan
# 버전 확인
conan --version
# CMake 라이브러리 레시피 템플릿 생성 (Hello World 수준)
conan new cmake_lib -d name=mylib -d version=1.0

conan new로 생성되는 구조:

mylib/
├── CMakeLists.txt
├── conanfile.py
├── include/
│   └── mylib.h
├── src/
│   └── mylib.cpp
└── test_package/
    ├── CMakeLists.txt
    ├── conanfile.py
    └── src/
        └── example.cpp

2. conanfile.txt vs conanfile.py

언제 무엇을 쓸까?

형식용도빌드·패키징
conanfile.txt패키지 소비만 할 때없음 (requires, generators만)
conanfile.py패키지 생성 또는 고급 소비build(), package(), package_info()
레시피 작성은 반드시 conanfile.py를 사용합니다. conanfile.txt는 [requires]에 패키지 목록만 적고, 빌드·패키징 로직을 정의할 수 없습니다.

conanfile.txt (소비 전용)

[requires]
mylib/1.0
[generators]
CMakeDeps
CMakeToolchain

conanfile.py (레시피 = 패키지 생성)

from conan import ConanFile
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
class MylibConan(ConanFile):
    name = "mylib"
    version = "1.0"
    settings = "os", "compiler", "build_type", "arch"
    def layout(self):
        cmake_layout(self)
    def generate(self):
        tc = CMakeToolchain(self)
        tc.generate()
    def build(self):
        cmake = CMake(self)
        cmake.configure()
        cmake.build()
    def package(self):
        cmake = CMake(self)
        cmake.install()
    def package_info(self):
        self.cpp_info.libs = [mylib]

3. 완전한 conanfile.py 레시피

3.1 레시피 전체 구조

Conan 레시피의 핵심 메서드와 역할:

flowchart TD
  A[conanfile.py] --> B[layout]
  A --> C[generate]
  A --> D[build]
  A --> E[package]
  A --> F[package_info]
  B --> G[소스·빌드 경로 정의]
  C --> H[CMakeToolchain 등 생성]
  D --> I[실제 빌드 수행]
  E --> J[아티팩트를 package 폴더로 복사]
  F --> K[소비자에게 전달할 정보]

3.2 완전한 CMake 라이브러리 레시피

from conan import ConanFile
from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps, cmake_layout
from conan.tools.build import check_min_cppstd
from conan.tools.files import copy
class MylibConan(ConanFile):
    name = "mylib"
    version = "1.0.0"
    # 메타데이터 (선택이지만 권장)
    license = "MIT"
    author = "Your Name <[email protected]>"
    url = "https://github.com/yourorg/mylib"
    description = "A sample C++ library for Conan packaging"
    topics = ("conan", "library", "example")
    # 바이너리 구성
    settings = "os", "compiler", "build_type", "arch"
    options = {
        "shared": [True, False],
        "fPIC": [True, False],
    }
    default_options = {
        "shared": False,
        "fPIC": True,
    }
    # 소스 파일 (레시피와 함께 export됨)
    exports_sources = "CMakeLists.txt", "src/*", "include/*"
    def config_options(self):
        # Windows에서는 fPIC 의미 없음
        if self.settings.os == "Windows":
            del self.options.fPIC
    def configure(self):
        if self.options.shared:
            self.options.rm_safe("fPIC")
    def layout(self):
        cmake_layout(self)
    def requirements(self):
        # 의존성 예: self.requires("fmt/10.1.1")
        pass
    def generate(self):
        deps = CMakeDeps(self)
        deps.generate()
        tc = CMakeToolchain(self)
        tc.generate()
    def build(self):
        cmake = CMake(self)
        cmake.configure()
        cmake.build()
    def package(self):
        cmake = CMake(self)
        cmake.install()
    def package_info(self):
        self.cpp_info.libs = [mylib]
        # 헤더 경로는 CMake install이 설정하면 자동
        # 수동 지정 시: self.cpp_info.includedirs = [include]

3.3 CMakeLists.txt (레시피와 연동)

레시피의 cmake.install()이 동작하려면 CMake에 install 타겟이 있어야 합니다.

cmake_minimum_required(VERSION 3.15)
project(mylib VERSION 1.0.0 LANGUAGES CXX)
add_library(mylib
    src/mylib.cpp
)
target_include_directories(mylib PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    $<INSTALL_INTERFACE:include>
)
target_compile_features(mylib PUBLIC cxx_std_17)
# Conan이 package()에서 cmake.install() 호출 시 사용
install(TARGETS mylib
    RUNTIME DESTINATION bin
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib
)
install(DIRECTORY include/ DESTINATION include)

3.4 주요 속성·메서드 설명

항목설명
exports_sources레시피와 함께 Conan 캐시로 복사할 파일. conan create 시 사용
config_options()플랫폼별로 옵션 제거 (예: Windows에서 fPIC)
configure()옵션 간 의존성 (shared=True면 fPIC 불필요)
layout()소스·빌드·패키지 폴더 구조. cmake_layout()이 표준
generate()CMakeToolchain, CMakeDeps 등 빌드 설정 파일 생성
build()실제 빌드 (cmake configure + build)
package()빌드 결과를 package 폴더로 복사
package_info()소비자가 링크·include할 때 필요한 정보

4. 헤더 전용 라이브러리 레시피

헤더 전용 라이브러리는 빌드 단계가 없습니다. build()를 생략하고, package()에서 헤더만 복사합니다.

from conan import ConanFile
from conan.tools.files import copy
class HeaderOnlyConan(ConanFile):
    name = "headeronly"
    version = "1.0.0"
    description = "Header-only C++ library"
    # 헤더 전용: settings 불필요 (바이너리 없음)
    # 단, 의존성이 있으면 settings 필요
    settings = "os", "compiler", "build_type", "arch"
    no_copy_source = True  # 소스를 그대로 package에 복사
    exports_sources = "include/*"
    def package(self):
        copy(self, "*.hpp", self.source_folder, self.package_folder)
        copy(self, "*.h", self.source_folder, self.package_folder)
    def package_info(self):
        self.cpp_info.bindirs = []
        self.cpp_info.libdirs = []
        # includedirs 기본값이 "include"이므로, include/ 아래에 있으면 생략 가능
        self.cpp_info.includedirs = [include]

주의: no_copy_source = True이면 self.source_folder에 소스가 있으므로, exports_sources로 지정한 파일이 package() 시점에 사용 가능합니다.

5. 패키지 빌드 및 검증

5.1 conan create — 빌드 + test_package

# 현재 디렉터리의 conanfile.py로 패키지 생성
conan create .
# 특정 설정
conan create . -s build_type=Debug
conan create . -o mylib/1.0.0:shared=True
# 프로필 지정
conan create . -pr=default

conan create는 다음을 수행합니다:

  1. 레시피와 exports_sources를 캐시로 export
  2. generate()build()package() 실행
  3. test_package/로 이동해 패키지 소비 테스트

5.2 test_package 구조

test_package는 패키지가 올바르게 생성되었는지 검증하는 소규모 Conan 프로젝트입니다.

test_package/
├── CMakeLists.txt
├── conanfile.py
└── src/
    └── example.cpp

test_package/conanfile.py:

import os
from conan import ConanFile
from conan.tools.cmake import CMake, cmake_layout
class TestPackageConan(ConanFile):
    settings = "os", "compiler", "build_type", "arch"
    generators = "CMakeDeps", "CMakeToolchain"
    def layout(self):
        cmake_layout(self)
    def requirements(self):
        # 생성 중인 패키지를 의존성으로
        self.requires(self.tested_reference_str())
    def build(self):
        cmake = CMake(self)
        cmake.configure()
        cmake.build()
    def test(self):
        # 빌드된 실행 파일 실행
        self.run(f".{os.sep}example")

test_package/CMakeLists.txt:

cmake_minimum_required(VERSION 3.15)
project(test_package LANGUAGES CXX)
find_package(mylib REQUIRED)
add_executable(example src/example.cpp)
target_link_libraries(example PRIVATE mylib::mylib)

test_package/src/example.cpp:

#include <mylib.h>
int main() {
    mylib::hello();
    return 0;
}

5.3 conan create 출력 예시

======== Exporting recipe to the cache ========
mylib/1.0.0: Exporting package recipe
...
======== Installing packages ========
-------- Installing package mylib/1.0.0 (1 of 1) --------
mylib/1.0.0: Building from source
mylib/1.0.0: Calling build()
...
mylib/1.0.0: Package 'xxx' built
======== Testing the package: Building ========
...
======== Testing the package: Executing test ========
mylib/1.0.0 (test package): Running test()
mylib/1.0.0 (test package): RUN: ./example

5.4 로컬 개발 워크플로 (conan install + build)

패키지를 매번 conan create하지 않고, 로컬에서 수정하면서 빌드할 때:

# 1. 의존성 설치 (자기 자신은 제외)
conan install . --output-folder=build --build=missing
# 2. CMake 빌드
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake
cmake --build build

6. 원격 저장소 배포

6.1 conan upload — 로컬 캐시 → 원격

# 특정 패키지 업로드
conan upload "mylib/1.0.0" -r myremote --all
# 모든 리비전·바이너리 포함
conan upload "mylib/*" -r myremote --all

6.2 remote 추가 및 확인

# remote 목록
conan remote list
# 사내 Artifactory 추가
conan remote add mycompany https://mycompany.jfrog.io/artifactory/api/conan/conan-local
# remote 우선순위 (0이 가장 높음)
conan remote add mycompany https://....--insert=0

6.3 Artifactory 연동 예시

# 1. remote 추가
conan remote add mycompany https://mycompany.jfrog.io/artifactory/api/conan/conan-local
# 2. 패키지 생성
conan create . mylib/1.0.0@
# 3. 업로드
conan upload "mylib/1.0.0" -r mycompany --all

6.4 소비 측에서 사내 레포 사용

# conanfile.txt
[requires]
mylib/1.0.0
[generators]
CMakeDeps
CMakeToolchain
# mycompany remote에서 먼저 찾도록
conan install . --output-folder=build --build=missing

7. 자주 발생하는 에러와 해결법

에러 1: “package_info() missing cpp_info.libs”

ERROR: .../package_info(): self.cpp_info.libs is empty

원인: package_info()에서 self.cpp_info.libs를 설정하지 않음 (라이브러리 패키지인 경우). 해결법:

def package_info(self):
    self.cpp_info.libs = [mylib]  # 실제 라이브러리 이름

헤더 전용이면:

def package_info(self):
    self.cpp_info.bindirs = []
    self.cpp_info.libdirs = []

에러 2: “exports_sources” 파일을 찾을 수 없음

ERROR: ....exports_sources ....not found

원인: exports_sources에 지정한 경로가 레시피 디렉터리에 없음. 해결법:

# 존재하는 경로만 지정
exports_sources = "CMakeLists.txt", "src/*", "include/*"
# 디렉터리 전체
exports_sources = "include/*"

에러 3: “CMake install failed” / “No install target”

CMake Error: ....install TARGETS given no RUNTIME DESTINATION

원인: CMakeLists.txt에 install() 타겟이 없거나 잘못됨. 해결법:

install(TARGETS mylib
    RUNTIME DESTINATION bin
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib
)
install(DIRECTORY include/ DESTINATION include)

에러 4: test_package에서 “find_package(mylib) failed”

원인: package_info()cpp_info가 CMakeDeps에 제대로 전달되지 않음. 또는 CMake 타겟 이름 불일치. 해결법:

def package_info(self):
    self.cpp_info.libs = [mylib]
    # CMake 타겟 이름 명시 (기본은 패키지 이름)
    self.cpp_info.set_property("cmake_target_name", "mylib::mylib")

에러 5: “Binary not found” / “Can’t find a compatible binary”

ERROR: Missing prebuilt package for 'mylib/1.0.0'

원인: 해당 설정(OS, 컴파일러, arch 등)에 맞는 바이너리가 원격·캐시에 없음. 해결법:

# 소스에서 빌드
conan create . --build=missing
# 특정 패키지만 빌드
conan create . --build=mylib

에러 6: “Version conflict” (의존성 간)

ERROR: Conflict in mylib/1.0.0: requirement 'fmt/9.x' conflicts with 'fmt/10.1.1'

원인: 직접·간접 의존성의 버전 요구가 충돌. 해결법:

def requirements(self):
    self.requires("fmt/10.1.1", override=True)  # 강제로 이 버전 사용

에러 7: “conan create” 시 “layout()” 관련 오류

ERROR: ....layout(): self.source_folder is None

원인: exports_sources만 있고 외부 소스를 쓰지 않을 때, layout()에서 self.source_folder를 잘못 참조. 해결법: cmake_layout(self) 사용 시, Conan이 source_folderexports_sources 기준으로 설정합니다. conan create는 레시피 디렉터리를 소스로 사용합니다.

에러 8: Windows에서 “fPIC” 옵션 에러

ERROR: option 'fPIC' doesn't exist

원인: Windows에서는 fPIC가 의미 없는데 옵션에 남아 있음. 해결법:

def config_options(self):
    if self.settings.os == "Windows":
        del self.options.fPIC

에러 9: “Package not found” (upload 후)

원인: remote 순서, 인증, 또는 패키지 참조 형식 오류. 해결법:

# remote 확인
conan remote list
# 패키지 검색
conan search mylib -r mycompany
# 인증 (Artifactory)
conan remote add mycompany https://....--insert=0
# 사용자/비밀번호는 conan config set으로 또는 환경변수

에러 10: package_info의 includedirs가 비어 있음

원인: CMake install(DIRECTORY include/ DESTINATION include)로 설치했는데, 패키지 폴더 구조가 다름. 해결법:

def package_info(self):
    self.cpp_info.includedirs = [include]
    # 또는 실제 구조에 맞게
    self.cpp_info.includedirs = [include/mylib]

8. 베스트 프랙티스

8.1 버전 관리

  • 시맨틱 버전링: 1.2.3, 2.0.0 형식 사용
  • conanfile.py의 version: 가능하면 단일 소스(예: scm 또는 외부 파일)에서 가져오기
from conan.tools.scm import Git
from conan import ConanFile
class MylibConan(ConanFile):
    name = "mylib"
    version = "1.0.0"  # 또는 동적: self.version = ...

8.2 options 설계

  • shared: 정적/동적 라이브러리 선택 — 대부분의 C++ 라이브러리가 지원
  • fPIC: Linux/macOS에서 공유 라이브러리 시 필요
  • with_xxx: 기능 플래그 (예: with_ssl, with_tests)
options = {
    "shared": [True, False],
    "fPIC": [True, False],
    "with_ssl": [True, False],
}
default_options = {
    "shared": False,
    "fPIC": True,
    "with_ssl": True,
}

8.3 CMake install 규칙

  • install(TARGETS ...)로 라이브러리·실행 파일 설치
  • install(DIRECTORY include/ DESTINATION include)로 헤더 설치
  • Conan의 cmake.install()CMAKE_INSTALL_PREFIX를 패키지 폴더로 설정하므로, CMake 표준 경로 사용

8.4 test_package 필수화

  • conan create 전에 반드시 test_package로 검증
  • 실제 소비 시나리오(빌드·링크·실행)를 테스트

8.5 package_info 명확화

def package_info(self):
    self.cpp_info.libs = [mylib]
    self.cpp_info.includedirs = [include]
    # 필요 시
    self.cpp_info.defines = [MYLIB_VERSION=100]
    self.cpp_info.cxxflags = []

8.6 exports_sources 최소화

  • 빌드에 필요한 파일만 포함
  • *.md, *.txt 등 불필요한 파일 제외
exports_sources = "CMakeLists.txt", "src/*", "include/*"

9. 프로덕션 패턴

패턴 1: CI에서 conan create

# .github/workflows/conan-package.yml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install Conan
        run: pip install conan
      - name: Create package
        run: conan create . --build=missing
      - name: Upload to Artifactory
        if: github.ref == 'refs/heads/main'
        run: |
          conan remote add mycompany ${{ secrets.CONAN_REMOTE_URL }} --insert=0
          conan user -r mycompany -p ${{ secrets.CONAN_PASSWORD }} ${{ secrets.CONAN_USER }}
          conan upload "mylib/*" -r mycompany --all

패턴 2: 버전 태그와 연동

# Git 태그에서 버전 추출
VERSION=$(git describe --tags --abbrev=0)
conan create . mylib/${VERSION}@
conan upload "mylib/${VERSION}" -r mycompany --all

패턴 3: conan export-pkg (기존 빌드 결과 패키징)

이미 빌드된 바이너리가 있을 때, 다시 빌드하지 않고 패키지로 만들 수 있습니다.

conan export-pkg . mylib/1.0.0@ -pf build/package

패턴 4: 프로필 공유

conan/
└── profiles/
    ├── linux-gcc12
    ├── windows-msvc2022
    └── macos-clang
conan create . -pr=conan/profiles/linux-gcc12

패턴 5: lockfile로 재현 가능한 빌드

# lockfile 생성
conan lock create .
# lockfile로 create (의존성 버전 고정)
conan create . --lockfile=conan.lock --build=missing

패턴 6: Docker로 멀티 플랫폼 패키지 생성

FROM ubuntu:22.04
RUN apt-get update && apt-get install -y python3-pip cmake g++ build-essential
RUN pip install conan
WORKDIR /app
COPY . .
RUN conan profile detect --force
RUN conan create . --build=missing

10. 구현 체크리스트

레시피 작성

  • name, version 정의
  • settings = “os”, “compiler”, “build_type”, “arch”
  • options (shared, fPIC 등) 필요 시 정의
  • config_options()에서 Windows fPIC 제거
  • exports_sources에 빌드 필요 파일만 포함
  • layout()에서 cmake_layout(self) 사용
  • generate()에서 CMakeToolchain, CMakeDeps 생성
  • build()에서 CMake configure + build
  • package()에서 cmake.install() 또는 copy()
  • package_info()에서 libs, includedirs 설정

CMake

  • install(TARGETS ...) 정의
  • install(DIRECTORY include/ ...) 정의
  • target_include_directories에 INSTALL_INTERFACE 포함

test_package

  • test_package/conanfile.py에서 self.tested_reference_str() 사용
  • test_package에서 실제 사용 시나리오 검증

배포

  • conan create 성공 확인
  • conan upload 전 remote·인증 설정
  • CI에서 자동 create·upload (선택)

정리

항목설명
레시피conanfile.py로 패키지 빌드·패키징·정보 정의
빌드conan create로 캐시에 패키지 생성
검증test_package로 소비 가능 여부 확인
배포conan upload로 원격 저장소에 업로드
에러package_info, exports_sources, CMake install 등 점검
핵심 원칙:
  1. package_info()를 반드시 올바르게 작성 — 소비자가 링크·include할 수 있게
  2. test_package로 패키지 품질 검증
  3. CMake install과 레시피의 package() 연동
  4. options로 플랫폼·기능별 바이너리 구성

자주 묻는 질문 (FAQ)

Q. 이 내용을 실무에서 언제 쓰나요?

A. 사내 라이브러리를 Conan 패키지로 배포할 때, Conan Center에 없는 라이브러리를 패키징할 때, 오픈소스 프로젝트를 Conan으로 배포할 때 활용합니다. conan install 한 번으로 팀 전체가 동일한 버전을 사용할 수 있습니다.

Q. conanfile.txt와 conanfile.py 중 뭘 써야 하나요?

A. 패키지를 만들 때는 반드시 conanfile.py입니다. 패키지를 쓸 때만 conanfile.txt로 충분합니다. 고급 옵션·조건부 의존성이 필요하면 소비 측에서도 conanfile.py를 씁니다.

Q. 선행으로 읽으면 좋은 글은?

A. vcpkg와 Conan 기초(#40-1)에서 Conan 사용법을 먼저 익히면 좋습니다. C++ 시리즈 목차에서 전체 흐름을 확인할 수 있습니다.

Q. 더 깊이 공부하려면?

A. Conan 2.x 공식 문서, JFrog Academy Conan 과정, Conan Center 레시피 GitHub를 참고하세요. 한 줄 요약: conanfile.py 레시피로 라이브러리를 Conan 패키지로 만들고, conan create·upload로 빌드·배포할 수 있습니다. 다음 글: [C++ #53-4] Conan 고급 완벽 가이드 | lockfile·크로스 빌드·사내 레포 이전 글: [C++ #53-3] vcpkg 고급 활용 | Manifest·Triplet·오버레이·바이너리 캐시

관련 글

심화 부록: 구현·운영 관점

이 부록은 앞선 본문에서 다룬 주제(「C++ Conan 레시피 작성 완벽 가이드 | 패키지·빌드·원격 저장소 [#53-4]」)를 구현·런타임·운영 관점에서 다시 압축합니다. 도메인별 세부 구현은 글마다 다르지만, 입력 검증 → 핵심 연산 → 부작용(I/O·네트워크·동시성) → 관측의 흐름으로 장애를 나누면 원인 추적이 빨라집니다.

내부 동작과 핵심 메커니즘

flowchart TD
  A[입력·요청·이벤트] --> B[파싱·검증·디코딩]
  B --> C[핵심 연산·상태 전이]
  C --> D[부작용: I/O·네트워크·동시성]
  D --> E[결과·관측·저장]
sequenceDiagram
  participant C as 클라이언트/호출자
  participant B as 경계(런타임·게이트웨이·프로세스)
  participant D as 의존성(API·DB·큐·파일)
  C->>B: 요청/이벤트
  B->>D: 조회·쓰기·RPC
  D-->>B: 지연·부분 실패·재시도 가능
  B-->>C: 응답 또는 오류(코드·상관 ID)
  • 불변 조건(Invariant): 버퍼 경계, 프로토콜 상태, 트랜잭션 격리, FD 상한 등 단계별로 문장으로 적어 두면 디버깅 비용이 줄어듭니다.
  • 결정성: 순수 층과 시간·네트워크·스케줄에 의존하는 층을 분리해야 테스트와 장애 분석이 쉬워집니다.
  • 경계 비용: 직렬화, 인코딩, syscall 횟수, 락 경합, 할당·GC, 캐시 미스를 의심 목록에 둡니다.
  • 백프레셔: 생산자가 소비자보다 빠를 때 버퍼·큐·스트림에서 속도를 줄이는 신호를 어디에 둘지 정의합니다.

프로덕션 운영 패턴

영역운영 관점 질문
관측성요청 단위 상관 ID, 에러율·지연 p95/p99, 의존성 타임아웃·재시도가 대시보드에 보이는가
안전성입력 검증·권한·비밀·감사 로그가 코드 경로마다 일관적인가
신뢰성재시도는 멱등 연산에만 적용되는가, 서킷 브레이커·백오프·DLQ가 있는가
성능캐시·배치 크기·커넥션 풀·인덱스·백프레셔가 데이터 규모에 맞는가
배포롤백 룬북, 카나리/블루그린, 마이그레이션·피처 플래그가 문서화되어 있는가
용량피크 트래픽·디스크·FD·스레드 풀 상한을 주기적으로 검증하는가

스테이징은 데이터 양·네트워크 RTT·동시성을 프로덕션에 가깝게 맞출수록 재현율이 올라갑니다.

확장 예시: 엔드투엔드 미니 시나리오

앞선 본문 주제(「C++ Conan 레시피 작성 완벽 가이드 | 패키지·빌드·원격 저장소 [#53-4]」)를 배포·운영 흐름에 맞춰 옮긴 체크리스트입니다. 도메인에 맞게 단계 이름만 바꿔 적용할 수 있습니다.

  1. 입력 계약 고정: 스키마·버전·최대 페이로드·타임아웃·에러 코드를 경계에 둔다.
  2. 핵심 경로 계측: 요청 ID, 단계별 지연, 외부 호출 결과 코드를 로그·메트릭·트레이스에서 한 흐름으로 본다.
  3. 실패 주입: 의존성 타임아웃·5xx·부분 데이터·락 대기를 스테이징에서 재현한다.
  4. 호환·롤백: 설정/마이그레이션/클라이언트 버전을 되돌릴 수 있는지 확인한다.
  5. 부하 후 검증: 피크 대비 p95/p99, 에러율, 리소스 상한, 알림 임계값을 점검한다.
handle(request):
  ctx = newCorrelationId()
  validated = validateSchema(request)
  authorize(validated, ctx)
  result = domainCore(validated)
  persistOrEmit(result, idempotentKey)
  recordMetrics(ctx, latency, outcome)
  return result

문제 해결(Troubleshooting)

증상가능 원인조치
간헐적 실패레이스, 타임아웃, 외부 의존성, DNS최소 재현 스크립트, 분산 트레이스·로그 상관관계, 재시도·서킷 설정 점검
성능 저하N+1, 동기 I/O, 락 경합, 과도한 직렬화, 캐시 미스프로파일러·APM으로 핫스팟 확인 후 한 가지씩 제거
메모리 증가캐시 무제한, 구독/리스너 누수, 대용량 버퍼, 커넥션 미반납상한·TTL·힙/FD 스냅샷 비교
빌드·배포만 실패환경 변수, 권한, 플랫폼 차이, lockfileCI 로그와 로컬 diff, 런타임·이미지 버전 핀
설정 불일치프로필·시크릿·기본값, 리전스키마 검증된 설정 단일 소스와 배포 매트릭스 표준화
데이터 불일치비멱등 재시도, 부분 쓰기, 캐시 무효화 누락멱등 키·아웃박스·트랜잭션 경계 재검토

권장 순서: (1) 최소 재현 (2) 최근 변경 범위 축소 (3) 환경·의존성 차이 (4) 관측으로 가설 검증 (5) 수정 후 회귀·부하 테스트.

배포 전에는 git addgit commitgit pushnpm run deploy 순서를 권장합니다.


같이 보면 좋은 글 (내부 링크)

이 주제와 연결되는 다른 글입니다.


이 글에서 다루는 키워드 (관련 검색어)

C++, Conan, 패키지관리, 빌드, CMake, 레시피 등으로 검색하시면 이 글이 도움이 됩니다.