연습: STL 라이브러리를 헤더 단위로 가져오기
이 연습에서는 Visual Studio에서 헤더 단위로 C++ STL(표준 템플릿 라이브러리) 라이브러리를 가져오는 방법을 보여 줍니다. 표준 라이브러리를 가져오는 더욱 빠르고 강력한 방법에 대해 알아보려면 자습서: 모듈을 사용하여 C++ 표준 라이브러리 가져오기를 참조하세요.
STL 헤더를 헤더 단위로 가져오는 것은 미리 컴파일된 헤더 파일을 사용하는 것보다 단순합니다. 헤더 단위는 설정 및 사용이 더 쉽고 디스크에서 차지하는 공간이 훨씬 작으며 유사한 성능 이점을 제공하며 공유 PCH보다 더 유연합니다.
헤더 단위가 무엇이고 어떤 이점을 제공하는지에 대한 자세한 내용은 헤더 단위란?을 참조하세요. 표준 라이브러리를 가져오는 다른 방법과 헤더 단위를 비교하려면 헤더 단위, 모듈 및 미리 컴파일된 헤더 비교를 참조하세요.
필수 조건
헤더 단위를 사용하려면 Visual Studio 2022 이상 또는 Visual Studio 2019 버전 16.11 이상을 사용합니다. 헤더 단위를 사용하려면 /std:c++20
옵션(이상)이 필요합니다.
STL 헤더를 헤더 단위로 가져오는 두 가지 방법
STL 헤더를 가져오려면 먼저 헤더 단위로 컴파일해야 합니다. 헤더 단위는 헤더 파일의 이진 표현입니다. .ifc
확장자가 있습니다.
권장되는 방법은 사용하려는 STL 헤더에 대한 내장된 헤더 단위를 포함하는 정적 라이브러리를 만드는 것입니다. 그런 다음 해당 라이브러리와 import
헤더 단위를 참조합니다. 이 방법을 사용하면 빌드 속도가 빨라지고 다시 사용성이 향상됩니다. 이 방법을 시도하려면 방법 1: STL 라이브러리 헤더 단위의 정적 라이브러리 만들기를 참조하세요.
또 다른 방법은 프로젝트에서 #include
한 STL 헤더를 Visual Studio에서 검사하여 헤더 단위로 컴파일한 후 해당 헤더를 #include
하는 대신 import
하는 것입니다. 소스 코드를 변경할 필요가 없기 때문에 코드베이스가 큰 경우에 이러한 방법이 유용합니다. 이러한 방법은 정적 라이브러리 방법보다 유연성이 떨어지며, 다른 프로젝트에서 빌드된 헤더 단위를 재사용하는 데 적합하지 않습니다. 하지만, 개별 STL 라이브러리를 헤더 단위로 가져오면 성능상의 이점을 가져올 수 있습니다. 이 방법을 시도하려면 방법 2: 가져올 STL 헤더에 대한 include 검사를 참조하세요.
방법 1: STL 라이브러리 헤더 단위의 정적 라이브러리 만들기
STL 라이브러리를 헤더 단위로 사용하는 데 권장되는 방법은 하나 이상의 정적 라이브러리 프로젝트를 만드는 것입니다. 이러한 프로젝트는 사용하려는 STL 라이브러리 헤더 단위로 구성되어야 합니다. 그런 다음 라이브러리 프로젝트를 참조하여 STL 헤더 단위를 사용합니다. 공유 미리 컴파일된 헤더를 사용하는 것과 비슷하지만 더 쉽습니다.
정적 라이브러리 프로젝트에 기본 제공된 헤더 단위(및 모듈)는 참조 프로젝트에서 자동으로 사용할 수 있습니다. 이는 프로젝트 시스템이 컴파일러에 적절한 /headerUnit
명령줄 옵션을 자동으로 추가하여 참조 프로젝트가 헤더 단위를 가져올 수 있기 때문입니다.
이 방법은 특정 헤더의 헤더 단위가 한 번만 빌드되도록 보장합니다. PCH에서는 불가능한 일부 또는 모든 헤더 단위를 가져올 수 있습니다. 헤더 단위는 어떤 순서로든 포함할 수 있습니다.
다음 예에서는 <iostream>
및 <vector>
헤더 단위로 구성된 정적 라이브러리 프로젝트를 만듭니다. 솔루션이 빌드되면 다른 C++ 프로젝트에서 이 공유 헤더 단위 프로젝트를 참조합니다. import <iostream>;
또는 import <vector>;
가 발견되는 모든 곳에서는 헤더를 전처리기로 변환하는 대신 해당 라이브러리에 대해 빌드된 헤더 단위가 사용됩니다. 동일한 헤더가 여러 파일에 포함되면 PCH 파일과 마찬가지로 빌드 성능이 개선됩니다. 헤더를 포함하는 파일에서 헤더를 반복해서 처리할 필요가 없습니다. 대신 이미 처리된 컴파일된 헤더 단위가 가져옵니다.
STL 라이브러리 <iostream>
및 <vector>
를 포함하는 정적 라이브러리를 만들려면 다음 단계를 따릅니다.
빈 C++ 프로젝트를 만듭니다. 이름을 SharedPrj로 지정합니다.
새 프로젝트 만들기 창에서 사용 가능한 프로젝트 형식 중에서 C++의 경우 빈 프로젝트를 선택합니다.프로젝트에 새로운 C++ 파일을 추가합니다. 파일의 콘텐츠를 다음으로 변경합니다.
import <iostream>; import <vector>;
프로젝트 속성 설정
이 프로젝트의 헤더 단위를 공유하도록 프로젝트 속성을 설정합니다.
- Visual Studio 주 메뉴에서 프로젝트>SharedPrj 속성을 선택하여 프로젝트 속성 페이지 대화 상자를 엽니다.
- 구성 드롭다운 목록에서 모든 구성을 선택한 다음, 플랫폼 드롭다운 목록에서 모든 플랫폼을 선택합니다. 이러한 설정을 사용하면 디버그용이나 릴리스용으로 빌드하는 경우 변경 내용이 적용됩니다.
- 프로젝트 속성 페이지 대화 상자의 왼쪽 창에서 구성 속성>일반을 선택합니다.
- 구성 형식 옵션을 정적 라이브러리(.lib)로 변경합니다.
- C++ 언어 표준을 ISO C++20 표준(/std:c++20) 이상으로 변경합니다.
- 프로젝트 속성 페이지 대화 상자의 왼쪽 창에서 구성 속성>C/C++>일반을 선택합니다.
- 모듈 종속성에 대한 원본 검사 드롭다운 목록에서 예를 선택합니다. (이 옵션을 사용하면 컴파일러가 헤더 단위에 빌드할 수 있는 종속성에 대해 코드를 검사합니다.)
- 확인을 선택하여 프로젝트 속성 페이지 대화 상자를 닫습니다. 주 메뉴에서 빌드>솔루션 빌드를 선택하여 솔루션을 빌드합니다.
헤더 단위 라이브러리 참조
정적 라이브러리에서 <iostream>
및 <vector>
를 헤더 단위로 가져오려면 다음과 같이 정적 라이브러리를 참조하는 프로젝트를 만듭니다.
현재 솔루션이 열려 있는 상태로 Visual Studio 메뉴에서 파일>추가>새 프로젝트를 선택합니다.
새 프로젝트 만들기 마법사에서 C++ 콘솔 앱 템플릿을 선택하고 다음을 선택합니다.
새로운 프로젝트의 이름을 Walkthrough로 지정합니다. 솔루션 드롭다운을 솔루션에 추가로 변경합니다. 만들기를 선택하여 프로젝트를 만들고 솔루션에 추가합니다.
Walkthrough.cpp 원본 파일의 콘텐츠를 다음과 같이 변경합니다.
import <iostream>; import <vector>; int main() { std::vector<int> numbers = {0, 1, 2}; std::cout << numbers[1]; }
헤더 단위에는 /std:c++20
옵션(이상)이 필요합니다. 다음 단계에 따라 언어 표준을 설정합니다.
- 솔루션 탐색기에서 연습 프로젝트를 마우스 오른쪽 단추로 클릭하고 속성을 선택하여 프로젝트 속성 페이지 대화 상자를 엽니다.
- 연습 프로젝트 속성 페이지 대화 상자의 왼쪽 창에서 구성 속성>일반을 선택합니다.
- C++ 언어 표준 드롭다운에서 ISO C++20 표준(/std:c++20)(이상)을 선택합니다.
- 확인을 선택하여 프로젝트 속성 페이지 대화 상자를 닫습니다.
Walkthrough 프로젝트에서 다음 단계에 따라 SharedPrj 프로젝트에 대한 참조를 추가합니다.
- Walkthrough 프로젝트에서 참조 노드를 선택하고 참조 추가를 선택합니다. 프로젝트 목록에서 SharedPrj를 선택합니다. 이 참조를 추가하면 빌드 시스템에서 Walkthrough 프로젝트의
import
가 SharedPrj에 있는 빌드된 헤더 단위 중 하나와 일치할 때마다 SharedPrj에 의해 빌드된 헤더 단위를 사용하게 됩니다. - 확인을 선택하여 참조 추가 대화 상자를 닫습니다.
- Walkthrough 프로젝트를 마우스 오른쪽 단추로 클릭하고 시작 프로젝트로 설정을 선택합니다.
- 솔루션을 빌드합니다. (메인 메뉴에서 빌드>솔루션 빌드를 사용합니다.) 예상한 출력이 생성되는지 확인하려면 실행합니다.
1
이 방법은 프로젝트에서 정적 라이브러리 프로젝트를 참조하여 헤더 단위를 다시 사용할 수 있다는 장점이 있습니다. 이 예에서 정적 라이브러리에는 <vector>
및 <iostream>
헤더 단위가 포함되어 있습니다.
다양한 프로젝트에서 가져오려는 일반적으로 사용되는 STL 헤더를 모두 포함하는 모놀리식 정적 라이브러리 프로젝트를 만들 수 있습니다. 또는 헤더 단위로 가져오려는 STL 라이브러리의 다양한 그룹에 대해 더 작은 공유 라이브러리 프로젝트를 만들 수 있습니다. 그런 다음, 필요에 따라 해당 공유 헤더 단위 프로젝트를 참조합니다.
헤더 단위를 가져오면 컴파일러가 수행해야 하는 작업이 현저하게 줄어들기 때문에 빌드 처리량이 증가하게 됩니다.
자신의 프로젝트에서 이 방법을 사용하는 경우, 참조할 프로젝트와 호환되는 컴파일러 옵션을 사용하여 정적 라이브러리 프로젝트를 빌드합니다. 예를 들어 예외 처리를 켜서 정적 라이브러리 프로젝트를 참조하는 프로젝트가 되도록 하려면 /EHsc
컴파일러 옵션으로 STL 프로젝트를 빌드해야 합니다.
/translateInclude
사용
/translateInclude
컴파일러 옵션(프로젝트 속성 페이지 대화 상자의 C/C++>일반>include 지시문을 import 지시문으로 변환에서 사용 가능)을 사용하면 STL 라이브러리를 #include
하는 이전 프로젝트에서 헤더 단위 라이브러리를 사용하기가 더 쉬워집니다. 이렇게 하면 프로젝트에서 #include
지침을 import
로 변경할 필요가 없어지고 헤더 단위를 포함하는 대신 가져오는 이점도 얻을 수 있습니다.
예를 들어, 프로젝트에 #include <vector>
가 있고 <vector>
에 대한 헤더 단위가 포함된 정적 라이브러리를 참조하는 경우 소스 코드에서 #include <vector>
를 import <vector>;
로 수동으로 변경할 필요가 없습니다. 대신 컴파일러는 자동으로 #include <vector>
를 import <vector>;
로 처리합니다. 이 방법에 대한 자세한 내용은 방법 2: 가져올 STL 헤더에 대한 include 검사를 참조하세요. 모든 STL 헤더 파일을 헤더 단위로 컴파일할 수 있는 것은 아닙니다. Visual Studio와 함께 제공되는 header-units.json
은 어떤 STL 헤더 파일을 헤더 단위로 컴파일할 수 있는지 나열합니다. 동작을 지정하기 위해 매크로에 의존하는 헤더는 종종 헤더 단위로 컴파일할 수 없습니다.
헤더 단위를 참조하지 않는 #include
문은 일반 #include
로 처리됩니다.
프로젝트 간 헤더 단위 다시 사용
정적 라이브러리 프로젝트에서 빌드된 헤더 단위는 직접적으로 및 간접적으로 참조하는 모든 프로젝트에서 자동으로 사용할 수 있습니다. 모든 참조하는 프로젝트에서 자동으로 사용할 수 있는 헤더 단위를 선택할 수 있는 프로젝트 설정이 있습니다. 해당 설정은 프로젝트 설정의 VC++ 디렉터리에 있습니다.
- 솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 속성을 선택하여 프로젝트 속성 페이지 대화 상자를 엽니다.
- 대화 상자의 왼쪽 창에서 구성 속성>VC++ 디렉터리를 선택합니다.
다음 속성은 빌드 시스템에서 헤더 단위의 표시 여부를 제어합니다.
- 공용 포함 디렉터리: 참조하는 프로젝터의 포함 경로에 자동으로 추가되어야 하는 헤더 단위에 대한 프로젝트 디렉터리를 지정합니다.
- 퍼블릭 C++ 모듈 디렉터리: 참조하는 프로젝트에서 사용할 수 있어야 하는 헤더 단위를 포함하는 프로젝트 디렉터리를 지정합니다. 이 속성을 사용하면 일부 헤더 단위를 공개할 수 있습니다. 다른 프로젝트에서도 볼 수 있으므로, 공유하려는 헤더 단위를 여기에 넣으세요. 편의상 이 설정을 사용하는 경우 공용 포함 디렉터리를 지정하여 참조 프로젝트의 포함 경로에 공용 헤더를 자동으로 추가합니다.
- 모든 모듈이 퍼블릭임 - DLL 프로젝트의 일부로 빌드된 헤더 단위를 사용할 때 DLL에서 기호를 내보내야 합니다. 모듈 기호를 자동으로 내보내려면 이 속성을 예로 설정합니다.
미리 빌드된 모듈 파일 사용
일반적으로 솔루션 간에 헤더 단위를 다시 사용하는 가장 쉬운 방법은 각 솔루션에서 공유 헤더 단위 프로젝트를 참조하는 것입니다.
프로젝트가 없는 빌드된 헤더 단위를 사용해야 하는 경우 빌드된 .ifc
파일이 있는 위치를 지정하여 솔루션에서 가져올 수 있습니다. 이 설정에 액세스하려면
- 주 메뉴에서 프로젝트>속성을 선택하여 프로젝트 속성 페이지 대화 상자를 엽니다.
- 대화 상자의 왼쪽 창에서 구성 속성>C/C++>일반을 선택합니다.
- 추가 모듈 종속성에서 참조할 모듈을 세미콜론으로 구분하여 추가합니다. 추가 모듈 종속성에 사용할 형식의 예는 다음과 같습니다.
ModuleName1=Path\To\ModuleName1.ifc; ModuleName2=Path\To\ModuleName2.ifc
여러 헤더 단위의 복사본 중에서 선택
같은 이름이나 같은 헤더 파일을 사용하여 여러 헤더 단위를 빌드하는 프로젝트를 참조하는 경우 어떤 헤더 단위를 사용할지 지정해야 합니다. 예를 들어, 서로 다른 컴파일러 설정으로 빌드된 여러 버전의 헤더 단위가 있을 수 있으며, 프로젝트 설정과 일치하는 헤더 단위를 지정해야 합니다.
프로젝트의 추가 헤더 단위 종속성 속성을 사용하여 사용할 헤더 단위를 지정하여 충돌을 해결합니다. 그렇지 않으면 어느 것이 선택될지 예측할 수 없습니다.
추가 헤더 단위 종속성 속성을 설정하려면:
- 주 메뉴에서 프로젝트>속성을 선택하여 프로젝트 속성 페이지 대화 상자를 엽니다.
- 대화 상자의 왼쪽 창에서 구성 속성>C/C++>일반을 선택합니다.
- 충돌을 해결하기 위해 추가 헤더 단위 종속성에서 사용할 모듈이나 헤더 단위 파일을 지정합니다. 추가 헤더 단위 종속성에 대해 이 형식을 사용합니다.
Path\To\Header1.h= Path\To\HeaderUnit1.ifc;Path\To\Header2.h= Path\To\ HeaderUnit2.ifc
Important
헤더 단위를 공유하는 프로젝트가 호환되는 컴파일 옵션으로 빌드되었는지 확인합니다. 만들 때 사용한 것과 다른 헤더 단위를 구현할 때 컴파일 옵션을 사용하면 컴파일러가 경고를 표시합니다.
참고 항목
DLL 프로젝트의 일부로 빌드된 헤더 단위를 사용하려면 모든 모듈이 퍼블릭임을 예로 설정합니다.
방법 2: 가져올 STL 헤더에 대한 include 검사
STL 라이브러리를 가져오는 또 다른 방법은 Visual Studio에서 프로젝트에서 #include
한 STL 헤더를 검사하여 헤더 단위로 컴파일하는 것입니다. 그런 다음 컴파일러는 해당 헤더를 포함하는 대신 가져옵니다.
이 옵션은 프로젝트에 여러 파일에 걸쳐 많은 STL 헤더 파일이 포함되어 있거나 빌드 처리량이 중요하지 않을 때 편리합니다. 이 옵션은 특정 헤더 파일의 헤더 단위가 한 번만 빌드된다는 것을 보장하지 않습니다. 하지만 코드베이스가 큰 경우에는 유용합니다. 사용하는 많은 STL 라이브러리의 헤더 단위의 이점을 활용하기 위해 소스 코드를 변경할 필요가 없습니다.
이러한 방법은 정적 라이브러리 방법보다 유연성이 떨어지며, 다른 프로젝트에서 빌드된 헤더 단위를 재사용하는 데 적합하지 않습니다. 이러한 방법은 대규모 프로젝트에는 적절하지 않을 수 있습니다. 모든 원본을 검사하여 #include
문을 찾아야 하기 때문에 최적의 빌드 시간을 보장하지 않기 때문입니다.
일부 헤더 파일은 자동으로 헤더 단위로 변환되지 않을 수 있습니다. 예를 들어, 매크로를 통한 조건부 컴파일에 의존하는 헤더는 헤더 단위로 변환되어서는 안 됩니다. /translateInclude
가 지정되면 컴파일러가 사용하는 STL 헤더에 대한 header-units.json
파일 형식의 허용 목록이 있습니다. 어떤 STL 헤더가 헤더 단위로 컴파일될 수 있는지 결정합니다. header-units.json
파일은 Visual Studio 설치 디렉터리에 있습니다. 예들 들어 %ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.30.30705\include\header-units.json
입니다. STL 헤더 파일이 목록에 없으면 헤더 단위로 가져오는 대신 일반 #include
로 처리됩니다. header-units.json
파일의 또 다른 장점은 빌드된 헤더 단위에서 기호 중복을 방지한다는 것입니다. 즉, 헤더 단위를 컴파일할 때 다른 라이브러리 헤더를 여러 번 가져오는 경우 기호는 복제되지 않습니다.
이 방법을 시도해 보려면 두 개의 STL 라이브러리를 포함하는 프로젝트를 만듭니다. 그런 다음, 다음 섹션에 설명된 대로 라이브러리를 포함하는 대신 헤더 단위로 가져오도록 프로젝트 속성을 변경합니다.
C++ 콘솔 앱 프로젝트 만들기
<iostream>
및 <vector>
라는 두 개의 STL 라이브러리를 포함하는 프로젝트를 만들려면 다음 단계를 따릅니다.
Visual Studio에서 새 C++ 콘솔 앱 프로젝트를 만듭니다.
원본 파일의 콘텐츠를 다음과 같이 바꿉니다.
#include <iostream>; #include <vector>; int main() { std::vector<int> numbers = {0, 1, 2}; std::cout << numbers[1]; }
프로젝트 옵션을 설정하고 프로젝트를 실행합니다.
다음 단계에서는 컴파일러가 포함된 헤더를 검사하여 헤더 단위로 변환하도록 하는 옵션을 설정합니다. 또한 헤더 단위로 처리할 수 있는 헤더 파일에 대해 import
를 작성한 것처럼 컴파일러가 #include
를 처리하도록 하는 옵션도 설정합니다.
- 주 메뉴에서 프로젝트>속성을 선택하여 프로젝트 속성 페이지 대화 상자를 엽니다.
- 구성 드롭다운 목록에서 모든 구성을 선택한 다음, 플랫폼 드롭다운 목록에서 모든 플랫폼을 선택합니다. 이러한 설정을 사용하면 디버그나 릴리스 및 기타 구성에 관계없이 변경 내용이 적용됩니다.
- 대화 상자의 왼쪽 창에서 구성 속성>C/C++>일반을 선택합니다.
- Scan Sources for Module Dependencies(소스의 모듈 종속성 검색)를 예로 설정합니다. 이 설정은 모든 호환 헤더 파일이 헤더 단위로 컴파일되도록 보장합니다.
- include 지시문을 import 지시문으로 변환을 예로 설정합니다. 이 설정은
header-unit.json
파일에 나열된 STL 헤더 파일을 헤더 단위로 컴파일한 다음, 전처리기를 사용하여#include
하는 대신 이를 가져옵니다. - 확인을 선택하여 변경 내용을 저장하고 프로젝트 속성 페이지 대화 상자를 닫습니다.
헤더 단위를 사용하려면 /std:c++20
옵션 이상이 필요합니다. 컴파일러에서 사용하는 C++ 언어 표준을 변경하려면:
- 주 메뉴에서 프로젝트>속성을 선택하여 프로젝트 속성 페이지 대화 상자를 엽니다.
- 구성 드롭다운 목록에서 모든 구성을 선택한 다음, 플랫폼 드롭다운 목록에서 모든 플랫폼을 선택합니다. 이러한 설정을 사용하면 디버그나 릴리스 및 기타 구성에 관계없이 변경 내용이 적용됩니다.
- 프로젝트 속성 페이지 대화 상자의 왼쪽 창에서 구성 속성>일반을 선택합니다.
- C++ 언어 표준 드롭다운 목록에서 ISO C++20 표준(/std:c++20)(이상)을 선택합니다.
- 확인을 선택하여 변경 내용을 저장하고 프로젝트 속성 페이지 대화 상자를 닫습니다.
- 주 메뉴에서 빌드>솔루션 빌드를 선택하여 솔루션을 빌드합니다.
예상 출력이 생성되는지 확인하려면 솔루션을 실행합니다. 1
이 방법을 사용할지 여부에 대한 주요 고려 사항은 편의성과 모든 파일을 검사하여 헤더 단위로 빌드할 헤더 파일을 결정하는 비용 간의 균형입니다.
참고 항목
헤더 단위, 모듈 및 미리 컴파일된 헤더 비교
자습서: 모듈을 사용하여 C++ 표준 라이브러리 가져오기
연습: Visual C++ 프로젝트에서 헤더 단위 빌드 및 가져오기
/translateInclude