[2026] C++ 패키지 매니저 | vcpkg·Conan으로 라이브러리 설치 지옥 탈출하기
이 글의 핵심
C++ 패키지 매니저: vcpkg·Conan으로 라이브러리 설치 지옥 탈출하기. 라이브러리 설치가 너무 어렵다·실무에서 겪는 패키지 관리 고통.
들어가며: 라이브러리 설치가 너무 어렵다
”Boost 설치하는데 하루가 걸렸어요”
프로젝트에 Boost 라이브러리를 추가하려고 했습니다. 하지만:
- 소스 다운로드
- 빌드 스크립트 실행
- 헤더 경로 설정
- 라이브러리 경로 설정
- 플랫폼별로 다른 설정 하루가 걸렸습니다. vcpkg·Conan 같은 패키지 매니저(라이브러리 다운로드·빌드·경로 설정을 자동화하는 도구)는 “의존성(다른 라이브러리·도구에 대한 필요)—이름과 버전”만 적으면 다운로드·빌드·경로 설정을 자동으로 해 줍니다. 팀 전체가 같은 버전의 라이브러리를 쓰게 할 수 있어서, “내 PC에서는 되는데 CI에서 안 된다” 같은 문제를 줄이는 데 도움이 됩니다. 아래 코드는 mermaid를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 실행 예제
flowchart LR
subgraph manual[수동 설치]
M1[소스 다운로드] --> M2[빌드]
M2 --> M3[경로 설정]
M3 --> M4[플랫폼별 설정]
end
subgraph pm[패키지 매니저]
P1[vcpkg.json / conanfile] --> P2[자동 설치]
P2 --> P3[CMake 연동]
end
vcpkg로 해결: vcpkg는 vcpkg install boost 한 줄로 Boost를 다운로드·빌드·설치하고, vcpkg integrate install을 해 두면 CMake가 vcpkg 설치 경로를 자동으로 찾습니다. 그래서 find_package(Boost REQUIRED)만 해도 include·라이브러리 경로가 설정되고, target_link_libraries(myapp PRIVATE Boost::boost)로 링크할 수 있습니다. 수동으로 경로 잡지 않아도 되어 “Boost 설치하는데 하루 걸리던” 상황을 크게 줄일 수 있습니다. 아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# 복사해 붙여넣은 뒤: vcpkg가 설치된 디렉터리에서 실행. 설치 후 CMake에서 -DCMAKE_TOOLCHAIN_FILE=[vcpkg]/scripts/buildsystems/vcpkg.cmake 로 사용
vcpkg install boost-asio
# CMake에서 자동 인식 (toolchain 지정 시)
# find_package(Boost REQUIRED)
# target_link_libraries(myapp PRIVATE Boost::boost)
실행 결과: vcpkg가 Boost.Asio를 다운로드·빌드하고, vcpkg list에 boost-asio가 보이면 설치 완료입니다.
실행 가능 예제 (vcpkg 설치 후 빌드할 수 있는 최소 C++ 프로그램):
아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 코드를 직접 실행해보면서 동작을 확인해보세요.
// 복사해 붙여넣은 뒤: vcpkg로 설치한 툴체인으로 CMake 빌드하거나, 의존성 없이 g++ -std=c++17 -o demo main.cpp && ./demo
#include <iostream>
int main() {
std::cout << "vcpkg로 환경을 맞춘 뒤 이 프로젝트를 빌드하면 됩니다.\n";
return 0;
}
이 글을 읽으면:
- vcpkg로 라이브러리를 쉽게 설치할 수 있습니다.
- Conan으로 의존성을 관리할 수 있습니다.
- 프로젝트 의존성을 명시적으로 관리할 수 있습니다.
- 실전에서 재현 가능한 빌드를 만들 수 있습니다.
실무 적용 경험: 이 글은 대규모 C++ 프로젝트에서 실제로 겪은 문제와 해결 과정을 바탕으로 작성되었습니다. 책이나 문서에서 다루지 않는 실전 함정과 디버깅 팁을 포함합니다.
문제 시나리오: 실무에서 겪는 패키지 관리 고통
시나리오 1: “내 PC에서는 되는데 CI에서 안 돼요”
증상: 로컬에서는 빌드가 되는데, GitHub Actions나 Jenkins에서 find_package(fmt) failed 에러가 납니다.
원인: 로컬에 수동으로 설치한 라이브러리가 CI 환경에는 없음. 시스템 패키지(apt, brew)로 설치하면 버전이 플랫폼마다 달라짐.
해결: vcpkg.json 또는 conanfile로 의존성을 선언하고, CI에서 toolchain/profile을 지정해 동일한 환경으로 빌드.
시나리오 2: “라이브러리 버전이 바뀌어서 빌드가 깨졌어요”
증상: 어제까지 잘 되던 프로젝트가 오늘 conan install 후 빌드 에러가 납니다.
원인: 의존성에 버전 범위를 넣지 않아 최신 버전이 설치됨. API 변경으로 호환성이 깨짐.
해결: vcpkg는 builtin-baseline으로, Conan은 fmt/9.1.0처럼 명시적 버전으로 고정.
시나리오 3: “헤더는 찾는데 링크 에러가 나요”
증상: undefined reference to 'fmt::v9::format(...)' 같은 링크 에러.
원인: find_package는 찾았지만 target_link_libraries에 누락했거나, 동적/정적 라이브러리 혼용(예: Release로 빌드한 fmt를 Debug로 링크).
해결: target_link_libraries(myapp PRIVATE fmt::fmt) 명시, 트리플렛/프로파일에서 build_type 일치 확인.
시나리오 4: “의존성 트리가 꼬였어요”
증상: A는 Boost 1.70, B는 1.80을 요구하는데 둘 다 링크해야 하는 상황. 원인: 전역 설치된 라이브러리나 여러 패키지 매니저 혼용. 해결: Manifest 모드(vcpkg.json) 또는 conanfile로 프로젝트별 격리. 한 프로젝트 내에서는 하나의 버전만 사용.
시나리오 5: “빌드가 너무 오래 걸려요”
증상: vcpkg install 또는 conan install이 30분 이상 걸림.
원인: 바이너리 캐시 없이 매번 소스에서 빌드. CI에서 매번 클린 빌드.
해결: vcpkg binary cache, Conan remote 캐시 활용. CI에서는 의존성 캐시 레이어 분리.
목차
- vcpkg 시작하기
- vcpkg 고급 사용법
- vcpkg 완전 예제
- Conan 시작하기
- Conan 고급 사용법
- Conan 완전 예제
- 비교와 선택
- 자주 발생하는 에러와 해결법
- 베스트 프랙티스
- 프로덕션 패턴
1. vcpkg 시작하기
설치
vcpkg는 Git 저장소를 클론한 뒤 bootstrap 스크립트를 실행해 vcpkg 실행 파일을 만듭니다. Linux/macOS는 ./bootstrap-vcpkg.sh, Windows는 .\bootstrap-vcpkg.bat을 쓰면 됩니다. 이후 vcpkg 명령은 이 디렉토리에서 실행하거나, PATH에 넣어 두고 사용합니다. 한 번 설치해 두면 여러 프로젝트에서 같은 vcpkg 인스턴스를 쓸 수 있습니다. 아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 복사해 붙여넣은 뒤: 프로젝트 밖 디렉터리에서 실행. 완료 후 vcpkg.exe(Windows) 또는 vcpkg(Linux/Mac) 실행 파일이 생성됨
# Linux/Mac
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
# Windows (PowerShell 또는 cmd)
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
.\bootstrap-vcpkg.bat
실행 결과: vcpkg(또는 vcpkg.exe) 실행 파일이 생성되고, ./vcpkg version으로 확인할 수 있습니다.
기본 사용법
vcpkg search json으로 이름에 “json”이 들어간 패키지를 검색하고, vcpkg install nlohmann-json으로 해당 패키지를 설치합니다. 설치된 목록은 vcpkg list로 확인하고, vcpkg remove nlohmann-json으로 제거할 수 있습니다. 패키지 이름은 vcpkg 포트 이름이라 라이브러리 공식 이름과 다를 수 있으므로(예: nlohmann-json), search로 정확한 이름을 확인하는 것이 좋습니다. 아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 라이브러리 검색
vcpkg search json
# 라이브러리 설치
vcpkg install nlohmann-json
# 설치된 라이브러리 확인
vcpkg list
# 라이브러리 제거
vcpkg remove nlohmann-json
CMake 통합
vcpkg integrate install을 실행하면 vcpkg가 시스템에 통합 스크립트를 등록합니다. CMake로 프로젝트를 configure할 때 -DCMAKE_TOOLCHAIN_FILE=[vcpkg 루트]/scripts/buildsystems/vcpkg.cmake를 주면, find_package가 vcpkg로 설치한 패키지를 찾고, target_link_libraries만 해도 include·링크 경로가 자동으로 붙습니다. 그래서 CMakeLists.txt는 “find_package + target_link_libraries”만 쓰면 되고, 경로를 수동으로 지정할 필요가 없습니다. 아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# CMake 통합 설정
vcpkg integrate install
# CMakeLists.txt에서 자동 인식
# find_package(nlohmann_json REQUIRED)
# target_link_libraries(myapp PRIVATE nlohmann_json::nlohmann_json)
2. vcpkg 고급 사용법
vcpkg.json (Manifest Mode)
Manifest 모드에서는 프로젝트 루트에 vcpkg.json을 두고 의존성을 선언합니다. dependencies 배열에 패키지 이름을 문자열로 넣거나, name과 features(Boost의 system, filesystem 등)를 객체로 지정할 수 있습니다. 이렇게 하면 cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=…로 빌드할 때 vcpkg가 vcpkg.json을 읽고 필요한 패키지를 자동으로 설치합니다. 팀원이나 CI가 같은 파일만 있으면 동일한 의존성으로 빌드할 수 있어 재현성이 좋아집니다. 아래 코드는 json를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
{
"name": "myproject",
"version": "1.0.0",
"dependencies": [
"fmt",
"spdlog",
"nlohmann-json",
{
"name": "boost",
"features": ["system", "filesystem"]
}
]
}
사용:
# vcpkg.json이 있는 디렉토리에서
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=[vcpkg root]/scripts/buildsystems/vcpkg.cmake
cmake --build build
트리플렛 (플랫폼 지정)
트리플렛은 vcpkg가 “어떤 플랫폼·아키텍처·링크 방식”으로 빌드할지 구분하는 이름입니다. x64-windows는 Windows 64비트, x64-linux는 Linux 64비트, x64-osx는 macOS입니다. x64-windows-static은 정적 링크로 빌드해, 실행 파일 하나에 라이브러리를 포함하고 싶을 때 씁니다. Manifest 모드에서도 트리플렛을 지정할 수 있어, CI에서 x64-linux로 빌드하고 로컬에서는 x64-windows로 빌드하는 식으로 나눌 수 있습니다. 아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# Windows 64비트
vcpkg install fmt:x64-windows
# Linux 64비트
vcpkg install fmt:x64-linux
# macOS
vcpkg install fmt:x64-osx
# 정적 라이브러리
vcpkg install fmt:x64-windows-static
버전 고정
version>=로 최소 버전을 요구하고, builtin-baseline에 vcpkg 저장소의 커밋 날짜(또는 커밋 해시)를 넣으면, 그 시점의 포트 버전을 기준으로 의존성이 잡힙니다. 이렇게 하면 “오늘은 9.1.0인데 내일 9.2.0으로 바뀌어서 빌드가 깨지는” 상황을 막을 수 있습니다. 팀 전체가 같은 baseline을 쓰면 동일한 버전으로 빌드되어 “내 PC에서는 되는데 CI에서 안 된다”를 줄일 수 있습니다. 아래 코드는 json를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
{
"name": "myproject",
"version": "1.0.0",
"dependencies": [
{
"name": "fmt",
"version>=": "9.1.0"
}
],
"builtin-baseline": "2023-04-15"
}
3. vcpkg 완전 예제
프로젝트 구조
아래 코드는 text를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
myapp-vcpkg/
├── CMakeLists.txt
├── vcpkg.json
├── src/
│ └── main.cpp
└── tests/
└── test_main.cpp
vcpkg.json (의존성 선언)
다음은 json를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
{
"name": "myapp-vcpkg",
"version": "1.0.0",
"description": "vcpkg를 사용한 C++ 프로젝트 예제",
"dependencies": [
"fmt",
"spdlog",
{
"name": "nlohmann-json",
"version>=": "3.11.0"
},
{
"name": "boost-asio",
"features": [ssl]
}
],
"builtin-baseline": "a1c7f64"
}
CMakeLists.txt
다음은 cmake를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
cmake_minimum_required(VERSION 3.15)
project(MyAppVcpkg LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
# vcpkg가 toolchain으로 지정되면 find_package가 vcpkg 설치 경로를 자동으로 찾음
find_package(fmt REQUIRED)
find_package(spdlog REQUIRED)
find_package(nlohmann_json REQUIRED)
find_package(Boost REQUIRED COMPONENTS system)
add_executable(myapp src/main.cpp)
target_link_libraries(myapp PRIVATE
fmt::fmt
spdlog::spdlog
nlohmann_json::nlohmann_json
Boost::system
)
src/main.cpp (실행 가능한 예제)
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <iostream>
#include <fmt/core.h>
#include <spdlog/spdlog.h>
#include <nlohmann/json.hpp>
#include <boost/asio.hpp>
int main() {
spdlog::info("vcpkg 예제 시작");
// fmt 사용
std::cout << fmt::format("Hello, {}!\n", "vcpkg");
// nlohmann-json 사용
auto j = nlohmann::json::parse(R"({"name": "myapp", "version": 1})");
std::cout << "JSON: " << j.dump() << "\n";
// Boost.Asio 사용 (타이머만)
boost::asio::io_context io;
boost::asio::steady_timer t(io, boost::asio::chrono::seconds(1));
t.async_wait( { spdlog::info("타이머 완료"); });
io.run();
return 0;
}
빌드 명령
아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# VCPKG_ROOT을 vcpkg 설치 경로로 설정
export VCPKG_ROOT=/path/to/vcpkg
cmake -B build -S . \
-DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake
cmake --build build
./build/myapp
4. Conan 시작하기
설치
아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# pip로 설치
pip install conan
# 버전 확인
conan --version
기본 사용법
conan profile detect —force는 현재 환경(OS, 컴파일러, 아키텍처)을 감지해 기본 프로파일을 만듭니다. conanfile.txt에는 [requires]에 패키지와 버전을, [generators]에 CMakeDeps와 CMakeToolchain을 넣어 두면, conan install . —build=missing 시 Conan이 의존성을 설치하고 CMake가 쓸 설정 파일(conan_toolchain.cmake 등)을 생성합니다. —build=missing은 로컬/캐시에 없으면 해당 패키지를 빌드한다는 뜻입니다. 아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# 프로파일 생성
conan profile detect --force
# 라이브러리 검색
conan search fmt -r conancenter
# conanfile.txt 생성 후 의존성 설치
conan install . --build=missing
conanfile.txt 예시
아래 코드는 ini를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
[requires]
fmt/9.1.0
spdlog/1.11.0
[generators]
CMakeDeps
CMakeToolchain
[layout]
cmake_layout
CMake 통합
conan install을 먼저 실행하면 빌드 디렉토리에 conan_toolchain.cmake 등이 생성됩니다. CMake configure 시 -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake를 넘기면, Conan이 만든 경로와 타겟이 적용되어 find_package(fmt) 등이 Conan으로 설치한 패키지를 찾습니다. vcpkg는 툴체인 파일만 주면 자동으로 manifest를 읽는 반면, Conan은 conan install을 먼저 돌려야 하므로 빌드 스크립트나 문서에 순서를 명시해 두는 것이 좋습니다. 다음은 cmake를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(MyProject)
set(CMAKE_CXX_STANDARD 17)
# Conan toolchain 로드 (conan install 후 build/conan_toolchain.cmake 생성됨)
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_BINARY_DIR}/conan_toolchain.cmake" CACHE PATH "" FORCE)
find_package(fmt REQUIRED)
find_package(spdlog REQUIRED)
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE
fmt::fmt
spdlog::spdlog
)
빌드: 아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# 1. 의존성 설치 (반드시 먼저)
conan install . --build=missing
# 2. CMake 빌드
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake
cmake --build build
5. Conan 고급 사용법
conanfile.py
conanfile.py는 Python으로 의존성·빌드·패키징을 제어하는 방식입니다. requirements()에서 self.requires()로 런타임 의존성을, build_requirements()에서 self.test_requires()로 테스트용 의존성(GTest 등)을 선언합니다. layout()으로 소스·빌드 디렉토리 구조를 정하고, generate()에서 CMakeToolchain을 생성해 CMake가 Conan 결과를 쓰게 합니다. build()에서 CMake(self).configure().build()를 호출해 실제 빌드를 수행합니다. 복잡한 옵션이나 조건부 의존성이 필요할 때 conanfile.py가 유리합니다. 다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 필요한 모듈 import
from conan import ConanFile
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
class MyProjectConan(ConanFile):
name = "myproject"
version = "1.0.0"
settings = "os", "compiler", "build_type", "arch"
def requirements(self):
self.requires("fmt/9.1.0")
self.requires("spdlog/1.11.0")
self.requires("boost/1.81.0")
def build_requirements(self):
self.test_requires("gtest/1.12.1")
def layout(self):
cmake_layout(self)
def generate(self):
tc = CMakeToolchain(self)
tc.generate()
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
옵션과 설정
options로 패키지별 선택 사항을 정의할 수 있습니다. shared는 동적/정적 라이브러리 선택, with_tests는 테스트 빌드 여부 같은 식으로 쓰입니다. default_options로 기본값을 두고, requirements() 안에서 if self.options.with_tests:처럼 분기해 test_requires를 조건부로 추가할 수 있습니다. conan install . -o with_tests=False처럼 명령줄에서 옵션을 오버라이드할 수 있어, CI에서는 테스트를 빼고 빌드하는 등 유연한 설정이 가능합니다. 다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
from conan import ConanFile
class MyProjectConan(ConanFile):
options = {
"shared": [True, False],
"with_tests": [True, False]
}
default_options = {
"shared": False,
"with_tests": True
}
def requirements(self):
self.requires("fmt/9.1.0")
if self.options.with_tests:
self.test_requires("gtest/1.12.1")
프로파일 커스터마이징
프로파일 파일에 [settings]로 OS, 아키텍처, 컴파일러, C++ 표준 라이브러리, 빌드 타입 등을 고정할 수 있습니다. ~/.conan2/profiles/ 아래에 gcc11 같은 이름으로 두고, conan install . —profile=gcc11로 사용합니다. [conf]에서 CMake 제너레이터를 Ninja로 바꾸는 등 도구 설정도 넣을 수 있어, 팀 표준 환경(예: Ubuntu 22.04 + GCC 11 + Release)을 프로파일 하나로 맞춰 두면 재현 가능한 빌드가 됩니다. 아래 코드는 ini를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# ~/.conan2/profiles/gcc11
[settings]
os=Linux
arch=x86_64
compiler=gcc
compiler.version=11
compiler.libcxx=libstdc++11
build_type=Release
[conf]
tools.cmake.cmaketoolchain:generator=Ninja
사용:
conan install . --profile=gcc11 --build=missing
6. Conan 완전 예제
프로젝트 구조
아래 코드는 text를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
myapp-conan/
├── CMakeLists.txt
├── conanfile.txt
├── src/
│ └── main.cpp
└── tests/
└── test_main.cpp
conanfile.txt
아래 코드는 ini를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
[requires]
fmt/9.1.0
spdlog/1.11.0
nlohmann_json/3.11.2
boost/1.81.0
[generators]
CMakeDeps
CMakeToolchain
[layout]
cmake_layout
CMakeLists.txt
다음은 cmake를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
cmake_minimum_required(VERSION 3.15)
project(MyAppConan LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
# conan install 후 생성된 toolchain 사용
find_package(fmt REQUIRED)
find_package(spdlog REQUIRED)
find_package(nlohmann_json REQUIRED)
find_package(Boost REQUIRED COMPONENTS system)
add_executable(myapp src/main.cpp)
target_link_libraries(myapp PRIVATE
fmt::fmt
spdlog::spdlog
nlohmann_json::nlohmann_json
Boost::system
)
src/main.cpp
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <iostream>
#include <fmt/core.h>
#include <spdlog/spdlog.h>
#include <nlohmann/json.hpp>
#include <boost/asio.hpp>
int main() {
spdlog::info("Conan 예제 시작");
std::cout << fmt::format("Hello, {}!\n", "Conan");
auto j = nlohmann::json::parse(R"({"name": "myapp", "version": 1})");
std::cout << "JSON: " << j.dump() << "\n";
boost::asio::io_context io;
boost::asio::steady_timer t(io, boost::asio::chrono::seconds(1));
t.async_wait( { spdlog::info("타이머 완료"); });
io.run();
return 0;
}
빌드 스크립트 (build.sh)
아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#!/bin/bash
set -e
# 1. Conan 의존성 설치
conan install . --output-folder=build --build=missing
# 2. CMake configure & build
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake
cmake --build build
echo "빌드 완료. 실행: ./build/myapp"
7. 비교와 선택
vcpkg vs Conan 상세 비교
다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
flowchart TB
subgraph vcpkg[vcpkg]
V1[Git 클론 설치]
V2[Manifest: vcpkg.json]
V3[트리플렛: x64-windows]
V4[CMake 자동 연동]
end
subgraph conan[Conan]
C1[pip install]
C2[conanfile.txt / .py]
C3[프로파일: compiler, build_type]
C4[conan install 선실행]
end
V2 --> V4
C2 --> C4 --> C4
| 특징 | vcpkg | Conan |
|---|---|---|
| 설치 | Git 클론 + bootstrap | pip install conan |
| 라이브러리 수 | 2000+ (Microsoft 포트) | 1500+ (Conan Center) |
| CMake 통합 | toolchain만 지정하면 자동 | conan install → toolchain |
| 버전 관리 | builtin-baseline, version>= | 명시적 버전 (fmt/9.1.0) |
| 빌드 설정 | 트리플렛 (x64-windows 등) | 프로파일 (compiler, build_type) |
| 학습 곡선 | 쉬움 | 중간 |
| 유연성 | 중간 | 높음 (Python 스크립트) |
| 바이너리 캐시 | vcpkg binary cache | Conan remote 캐시 |
| 크로스 컴파일 | 트리플렛으로 지원 | 프로파일로 지원 |
선택 가이드
vcpkg 추천:
- CMake 프로젝트
- 빠른 시작 원함
- Microsoft 생태계 (Visual Studio, Azure)
- 팀이 C++만 다룸 Conan 추천:
- 복잡한 의존성 관리 (조건부, 옵션)
- 세밀한 빌드 제어
- Python 친숙함
- 자체 패키지 배포 필요
8. 자주 발생하는 에러와 해결법
에러 1: “Could not find a package configuration file”
CMake Error at CMakeLists.txt:10 (find_package):
Could not find a package configuration file provided by "fmt"
원인: vcpkg/Conan toolchain을 CMake에 전달하지 않음. 또는 conan install을 하지 않음. 해결: 아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# vcpkg
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake
# Conan: conan install을 먼저 실행
conan install . --build=missing
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake
에러 2: “undefined reference to” 링크 에러
undefined reference to `fmt::v9::format(...)'
원인: find_package는 성공했지만 target_link_libraries에 누락. 또는 Debug/Release 불일치. 해결: 아래 코드는 cmake를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# ✅ 반드시 target_link_libraries에 추가
target_link_libraries(myapp PRIVATE fmt::fmt)
# vcpkg: 트리플렛 일치 확인 (x64-windows vs x64-windows-static)
# Conan: 프로파일 build_type=Release/Debug 일치
에러 3: “Version conflict” (Conan)
ERROR: Version conflict: fmt/10.0.0, fmt/9.1.0
원인: 여러 패키지가 서로 다른 fmt 버전을 요구. 해결: conanfile에서 동일 버전으로 통일. 또는 override로 강제: 아래 코드는 ini를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
[requires]
fmt/9.1.0
spdlog/1.11.0
[tool_requires]
# override는 conanfile.py에서 self.requires("fmt/9.1.0", override=True)
에러 4: vcpkg “Baseline must be a valid git commit”
Error: builtin-baseline must be a valid git commit
원인: builtin-baseline에 잘못된 날짜 또는 해시. 해결: vcpkg 저장소의 최신 커밋 해시 사용:
cd vcpkg
git log -1 --format=%H
{
"builtin-baseline": "a1c7f64b3" // 실제 해시로 교체
}
에러 5: “Package not found” (Conan)
ERROR: Package 'xyz/1.0' not found
원인: Conan Center에 해당 패키지가 없거나, 이름/버전 오타. 해결:
# 패키지 검색
conan search xyz -r conancenter
# vcpkg 패키지 이름과 다를 수 있음 (예: nlohmann-json vs nlohmann_json)
에러 6: “A suitable version of cmake was not found”
원인: Conan이 요구하는 CMake 버전이 시스템에 없음. 해결:
# conanfile.txt에 tool_requires 추가
[tool_requires]
cmake/3.25.0
9. 베스트 프랙티스
1. 의존성 파일을 버전 관리에 포함
vcpkg.json, conanfile.txt, conanfile.py는 반드시 Git에 커밋합니다. 팀원과 CI가 동일한 의존성으로 빌드할 수 있습니다.
2. 버전 고정
아래 코드는 json를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// vcpkg: builtin-baseline + version>=
{
"builtin-baseline": "a1c7f64",
"dependencies": [{ "name": "fmt", "version>=": "9.1.0" }]
}
; Conan: 명시적 버전
[requires]
fmt/9.1.0
3. 최소 의존성 원칙
필요한 컴포넌트만 요구합니다. Boost 전체가 아닌 boost-asio, boost-system 등 필요한 것만.
4. CI에서 캐시 활용
아래 코드는 yaml를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# GitHub Actions 예시 (vcpkg)
- uses: actions/cache@v4
with:
path: ${{ env.VCPKG_ROOT }}/installed
key: vcpkg-${{ runner.os }}-${{ hashFiles('vcpkg.json') }}
5. 로컬과 CI 환경 일치
동일한 트리플렛(vcpkg) 또는 프로파일(Conan)을 사용합니다. 로컬이 x64-windows면 CI도 x64-windows.
6. 빌드 스크립트로 순서 고정 (Conan)
다음은 간단한 bash 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# build.sh
conan install . --build=missing
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake
cmake --build build
10. 프로덕션 패턴
패턴 1: Monorepo + Manifest 모드
대규모 프로젝트에서 여러 서브프로젝트가 있을 때, 루트에 vcpkg.json 하나로 통합하거나, 각 서브디렉토리에 vcpkg.json을 두고 각자 의존성을 관리합니다. 아래 코드는 text를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
monorepo/
├── vcpkg.json # 공통 의존성
├── service-a/
│ ├── vcpkg.json # service-a 전용
│ └── CMakeLists.txt
└── service-b/
├── vcpkg.json
└── CMakeLists.txt
패턴 2: Docker로 빌드 환경 고정
아래 코드는 dockerfile를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# Dockerfile.build
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y cmake g++ git python3-pip
RUN git clone https://github.com/Microsoft/vcpkg.git /vcpkg && \
/vcpkg/bootstrap-vcpkg.sh
ENV VCPKG_ROOT=/vcpkg
WORKDIR /app
COPY . .
RUN cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake && \
cmake --build build
패턴 3: Binary Cache로 CI 속도 향상
vcpkg: --x-use-binary-cache 또는 Azure Artifacts 연동
vcpkg install fmt --x-binarysource=clear;default
Conan: remote 캐시 서버 구축 또는 Artifactory 사용
conan remote add mycache https://my-artifactory.com/conan
conan upload "*" -r mycache --all
패턴 4: 프로파일/트리플렛 팀 공유
프로파일 파일을 저장소에 포함해 팀 전체가 동일한 컴파일러·플래그를 사용합니다. 아래 코드는 text를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
conan/
├── profiles/
│ ├── linux-gcc11
│ ├── windows-msvc2022
│ └── macos-clang14
conan install . --profile=conan/profiles/linux-gcc11
패턴 5: 의존성 업데이트 워크플로우
- builtin-baseline (vcpkg) 또는 버전(Conan) 업데이트
- 로컬에서 빌드 테스트
- CI 통과 확인
- 커밋
실전 예제 요약
프로젝트 구조
아래 코드는 text를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
myproject/
├── CMakeLists.txt
├── vcpkg.json # vcpkg 사용 시
├── conanfile.txt # Conan 사용 시
├── src/
│ └── main.cpp
└── tests/
└── test_main.cpp
vcpkg.json
아래 코드는 json를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
{
"name": "myproject",
"version": "1.0.0",
"dependencies": [
"fmt",
"spdlog",
"nlohmann-json",
"gtest"
]
}
conanfile.txt
아래 코드는 ini를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
[requires]
fmt/9.1.0
spdlog/1.11.0
nlohmann_json/3.11.2
[test_requires]
gtest/1.12.1
[generators]
CMakeDeps
CMakeToolchain
[layout]
cmake_layout
CMakeLists.txt
다음은 cmake를 활용한 상세한 구현 코드입니다. 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
cmake_minimum_required(VERSION 3.15)
project(MyProject)
set(CMAKE_CXX_STANDARD 17)
find_package(fmt REQUIRED)
find_package(spdlog REQUIRED)
find_package(nlohmann_json REQUIRED)
add_executable(myapp src/main.cpp)
target_link_libraries(myapp PRIVATE
fmt::fmt
spdlog::spdlog
nlohmann_json::nlohmann_json
)
if(BUILD_TESTS)
find_package(GTest REQUIRED)
enable_testing()
add_executable(myapp_test tests/test_main.cpp)
target_link_libraries(myapp_test PRIVATE GTest::gtest_main)
add_test(NAME myapp_test COMMAND myapp_test)
endif()
구현 체크리스트
- vcpkg 또는 Conan 설치
- vcpkg.json 또는 conanfile.txt 작성
- builtin-baseline(vcpkg) 또는 명시적 버전(Conan) 설정
- CMake에 toolchain 파일 지정
- target_link_libraries에 모든 의존성 추가
- CI에서 동일한 toolchain/profile 사용
- 의존성 캐시 설정 (선택)
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- C++ CMake 고급 | 멀티 타겟·외부 라이브러리 관리 (대규모 프로젝트 빌드)
- CMake 입문 | 수십 개 파일 컴파일할 때 필요한 빌드 자동화 (CMakeLists.txt 기초)
- C++ 개발 환경 구축 | “C++ 어디서 시작하죠?” 컴파일러 설치부터 Hello World까지
이 글에서 다루는 키워드 (관련 검색어)
C++ 패키지 매니저, vcpkg, Conan, 의존성 관리, 라이브러리 설치 등으로 검색하시면 이 글이 도움이 됩니다.
정리
| 작업 | vcpkg | Conan |
|---|---|---|
| 설치 | vcpkg install fmt | conan install . |
| 의존성 파일 | vcpkg.json | conanfile.txt/py |
| CMake 통합 | toolchain 자동 | conan install → toolchain |
| 버전 고정 | Baseline + version>= | 명시적 버전 |
| 핵심 원칙: |
- 패키지 매니저 사용 필수
- 의존성 파일로 명시
- 버전 고정으로 재현성
- CI/CD 통합
- 프로젝트에 맞는 도구 선택
자주 묻는 질문 (FAQ)
Q. 이 내용을 실무에서 언제 쓰나요?
A. vcpkg와 Conan으로 C++ 라이브러리를 쉽게 설치하고, 프로젝트 의존성을 관리하며, 재현 가능한 빌드를 만드는 방법을 다룹니다. 실무에서는 위 본문의 예제와 선택 가이드를 참고해 적용하면 됩니다.
Q. 선행으로 읽으면 좋은 글은?
A. 각 글 하단의 이전 글 링크를 따라가면 순서대로 배울 수 있습니다. C++ 시리즈 목차에서 전체 흐름을 확인할 수 있습니다.