C++ 의존성 관리 비교: vcpkg vs Conan vs 시스템 패키지, 버전 충돌과 CMake 통합

들어가며: “라이브러리 하나 추가하는데 하루가 걸려요”

“Boost 설치하다가 의존성 지옥에 빠졌어요”

C++에는 Python의 pip, Node.js의 npm처럼 언어 차원의 표준 패키지 관리자가 없습니다. 프로젝트마다 수동으로 소스 다운로드, CMake 설정, 링크 옵션을 맞추다 보면 의존성 지옥, 버전 충돌, 팀원마다 다른 빌드 결과가 발생합니다. 게다가 C++ 라이브러리는 소스가 아니라 컴파일된 바이너리로 공유되는 경우가 많아서, 같은 버전이라도 컴파일러·빌드 타입·런타임 라이브러리 설정이 다르면 링크가 안 되거나 실행 중에 깨집니다. 다른 언어의 패키지 관리자보다 C++ 쪽이 유독 복잡한 이유가 이 ABI 문제입니다. 비유하면 “창고에서 부품을 하나씩 찾아 조립하는 것”이 수동 관리라면, vcpkg·Conan은 “부품 목록만 주면 자동으로 맞는 버전을 가져와 조립해 주는 것”입니다.

flowchart LR
  subgraph problem[문제 상황]
    P1[의존성 지옥]
    P2[버전 충돌]
    P3[빌드 환경 불일치]
    P4[CI 실패]
  end
  subgraph solution[해결 방향]
    S1[vcpkg]
    S2[Conan]
    S3[시스템 패키지]
    S4[manifest 모드]
  end
  P1 --> S1
  P2 --> S2
  P3 --> S3
  P4 --> S4

vcpkg, Conan, 시스템 패키지 매니저로 같은 의존성을 설치해 보며 각각의 사용법과 운영 시 점검할 항목을 정리합니다.


의존성 관리가 막히는 다른 상황들

팀원마다 다른 빌드 결과

새 팀원이 git clone 후 cmake .. && make를 실행했는데 OpenSSL을 찾을 수 없습니다 에러가 납니다. 수동으로 설치한 경로가 다르고, 버전도 제각각입니다.

라이브러리 A와 B가 충돌

프로젝트에서 libA(1.2)와 libB(2.0)를 둘 다 쓰는데, libB가 내부적으로 libA(1.0)를 요구합니다. 전이 의존성 충돌로 링크 에러가 납니다.

CI에서만 실패

로컬에서는 빌드가 되는데, GitHub Actions에서 vcpkg 패키지를 찾을 수 없습니다 에러가 납니다. 캐시 설정·경로 설정이 로컬과 다릅니다.

프로덕션 빌드 재현 불가

6개월 전에 빌드한 바이너리와 동일한 결과를 내려고 하는데, vcpkg/Conan이 최신 버전을 가져와 ABI가 달라져 크래시가 납니다.

헤더만 있는 라이브러리 vs 바이너리

header-only 라이브러리는 빌드 없이 include만 하면 되는데, 빌드가 필요한 라이브러리와 섞여 있어 CMake 설정이 복잡해집니다.

시나리오특징권장 도구
팀 빌드 통일환경 동일화 필요vcpkg manifest, Conan
전이 의존성버전 충돌Conan (lockfile)
CI 재현성캐시·버전 고정vcpkg baseline, Conan lockfile
장기 재현성6개월+ 동일 빌드Conan revision, vcpkg overlay
헤더만빌드 불필요vcpkg/Conan 모두 지원

vcpkg·Conan·시스템 패키지 비교

도구별 특징

도구장점단점적합한 프로젝트
vcpkgMicrosoft 지원, VS 통합, manifest 모드기본은 소스 빌드, 바이너리 캐시는 별도 설정 필요Windows/VS 중심, 팀 규모 중소
Conan버전·바이너리 캐시 강력, lockfile학습 곡선, 설정 복잡크로스 플랫폼, CI/CD, 대규모
시스템 패키지OS 패키지와 통합, 재배포 용이버전 고정 어려움Linux 서버, 배포 환경 고정

의사결정 흐름

flowchart TB
  subgraph input[입력]
    Q1[Windows 중심?]
    Q2[버전 고정 필수?]
    Q3[배포 환경 고정?]
  end
  subgraph decision[의사결정]
    D1{Visual Studio?}
    D2{lockfile 필요?}
    D3{apt/yum 사용?}
  end
  subgraph result[선택]
    R1[vcpkg]
    R2[Conan]
    R3[시스템 패키지]
  end
  Q1 --> D1
  Q2 --> D2
  Q3 --> D3
  D1 -->|Yes| R1
  D2 -->|Yes| R2
  D3 -->|Yes| R3

vcpkg Manifest 모드와 baseline 고정

vcpkg 설치

# 1. vcpkg 클론
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
# 2. 부트스트랩 (Windows: bootstrap-vcpkg.bat, Unix: bash)
./bootstrap-vcpkg.sh
# 3. 환경 변수 (선택)
export VCPKG_ROOT=/path/to/vcpkg

Manifest 모드 (권장)

Manifest 모드는 프로젝트 루트에 vcpkg.json을 두며, 의존성을 선언하는 방식입니다. 프로젝트가 의존성을 소유합니다.

{
  "name": "my-project",
  "version": "1.0.0",
  "dependencies": [
    "boost-asio",
    "openssl",
    "spdlog",
    "nlohmann-json"
  ],
  "builtin-baseline": "<vcpkg 저장소의 40자리 커밋 SHA>"
}

설명:

  • builtin-baseline: vcpkg 레지스트리의 특정 커밋 SHA입니다. 그 커밋 시점의 포트 버전으로 기준이 고정되어 재현 가능한 빌드가 됩니다. 날짜나 릴리스 태그 문자열(2024.01.25 등)을 넣으면 builtin-baseline ... was not a valid commit sha: expected 40 hexadecimal characters 같은 에러가 나므로, vcpkg x-update-baseline --add-initial-baseline 명령으로 현재 vcpkg 체크아웃의 SHA를 자동으로 채우는 것이 가장 확실합니다.
  • dependencies: 필요한 패키지 목록. vcpkg가 자동으로 전이 의존성을 해결합니다.

CMake 연동 (Manifest 모드)

# CMakeLists.txt
cmake_minimum_required(VERSION 3.18)
project(MyProject CXX)
set(CMAKE_CXX_STANDARD 17)
# vcpkg 툴체인 파일 지정 (manifest 모드)
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake"
    CACHE STRING "VCPKG toolchain file")
# 또는 환경 변수로
# set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake")
find_package(PkgConfig REQUIRED)
find_package(spdlog CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(Boost REQUIRED COMPONENTS system)
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE
    spdlog::spdlog
    nlohmann_json::nlohmann_json
    OpenSSL::SSL
    Boost::system
)

툴체인 파일은 첫 번째 configure 전에 지정되어야 합니다. CMAKE_TOOLCHAIN_FILE은 project()가 컴파일러를 탐지할 때 읽히므로, 이미 한 번 configure한 빌드 디렉터리에 나중에 추가하면 반영되지 않고 find_package가 계속 실패합니다. 이때는 빌드 디렉터리(또는 CMakeCache.txt)를 지우고 다시 configure해야 합니다. 위처럼 project() 앞에서 set(... CACHE ...)로 지정하거나, 뒤에서 다룰 CMake Presets에 넣어 두면 이 실수를 피할 수 있습니다. 또 Boost는 라이브러리마다 CMake 타깃이 따로 있어서 Boost::Boost 같은 타깃은 없고, Boost::system, Boost::headers처럼 사용하는 구성 요소 이름으로 링크합니다.

vcpkg 버전 고정 (baseline)

{
  "name": "my-project",
  "version": "1.0.0",
  "dependencies": [
    {
      "name": "boost-asio",
      "version>=": "1.84.0"
    },
    {
      "name": "spdlog",
      "version>=": "1.12.0"
    }
  ],
  "builtin-baseline": "<40자리 커밋 SHA>",
  "overrides": [
    {
      "name": "openssl",
      "version": "3.2.0"
    }
  ]
}

설명:

  • version>=: 최소 버전 요구
  • overrides: 전이 의존성을 포함해 해당 패키지의 버전을 정확히 고정합니다. 다른 패키지가 더 높은 최소 버전을 요구해도 overrides가 이기므로, 호환되지 않는 버전을 고정하면 빌드는 되더라도 API 차이로 컴파일 에러가 날 수 있습니다.

vcpkg의 버전 해석은 npm과 다르게 동작한다는 점을 알아 두면 혼란이 줄어듭니다. vcpkg는 “조건을 만족하는 가장 낮은 버전”을 고르는 최소 버전 선택 방식이라, version>=는 “최신을 가져와라”가 아니라 “이 버전보다 낮으면 안 된다”는 하한일 뿐입니다. 실제로 쓰이는 버전은 baseline에 적힌 버전과 여러 version>= 조건 중 가장 높은 값으로 결정됩니다. 그래서 baseline을 바꾸지 않는 한 새 버전이 몰래 들어오지 않고, 이것이 재현성을 보장하는 핵심 장치입니다.

vcpkg 빌드 예제

# 프로젝트 루트에서
mkdir build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake
cmake --build .

vcpkg 오버레이 (커스텀 포트)

# CMakeLists.txt
set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_SOURCE_DIR}/custom-ports")
custom-ports/
  my-lib/
    portfile.cmake
    vcpkg.json
# custom-ports/my-lib/vcpkg.json
{
  "name": "my-lib",
  "version": "1.0.0",
  "description": "내부 라이브러리",
  "homepage": "https://github.com/myorg/my-lib",
  "license": "MIT",
  "supports": "windows | linux | osx"
}

Conan 2.x conanfile과 lockfile

Conan 설치

# pip로 설치
pip install conan
# 또는 pipx (격리)
pipx install conan
# 버전 확인
conan --version

conanfile.txt (레거시 방식)

[requires]
boost/1.84.0
openssl/3.2.0
spdlog/1.12.3
nlohmann_json/3.11.3
[generators]
CMakeDeps
CMakeToolchain
[options]
boost/*:shared=False
openssl/*:shared=False

conanfile.py (권장)

from conan import ConanFile
from conan.tools.cmake import CMakeToolchain, CMakeDeps, cmake_layout
from conan.tools.scm import GitVersion
class MyProjectConan(ConanFile):
    name = "my-project"
    version = "1.0.0"
    settings = "os", "compiler", "build_type", "arch"
    generators = "CMakeDeps", "CMakeToolchain"
    def layout(self):
        cmake_layout(self)
    def requirements(self):
        self.requires("boost/1.84.0")
        self.requires("openssl/3.2.0")
        self.requires("spdlog/1.12.3")
        self.requires("nlohmann_json/3.11.3")
    def generate(self):
        tc = CMakeToolchain(self)
        tc.generate()
        deps = CMakeDeps(self)
        deps.generate()

프로젝트 구조 (Conan 2.x)

my-project/
  conanfile.py
  CMakeLists.txt
  src/
    main.cpp

Conan 설치 및 빌드

# 1. Conan 프로필 생성 (최초 1회)
conan profile detect
# 2. 의존성 설치 (conanfile.txt 사용 시)
conan install . --output-folder=build --build=missing
# 3. conanfile.py 사용 시
conan install . --output-folder=build --build=missing
# 4. CMake 빌드
cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
cmake --build .

Conan lockfile (재현 가능 빌드)

# lockfile 생성
conan lock create .
# lockfile로 설치 (동일한 버전 보장)
conan install . --lockfile=conan.lock --output-folder=build

Conan CMakeLists.txt 연동

# CMakeLists.txt
cmake_minimum_required(VERSION 3.18)
project(MyProject CXX)
set(CMAKE_CXX_STANDARD 17)
# Conan이 생성한 파일들
find_package(spdlog CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(Boost REQUIRED COMPONENTS system)
add_executable(my_app src/main.cpp)
target_link_libraries(my_app PRIVATE
    spdlog::spdlog
    nlohmann_json::nlohmann_json
    OpenSSL::SSL
    Boost::Boost
)

Conan 옵션: 정적/동적 링크

# conanfile.py
def configure(self):
    self.options["boost"].shared = False
    self.options["openssl"].shared = False
# 설치 시 옵션 지정
conan install . -s build_type=Release -o "boost/*:shared=False"   # Conan 2.x 문법

Conan 1.x 자료를 보고 따라 하다 막히는 경우가 많습니다. Conan 2.x에서는 옵션 지정이 boost:shared 대신 boost/*:shared처럼 패키지 참조 패턴을 쓰고, conan profile new·conan profile update 명령과 cmake·cmake_find_package 같은 옛 제너레이터가 제거되었습니다. 인터넷 예제에서 이런 형태가 보이면 1.x 기준이라고 보면 됩니다. 또 Conan은 컴파일러·빌드 타입 조합마다 바이너리 패키지를 따로 관리하므로, Conan Center에 내 설정과 맞는 바이너리가 없으면 Missing prebuilt package 에러가 납니다. 위 명령들이 --build=missing을 붙이는 이유가 이것으로, 없는 바이너리만 소스에서 빌드하라는 뜻입니다.

Conan 원격 저장소

# 기본 원격 확인
conan remote list
# Conan Center (기본)
conan remote add conancenter https://center.conan.io
# 사내 저장소
conan remote add mycompany https://artifactory.mycompany.com/conan

apt·pkg-config 시스템 패키지와 Docker

apt (Ubuntu/Debian)

# 개발 패키지 설치 (헤더 + lib)
sudo apt update
sudo apt install -y libssl-dev libboost-all-dev
# CMake에서 찾기
# find_package(OpenSSL REQUIRED)
# find_package(Boost REQUIRED COMPONENTS system)

pkg-config 연동

# CMakeLists.txt
find_package(PkgConfig REQUIRED)
pkg_check_modules(OPENSSL REQUIRED openssl)
pkg_check_modules(SPDLOG REQUIRED spdlog)
target_include_directories(my_app PRIVATE ${OPENSSL_INCLUDE_DIRS})
target_link_libraries(my_app PRIVATE ${OPENSSL_LIBRARIES})

system 패키지와 vcpkg 혼용

# 시스템에 OpenSSL이 있으면 사용, 없으면 vcpkg
find_package(OpenSSL QUIET)
if(NOT OpenSSL_FOUND)
    find_package(OpenSSL REQUIRED)  # vcpkg에서
endif()

Dockerfile 예제 (시스템 패키지)

FROM ubuntu:22.04
RUN apt-get update && apt-get install -y \
    build-essential \
    cmake \
    libssl-dev \
    libboost-all-dev \
    libspdlog-dev \
    nlohmann-json3-dev \
    && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY . .
RUN mkdir build && cd build && cmake .. && cmake --build .

vcpkg in Docker

FROM ubuntu:22.04
RUN apt-get update && apt-get install -y \
    build-essential \
    cmake \
    git \
    && rm -rf /var/lib/apt/lists/*
# vcpkg 설치
RUN git clone https://github.com/Microsoft/vcpkg.git /opt/vcpkg \
    && /opt/vcpkg/bootstrap-vcpkg.sh
ENV VCPKG_ROOT=/opt/vcpkg
ENV PATH="${VCPKG_ROOT}:${PATH}"
WORKDIR /app
COPY . .
RUN mkdir build && cd build \
    && cmake .. -DCMAKE_TOOLCHAIN_FILE=${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake \
    && cmake --build .

패키지 탐색 실패·ABI 충돌·lockfile 문제

”Could not find a package configuration file”

증상: find_package(spdlog CONFIG REQUIRED) 에러 원인: vcpkg/Conan이 설치한 패키지 경로를 CMake가 찾지 못함

# ❌ 잘못된 예 — 툴체인 파일 없이 실행
cmake ..

해결법:

# ✅ vcpkg — 툴체인 파일 지정
cmake .. -DCMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake
# ✅ Conan — conan install 후 CMake
conan install . --output-folder=build
cd build && cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake

vcpkg “portfile failed”

증상: Error: vcpkg package installation failed 원인: 포트 빌드 실패, 의존성 누락, 플랫폼 미지원

# 해결 1: 빌드 로그 확인
vcpkg install spdlog --debug
# 해결 2: baseline 업데이트
# vcpkg.json의 builtin-baseline을 더 최신으로
# 해결 3: 특정 패키지 제외 후 수동 설치
# vcpkg.json에서 해당 패키지 제거, 시스템 패키지 사용

Conan “version not found”

증상: ERROR: boost/1.99.0: not found in remote 원인: Conan Center에 해당 버전이 없음

# 해결: 사용 가능한 버전 확인
conan search boost --remote=conancenter
# 또는 conanfile.py에서 버전 수정
# self.requires("boost/1.84.0")  # 존재하는 버전으로

ABI 충돌 (mixed compiler)

증상: 링크 시 undefined reference 또는 런타임 크래시 원인: vcpkg/Conan으로 빌드한 라이브러리와 앱의 컴파일러·버전이 다름

# ❌ 위험한 조합
# vcpkg: gcc-9로 빌드
# 앱: gcc-11로 빌드
# → 링크는 되지만 std::string ABI 등 불일치
# ✅ 해결: 동일 툴체인
# vcpkg와 앱 모두 같은 gcc 버전 사용
export CXX=g++-11
export CC=gcc-11

”cannot open shared object file” (런타임)

증상: 빌드는 성공했는데 실행 시 libfoo.so: cannot open shared object file 원인: 동적 라이브러리 경로가 없음

# 해결 1: LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/path/to/vcpkg/installed/x64-linux/lib:$LD_LIBRARY_PATH
./my_app
# 해결 2: RPATH 빌드 시 설정
# CMakeLists.txt
set(CMAKE_INSTALL_RPATH "$ORIGIN")
set(CMAKE_BUILD_RPATH_USE_ORIGIN TRUE)
# 해결 3: 정적 링크
# vcpkg: 빌드 타입이 아니라 triplet이 결정 (x64-linux는 기본 정적, x64-windows는 기본 동적)
# Conan: -o "*:shared=False"

vcpkg manifest 모드에서 패키지 없음

증상: vcpkg.json을 두었는데 CMake가 패키지를 찾지 못함 원인: CMAKE_TOOLCHAIN_FILE이 vcpkg를 가리키지 않거나, vcpkg.json 경로가 잘못됨

# ✅ 올바른 설정
# vcpkg.json은 프로젝트 루트(CMakeLists.txt와 같은 위치)
# 프로젝트 루트에서 cmake -B build
# vcpkg/ 가 서브디렉터리면:
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake"
    CACHE STRING "VCPKG toolchain")

Conan “lockfile out of date”

증상: conan.lock is out of date 원인: conanfile.py 또는 의존성 버전이 변경됨

# 해결: lockfile 재생성
conan lock create .
conan install . --lockfile=conan.lock --output-folder=build

증상: cannot open file 'libssl.lib' 원인: OpenSSL 등이 동적 링크로 빌드되었는데, 정적 링크를 시도하는 경우

# vcpkg: triplet 사용
# x64-windows-static
cmake .. -DCMAKE_TOOLCHAIN_FILE=... -DVCPKG_TARGET_TRIPLET=x64-windows-static

정적 triplet(x64-windows-static)은 라이브러리를 정적으로 만들 뿐 아니라 C 런타임도 정적(/MT) 으로 빌드합니다. 애플리케이션이 기본값인 동적 런타임(/MD)으로 빌드되면 LNK2038: mismatch detected for 'RuntimeLibrary': value 'MT_StaticRelease' doesn't match value 'MD_DynamicRelease' 에러가 나므로, 앱 쪽도 set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")로 맞추거나, 라이브러리만 정적이고 런타임은 동적인 x64-windows-static-md triplet을 쓰는 편이 간단합니다. Windows에서 링크 에러가 이해되지 않을 때는 대부분 triplet과 런타임 설정의 불일치입니다.

헤더 충돌 (multiple definitions)

증상: redefinition of 'struct foo' 또는 multiple definition 원인: vcpkg/Conan 패키지와 시스템 패키지가 동시에 include됨

# ❌ 위험: 시스템 경로가 먼저
include_directories(/usr/include)  # 시스템
target_link_libraries(my_app vcpkg::spdlog)  # vcpkg
# ✅ 해결: vcpkg/Conan 경로만 사용
# CMAKE_TOOLCHAIN_FILE 사용 시 vcpkg 경로가 우선
# target_link_libraries에만 의존하면 include 경로는 자동
target_link_libraries(my_app PRIVATE spdlog::spdlog)

CI에서 vcpkg 빌드 타임아웃

증상: GitHub Actions에서 vcpkg 설치가 매번 오래 걸림 해결: 캐시

vcpkg는 기본적으로 모든 패키지를 소스에서 빌드하므로, 캐시가 없는 CI에서는 Boost·OpenSSL 같은 큰 의존성 빌드에 매번 긴 시간이 듭니다. 아래처럼 설치 디렉터리를 통째로 캐시하는 방법이 가장 간단하지만, 캐시 키에 vcpkg.json만 넣으면 baseline이나 triplet, 컴파일러 버전이 바뀌어도 옛 바이너리를 재사용하는 문제가 있습니다. 키에 vcpkg 커밋 SHA와 러너 이미지 버전까지 넣거나, vcpkg의 바이너리 캐싱(VCPKG_BINARY_SOURCES로 파일 공유·NuGet 피드·클라우드 스토리지 지정)을 쓰면 패키지 단위로 ABI 해시를 비교해 재사용하므로 더 안전합니다.

# .github/workflows/build.yml
- name: Cache vcpkg
  uses: actions/cache@v4
  with:
    path: build/vcpkg_installed
    key: vcpkg-${{ runner.os }}-${{ hashFiles('vcpkg.json') }}
- name: Configure
  run: cmake -B build -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake

Manifest·lockfile로 재현 가능한 빌드 만들기

Manifest / Lockfile 사용

원칙: 의존성을 코드로 선언하며, 버전을 고정합니다.

// vcpkg.json — builtin-baseline 필수
{
  "builtin-baseline": "<40자리 커밋 SHA>",
  "dependencies": ["spdlog"]
}
# Conan — lockfile 커밋
conan lock create .
git add conan.lock

프로젝트별 격리

원칙: 전역 설치보다 프로젝트별 설치를 사용합니다.

# vcpkg: manifest 모드 (프로젝트별)
# vcpkg.json이 프로젝트에 있음
# Conan: --output-folder=build (프로젝트별)
conan install . --output-folder=build

CI에서 재현 가능 빌드

# vcpkg: baseline 고정
# Conan: lockfile 사용
- run: conan install . --lockfile=conan.lock --output-folder=build

의존성 최소화

// ❌ 나쁜 예 — 전체 Boost
"dependencies": ["boost"]
// ✅ 좋은 예 — 필요한 컴포넌트만
"dependencies": ["boost-asio", "boost-system"]

private vs public 의존성

# 라이브러리: PRIVATE — 내부 구현만 사용
target_link_libraries(my_lib PRIVATE spdlog::spdlog)
# 인터페이스 노출 시: PUBLIC
target_link_libraries(my_lib PUBLIC nlohmann_json::nlohmann_json)

헤더 전용 라이브러리

# vcpkg/Conan 모두 header-only 지원
# find_package 후 target_link_libraries만 하면 include 경로 자동
find_package(nlohmann_json CONFIG REQUIRED)
target_link_libraries(my_app PRIVATE nlohmann_json::nlohmann_json)

크로스 컴파일

# vcpkg: triplet
vcpkg install spdlog --triplet=arm64-linux
# Conan 2.x: 프로필 파일을 직접 작성 (profile new/update 명령은 2.x에서 제거됨)
cat > ~/.conan2/profiles/arm <<'EOF'
[settings]
os=Linux
arch=armv8
compiler=gcc
compiler.version=12
compiler.libcxx=libstdc++11
build_type=Release
EOF
conan install . --profile:host=arm --profile:build=default --build=missing

CMake Presets 연동·Docker 멀티스테이지·버전 매트릭스

vcpkg + CMake Presets

// CMakePresets.json
{
  "version": 3,
  "configurePresets": [
    {
      "name": "vcpkg",
      "cacheVariables": {
        "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake"
      }
    }
  ]
}
cmake --preset vcpkg

Conan + CMake FetchContent 대체

# CMakeLists.txt
# Conan이 의존성을 해결하므로 FetchContent 불필요
find_package(spdlog CONFIG REQUIRED)
# ...

계층적 의존성 (라이브러리 → 앱)

my-project/
  libs/
    core/           # conanfile.py, vcpkg.json
    network/        # core 의존
  apps/
    server/         # core, network 의존
# libs/network/conanfile.py
def requirements(self):
    self.requires("core/1.0.0")  # 내부 패키지
    self.requires("boost/1.84.0")

Docker 멀티스테이지 (vcpkg)

# Stage 1: vcpkg로 의존성 빌드
FROM ubuntu:22.04 AS vcpkg
RUN apt-get update && apt-get install -y git cmake build-essential
RUN git clone https://github.com/Microsoft/vcpkg.git /vcpkg
WORKDIR /vcpkg
RUN ./bootstrap-vcpkg.sh
COPY vcpkg.json .
RUN ./vcpkg install --x-install-root=installed
# Stage 2: 앱 빌드
FROM ubuntu:22.04 AS build
RUN apt-get update && apt-get install -y cmake build-essential
# 툴체인 파일(scripts/)과 설치 결과를 함께 가져와야 함
COPY --from=vcpkg /vcpkg /vcpkg
COPY . /app
WORKDIR /app/build
RUN cmake .. -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake \
             -DVCPKG_INSTALLED_DIR=/vcpkg/installed -DVCPKG_MANIFEST_INSTALL=OFF
RUN cmake --build .
# Stage 3: 최종 이미지
FROM ubuntu:22.04
COPY --from=build /app/build/my_app /usr/local/bin/

버전 매트릭스 (CI)

# .github/workflows/build.yml
strategy:
  matrix:
    vcpkg_ref: ["<릴리스 태그 A>", "<릴리스 태그 B>"]   # 체크아웃할 vcpkg 릴리스 태그 (baseline은 해당 커밋 SHA)
    compiler: [gcc-11, clang-14]

빌드 시나리오 시퀀스

sequenceDiagram
    participant Dev as 개발자
    participant CMake as CMake
    participant vcpkg as vcpkg
    participant Build as 빌드
    Dev->>CMake: cmake -B build
    CMake->>vcpkg: vcpkg.json 읽기
    vcpkg->>vcpkg: 설치/캐시 확인
    vcpkg->>CMake: 툴체인 파일 제공
    CMake->>CMake: find_package
    CMake->>Build: 구성 완료
    Dev->>Build: cmake --build

의존성 관리 점검 목록

- [ ] vcpkg.json 또는 conanfile.py로 의존성 선언
- [ ] builtin-baseline 또는 conan.lock로 버전 고정
- [ ] CI에서 캐시 사용 (vcpkg_installed, Conan cache)
- [ ] 동일 툴체인으로 빌드 (컴파일러·버전)
- [ ] 정적 링크 고려 (배포 환경에 lib 없을 때)
- [ ] Dockerfile에 멀티스테이지 적용
- [ ] 의존성 업데이트 시 ABI 검증

도구 선택 요약

도구핵심 명령버전 고정CI 적합
vcpkgvcpkg.json + manifestbuiltin-baseline, overrides✅
Conanconanfile.py, conan installlockfile✅
시스템apt/yum install패키지 버전제한적

선택 가이드

  • Windows + Visual Studio: vcpkg
  • 크로스 플랫폼 + lockfile: Conan
  • Linux 서버 배포: 시스템 패키지 또는 vcpkg/Conan

핵심 원칙

  1. 의존성을 코드로 선언 — vcpkg.json, conanfile.py
  2. 버전 고정 — baseline, lockfile, overrides
  3. 동일 툴체인 — ABI 충돌 방지
  4. CI 캐시 — 빌드 시간 단축
  5. 의존성 최소화 — 필요한 패키지만

자주 묻는 질문 (FAQ)

Q. vcpkg와 Conan을 같이 쓸 수 있나요?

A. 권장하지 않습니다. 같은 프로젝트에서 둘을 혼용하면 include 경로·라이브러리 경로가 충돌할 수 있습니다. 하나를 선택해 일관되게 사용하세요.

Q. 사내 프라이빗 라이브러리는 어떻게 하나요?

A. vcpkg: overlay-ports로 커스텀 포트 추가. Conan: 사내 Artifactory 등에 Conan 원격 저장소 추가 후 conan install 시 --remote 지정.

Q. 헤더 전용 라이브러리만 쓸 때도 vcpkg/Conan이 필요한가요?

A. 단순히 include만 하면 된다면 Git submodule이나 FetchContent로도 가능합니다. 다만 vcpkg/Conan을 쓰면 버전 관리·팀 통일이 일관됩니다.


참고 자료


같이 보면 좋은 글