개발 환경 설정
편집기와 컴파일러, 링커, 디버거가 각각 맡는 일을 나누어 보고, Windows에서는 MSYS2의 GCC와 VS Code로, macOS와 Linux에서는 시스템의 컴파일러로 C++20 개발 환경을 갖춘 뒤, 첫 프로그램을 빌드하고 실행해 그 연결을 확인합니다.
C++ 코드를 실행하려면 코드를 쓰는 도구와, 그 코드를 기계가 실행할 수 있는 파일로 바꾸는 도구가 함께 있어야 합니다. 편집기에 코드를 쓰는 것만으로는 아무것도 실행되지 않으며, 컴파일러가 소스를 번역하고 링커가 그 결과를 묶어야 실행 파일이 생깁니다.
이 글은 그 도구들이 각각 무엇을 하는지 나눈 뒤, Windows에서 VS Code와 MSYS2의 GCC로 개발 환경을 갖추고 macOS와 Linux의 설치 방법도 정리합니다. 마지막으로 첫 프로그램을 빌드하고 실행해, 저장한 소스가 실행 파일이 되는 길을 직접 확인합니다.
g++가 C++ 소스를 실행 파일로 만드는 단계
main.cpp의 전처리·목적 코드·링크 산출물을 거쳐 별도 PowerShell 실행으로 넘어가므로 현재 산출물과 빌드/실행 경계를 단계별로 확인할 수 있다.
C++ · BUILD AND EXECUTION
g++는 빌드를 조정하고 실행은 별도로 시작한다
한 번의 g++ 명령 안에서도 번역과 링크는 구별됩니다. 실행은 빌드 성공 뒤 운영체제에서 시작합니다.
- 전처리
#include와 매크로를 처리해 컴파일할 번역 단위를 준비합니다. - 컴파일과 어셈블
C++를 목적 코드로 바꿉니다.
-c를 쓰면 링크하지 않고 목적 파일에서 멈출 수 있습니다. - 링크
목적 코드와 필요한 C++ 라이브러리를 연결해
hello.exe를 만듭니다. - 실행
PowerShell의
.\hello.exe가 빌드 결과를 시작하고 Windows가 프로그램을 적재합니다.
빌드와 실행 명령
g++ -std=c++20 main.cpp -o hello.exe
.\hello.exe첫 줄은 빌드, 둘째 줄은 PowerShell에서의 실행입니다. 편집기나 C/C++ 확장과 별도로 컴파일러 툴체인이 필요합니다.
g++ main.cpp -o hello.exe처럼 한 번에 링크하면 목적 파일이 별도 파일로 남지 않을 수 있지만, 번역과 링크의 책임은 여전히 구분됩니다.
이 예의 조건
- 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
- 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.
| 관찰·상황 | 값·보충 정보 | 변화·이유 |
|---|---|---|
| 소스 준비 실행 전에 소스를 빌드 입력으로 둔다. |
|
|
| 빌드 산출물 전처리·컴파일·링크로 실행 파일을 만든다. |
|
|
| 실행 시작 PowerShell에서 만들어진 파일을 실행한다. |
|
|
g++가 C++ 소스를 실행 파일로 만드는 단계
main.cpp의 전처리·목적 코드·링크 산출물을 거쳐 별도 PowerShell 실행으로 넘어가므로 현재 산출물과 빌드/실행 경계를 단계별로 확인할 수 있다.
C++ · BUILD AND EXECUTION
g++는 빌드를 조정하고 실행은 별도로 시작한다
한 번의 g++ 명령 안에서도 번역과 링크는 구별됩니다. 실행은 빌드 성공 뒤 운영체제에서 시작합니다.
- 전처리
#include와 매크로를 처리해 컴파일할 번역 단위를 준비합니다. - 컴파일과 어셈블
C++를 목적 코드로 바꿉니다.
-c를 쓰면 링크하지 않고 목적 파일에서 멈출 수 있습니다. - 링크
목적 코드와 필요한 C++ 라이브러리를 연결해
hello.exe를 만듭니다. - 실행
PowerShell의
.\hello.exe가 빌드 결과를 시작하고 Windows가 프로그램을 적재합니다.
빌드와 실행 명령
g++ -std=c++20 main.cpp -o hello.exe
.\hello.exe첫 줄은 빌드, 둘째 줄은 PowerShell에서의 실행입니다. 편집기나 C/C++ 확장과 별도로 컴파일러 툴체인이 필요합니다.
g++ main.cpp -o hello.exe처럼 한 번에 링크하면 목적 파일이 별도 파일로 남지 않을 수 있지만, 번역과 링크의 책임은 여전히 구분됩니다.
이 예의 조건
- 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
- 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.
| 관찰·상황 | 값·보충 정보 | 변화·이유 |
|---|---|---|
| 소스 준비 실행 전에 소스를 빌드 입력으로 둔다. |
|
|
| 빌드 산출물 전처리·컴파일·링크로 실행 파일을 만든다. |
|
|
| 실행 시작 PowerShell에서 만들어진 파일을 실행한다. |
|
|
개발에 필요한 도구
그림처럼 g++ 명령 하나가 여러 도구를 차례로 부릅니다. 먼저 전처리기가 #include와 매크로를 처리하고, 컴파일러와 어셈블러가 C++ 코드를 기계어로 된 목적 코드(object code)로 바꾸며, 링커(linker)가 목적 코드와 표준 라이브러리를 묶어 실행 파일을 만듭니다. 이렇게 빌드에 쓰는 도구를 묶어 툴체인(toolchain)이라고 부르며, g++처럼 이 단계들을 대신 불러 주는 명령을 컴파일러 드라이버(compiler driver)라고 합니다.
실행은 빌드와 별개입니다. 빌드가 성공해 실행 파일이 생긴 뒤, 그 파일을 실행하면 운영체제가 프로그램을 메모리에 올려 시작합니다. 실행 중의 프로그램을 멈추고 변수의 값과 함수의 호출 순서를 보는 도구는 디버거(debugger)이며, GCC와 함께 쓰는 디버거는 GDB입니다.
편집기는 이 도구들과 따로 있습니다. VS Code 같은 편집기나 Visual Studio 같은 통합 개발 환경(IDE)은 컴파일러를 불러 주고 그 결과를 화면에 보여 주지만, Visual Studio처럼 컴파일러를 함께 설치하는 제품도 있고 VS Code처럼 컴파일러를 따로 설치해야 하는 제품도 있습니다.
주요 컴파일러
C++ 컴파일러로 널리 쓰이는 것은 세 가지입니다.
| 컴파일러 | 드라이버 명령 | 주로 쓰이는 곳 |
|---|---|---|
| GCC | g++ | Linux의 기본 컴파일러이며, Windows에서는 MSYS2 같은 배포판으로 씁니다. |
| Clang | clang++ | macOS의 기본 컴파일러이며, Linux와 Windows에서도 씁니다. |
| MSVC | cl | Windows용 Visual Studio와 Build Tools에 들어 있습니다. |
세 컴파일러 모두 C++20의 대부분을 지원하지만, 기능마다 지원하기 시작한 버전이 다르고 오류 메시지의 모양도 다릅니다. 이 교재의 명령은 GCC를 기준으로 하며, 어떤 기능을 어느 버전부터 지원하는지는 cppreference의 컴파일러 지원표에서 확인합니다.
Windows에서 환경 갖추기
Windows에서는 VS Code와, MSYS2가 제공하는 GCC 툴체인을 씁니다. 이 설정은 x86_64 PC의 64비트 Windows 10 1809 이상이나 Windows 11에서 MSYS2의 UCRT64 환경을 쓰는 경우를 기준으로 하며, ARM64 Windows는 MSYS2의 ARM64 안내를 따릅니다.
먼저 VS Code 공식 사이트에서 설치 프로그램을 내려받아 설치합니다.

VS Code의 확장(Extensions) 보기에서 C/C++을 검색해 Microsoft의 ms-vscode.cpptools 확장을 설치합니다. 이 확장은 자동 완성과 오류 표시, 디버깅 기능을 제공하지만, 컴파일러를 설치해 주지는 않습니다.

다음으로 MSYS2 공식 설치 페이지에서 최신 설치 프로그램을 내려받아 설치하고, 시작 메뉴에서 MSYS2 UCRT64 터미널을 열어 툴체인을 설치합니다.
pacman -S --needed base-devel mingw-w64-ucrt-x86_64-toolchain
Enter a selection (default=all)이라고 물으면 Enter를 눌러 그룹 전체를 고르고, 설치할 패키지의 요약 뒤에 Proceed with installation? [Y/n]이라고 물으면 Enter나 Y를 눌러 진행합니다. 패키지의 개수와 버전은 그때그때 바뀌므로, 화면의 숫자가 아래 그림과 달라도 괜찮습니다.

설치가 끝나면 Windows의 사용자 환경 변수 Path에 UCRT64의 bin 폴더를 더해, 어느 터미널에서든 g++를 찾을 수 있게 합니다. 기본 경로로 설치했다면 그 폴더는 다음과 같습니다.
C:\msys64\ucrt64\bin열려 있던 터미널을 모두 닫고 새 터미널에서 다음 명령으로 설치를 확인합니다. 세 명령이 모두 버전을 출력하면 컴파일러와 디버거를 찾은 것입니다.
gcc --version
g++ --version
gdb --version다른 폴더에 설치했다면 이 경로와, 아래 설정 파일들의 C:\msys64나 C:/msys64를 모두 실제 설치 경로로 바꿉니다.
macOS와 Linux에서 환경 갖추기
macOS에서는 터미널에서 xcode-select --install을 실행해 Command Line Tools를 설치하면 Apple의 Clang과 링커가 설치되고, g++라는 이름도 그 Clang을 가리킵니다. 디버거는 GDB 대신 LLDB를 쓰며, VS Code에서는 C/C++ 확장의 lldb 설정이나 CodeLLDB 확장으로 디버깅합니다.
Ubuntu와 Debian 계열의 Linux에서는 sudo apt install build-essential gdb로 GCC와 GDB를 설치합니다. 다른 배포판은 그 배포판의 패키지 관리자로 GCC나 Clang을 설치하며, 어느 경우든 g++ --version으로 설치를 확인합니다. 아래 VS Code 설정은 Windows의 경로를 쓰므로, macOS와 Linux에서는 컴파일러와 디버거의 경로를 /usr/bin/g++처럼 그 시스템의 경로로 바꾸고 실행 파일의 확장자 .exe를 뺍니다.
VS Code 설정 파일
프로젝트로 쓸 새 폴더를 만들어 VS Code로 열고, 그 안에 .vscode 폴더를 만들어 세 설정 파일을 둡니다. 아래 설정은 편집기에서 열려 있는 소스 파일 하나를 같은 폴더에 같은 이름의 .exe로 빌드하고 디버깅합니다.
{
"configurations": [
{
"name": "GCC",
"includePath": ["${workspaceFolder}/**"],
"compilerPath": "C:/msys64/ucrt64/bin/g++.exe",
"cStandard": "c17",
"cppStandard": "c++20",
"intelliSenseMode": "windows-gcc-x64"
}
],
"version": 4
}{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++.exe 활성 파일 빌드",
"command": "C:\\msys64\\ucrt64\\bin\\g++.exe",
"args": [
"-fdiagnostics-color=always",
"-std=c++20",
"-Wall",
"-Wextra",
"-g",
"${file}",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": ["$gcc"],
"group": {
"kind": "build",
"isDefault": true
}
}
],
"version": "2.0.0"
}{
"configurations": [
{
"name": "C/C++: g++.exe 활성 파일 빌드 및 디버그",
"type": "cppdbg",
"request": "launch",
"program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "C:/msys64/ucrt64/bin/gdb.exe",
"setupCommands": [
{
"description": "gdb에 자동 서식 지정 사용",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "C/C++: g++.exe 활성 파일 빌드"
}
],
"version": "0.2.0"
}tasks.json이 실제로 빌드하는 명령을 정하며, -std=c++20은 C++20 표준으로 컴파일하라는 옵션이고, -Wall과 -Wextra는 실수일 가능성이 높은 코드에 경고를 더 많이 내게 하며, -g는 디버거가 쓸 정보를 실행 파일에 넣습니다. c_cpp_properties.json은 편집기의 자동 완성과 오류 표시가 참고할 컴파일러와 표준을 정할 뿐 실제 빌드에는 쓰이지 않고, launch.json은 빌드한 실행 파일을 GDB로 시작합니다. 세 파일의 version은 각 설정 파일 형식의 버전이어서 서로 값이 다릅니다.
C++ · BUILD AND EXECUTION
편집·빌드·디버그 설정은 연결 값을 맞춘다
세 JSON 파일의 책임을 나누고, 툴체인·표준·실행 파일·작업 이름을 짝으로 대조합니다.
| 파일 | 결정하는 것 | 일치시킬 값 |
|---|---|---|
c_cpp_properties.json |
IntelliSense가 참고할 컴파일러, include 경로, C++ 표준 | compilerPath와 cppStandard를 실제 빌드 조건에 맞춤 |
tasks.json |
g++에 전달할 소스·옵션·출력 경로 |
command는 같은 툴체인, 출력 경로는 디버그 대상과 같아야 함 |
launch.json |
GDB가 시작할 프로그램과 작업 폴더 | program은 빌드 출력, preLaunchTask는 task의 label과 정확히 일치 |
c_cpp_properties.json- 책임 IntelliSense의 컴파일러·include 경로·C++ 표준
- 계약
compilerPath와cppStandard를 실제 빌드 조건에 맞춥니다. tasks.json- 책임 실제
g++명령, 소스, 옵션, 출력 경로 - 계약
command는 같은 툴체인을 사용하고, 출력 실행 파일은launch.json의program과 같아야 합니다. launch.json- 책임 GDB로 시작할 프로그램과 작업 폴더
- 계약
program은 빌드 출력이고,preLaunchTask는 task의label과 정확히 같아야 합니다.
실제 값을 대조할 네 쌍
compilerPath ↔ task의 command
cppStandard ↔ 빌드의 -std
빌드의 -o ↔ debug의 program
task의 label ↔ preLaunchTask
includePath는 편집 지원의 검색 경로입니다. 실제 컴파일에 필요한 외부 헤더 경로는 빌드의 -I 인수에도 반영합니다.
IntelliSense가 정상이어도 빌드 명령은 실패할 수 있습니다. 편집 지원과 실제 빌드는 서로 다른 설정 경로입니다.
그림처럼 세 파일은 맡은 일이 다르므로, 서로 이어지는 값을 짝으로 맞춰야 합니다. compilerPath와 빌드 작업의 command는 같은 컴파일러를, cppStandard와 -std는 같은 표준을, 빌드의 -o 출력과 디버거의 program은 같은 파일을, 빌드 작업의 label과 디버거의 preLaunchTask는 같은 이름을 가리켜야 합니다. includePath도 편집기의 검색 범위일 뿐이어서, 다른 폴더의 헤더를 쓴다면 빌드 명령에도 -I 옵션으로 그 폴더를 알려야 합니다.
VS Code의 MinGW 안내는 작업 폴더의 .cpp 파일을 모두 빌드하려면 args의 "${file}"을 "${workspaceFolder}/*.cpp"로 바꾸라고 안내합니다. MSYS2는 2024년 11월부터 mingw-w64로 만든 프로그램이 와일드카드를 스스로 펼치지 않도록 바꾸었지만, g++ 같은 GCC 드라이버는 그 뒤 다시 와일드카드를 펼치도록 바뀌어 이 설정이 동작합니다. 다만 이 교재의 예제는 대부분 main이 있는 파일 하나짜리여서, 한 폴더에 둔 여러 예제를 모두 함께 빌드하면 main이 겹쳐 링크 오류가 납니다. 그래서 위 설정은 열려 있는 파일 하나만 빌드하며, 와일드카드를 펼치지 않는 도구를 쓴다면 소스를 하나씩 적거나 CMake 같은 빌드 시스템을 씁니다.
첫 프로그램 빌드와 실행
폴더에 main.cpp를 만들어 다음 코드를 저장합니다. 화면에 Hello, C++ World! 한 줄을 출력하고 끝나는 작은 프로그램이며, 여기서는 코드의 뜻보다 앞에서 설치한 컴파일러로 빌드와 실행이 되는지를 확인하는 데 씁니다. 각 줄이 하는 일은 다음 글에서 하나씩 읽습니다.
#include <iostream>
int main() {
std::cout << "Hello, C++ World!" << std::endl;
return 0;
}VS Code의 터미널에서 같은 폴더로 이동해 빌드하고 실행합니다. Windows의 PowerShell이라면 다음과 같습니다.
g++ -std=c++20 -Wall -Wextra -g main.cpp -o hello.exe
.\hello.exeHello, C++ World!빌드가 성공하면 아무것도 출력하지 않고 hello.exe가 생기며, 실행하면 인사말 한 줄이 출력됩니다. 빌드가 실패하면 진단을 먼저 읽고, 실행은 고친 뒤로 미룹니다. 예전에 만든 hello.exe가 남아 있으면 이번 빌드가 실패해도 옛 파일이 실행되어, 고친 코드가 반영되었다고 착각할 수 있기 때문입니다. PowerShell에서는 빌드 직후 $LASTEXITCODE가 0인지로 빌드의 성공을 확인할 수 있습니다.
인사말을 다른 문장으로 바꿔 저장한 뒤 다시 빌드하고 실행해 봅니다. 바뀐 문장이 나오면 저장한 소스가 새 실행 파일이 되고 그 파일이 실행되는 길이 이어진 것이고, 옛 문장이 나오면 저장 여부와 빌드한 파일, 실행한 파일의 경로를 차례로 확인합니다.
C++ · BUILD AND EXECUTION
첫 오류가 발생한 단계부터 원인을 좁힌다
설치·전처리/컴파일·링크·실행 시작·실행 중을 나누면 수정할 파일과 설정을 찾기 쉽습니다.
| 보이는 증상 | 멈춘 단계 | 먼저 확인할 것 |
|---|---|---|
g++ 또는 gdb를 찾을 수 없음 |
설치 · Path | 새 터미널에서 버전 명령을 실행하고 C:\msys64\ucrt64\bin을 확인 |
error: expected ... 또는 header를 찾지 못함 |
전처리 · 컴파일 | 첫 진단에 따라 저장된 파일의 문법 또는 #include 이름·검색 경로를 확인 |
undefined reference 또는 cannot find -l... |
링크 | 함수 정의가 든 목적 파일, 라이브러리 이름·경로·명령 인수 순서를 확인 |
| 빌드됐지만 실행 파일을 찾지 못함 | 실행 시작 | tasks.json의 -o와 launch.json의 program을 대조 |
| 실행되지만 출력이나 동작이 예상과 다름 | 실행 중 | 현재 작업 폴더, 입력값, 중단점과 변수 값을 확인 |
- 명령을 찾을 수 없음
- 단계 설치 · Path
- 확인 새 터미널에서
g++ --version과gdb --version을 실행합니다. 기본 설치 경로는C:\msys64\ucrt64\bin이며, 실제 설치 위치와 Path를 대조합니다. - 컴파일 · header 진단
- 단계 전처리 · 컴파일
- 확인 첫 진단에 따라 문법 또는
#include이름·검색 경로를 봅니다. - 링크 진단
- 단계 링크
- 증상
undefined reference,cannot find -l... - 확인 누락된 정의·목적 파일·라이브러리와 명령 인수 순서를 봅니다.
- 실행 파일을 찾지 못함
- 단계 실행 시작
- 확인
tasks.json의-o출력과launch.json의program경로를 맞춥니다. - 출력이나 동작이 예상과 다름
- 단계 실행 중
- 확인 작업 폴더·입력값·중단점·변수 값을 확인합니다.
여러 진단이 이어지면 가장 먼저 출력된 오류부터 해결합니다. 뒤의 메시지는 앞선 실패가 만든 연쇄 증상일 수 있습니다.
그림은 첫 프로그램이 동작하지 않을 때 증상으로 멈춘 단계를 찾는 표입니다. g++를 찾을 수 없다면 설치와 Path를, error:로 시작하는 진단이나 헤더를 찾지 못한다는 진단이라면 소스의 문법과 #include를, undefined reference라면 링크할 파일과 라이브러리를 봅니다. 빌드는 되었는데 디버거가 실행 파일을 찾지 못한다면 -o와 program을, 실행은 되는데 결과가 이상하다면 작업 폴더와 입력값, 중단점에서의 변수 값을 확인합니다.
정리
- 소스는 전처리, 컴파일과 어셈블, 링크를 거쳐 실행 파일이 되고,
g++같은 컴파일러 드라이버가 이 단계들을 차례로 부르며, 실행은 빌드와 별개의 단계입니다. - 널리 쓰이는 C++ 컴파일러는 GCC, Clang, MSVC이며, 기능마다 지원을 시작한 버전과 진단의 모양이 다릅니다.
- Windows에서는 VS Code와 MSYS2 UCRT64의 GCC를 설치하고
Path를 설정하며, macOS는 Command Line Tools의 Clang을, Linux는 배포판의 GCC를 씁니다. - VS Code의 세 설정 파일은 편집기의 표시, 실제 빌드, 디버거의 실행을 각각 맡으므로, 컴파일러와 표준, 출력 파일, 작업 이름을 짝으로 맞춥니다.
- 빌드가 실패하면 진단을 먼저 읽고, 옛 실행 파일이 실행되는 일이 없도록 빌드의 성공을 확인한 뒤에 실행합니다.
연습 문제
1. 디버거가 찾지 못하는 실행 파일
빌드 작업의 -o는 hello.exe로, 디버거의 program은 main.exe로 되어 있습니다. 디버깅을 시작하면 어떻게 되고, 어느 값을 맞춰야 하나요?
해설 보기
빌드는 hello.exe를 만드는데 디버거는 main.exe를 시작하려 하므로, 그 파일이 없다는 오류가 나거나 예전에 만든 다른 main.exe가 실행됩니다. 디버거의 program을 빌드가 실제로 만드는 파일과 같게 맞춥니다.
2. 편집기에서는 사라진 오류
다른 폴더의 헤더를 쓰려고 c_cpp_properties.json의 includePath에 그 폴더를 더했더니, 편집기의 빨간 밑줄은 사라졌지만 빌드는 여전히 헤더를 찾지 못한다고 합니다. 왜 그런가요?
해설 보기
includePath는 편집기의 자동 완성과 오류 표시가 헤더를 찾는 범위일 뿐, 실제 빌드를 하는 g++에는 전달되지 않습니다. 빌드 작업의 args에 -I 옵션으로 그 폴더를 더해야 컴파일러가 헤더를 찾습니다. 편집기에서 오류 표시가 사라진 것으로 빌드의 성공을 판단하지 않습니다.
3. 고친 코드가 반영되지 않을 때
인사말을 고쳐 저장하고 g++ -std=c++20 main.cpp -o hello.exe; .\hello.exe를 실행했더니 옛 인사말이 나왔습니다. 무엇을 의심해야 하나요?
해설 보기
먼저 빌드가 성공했는지 봅니다. 고친 코드에 오류가 있어 빌드가 실패했다면 새 hello.exe가 만들어지지 않고, 그 뒤의 실행 명령이 예전의 hello.exe를 실행합니다. 빌드의 진단을 읽어 오류를 고치고, 빌드가 성공한 것을 확인한 뒤에 실행합니다. 저장하지 않은 채 빌드한 것은 아닌지도 함께 확인합니다.
다음 글 첫 번째 C++ 프로그램에서는 방금 실행한 프로그램의 각 줄이 무엇을 하는지, #include와 main 함수, std::cout을 하나씩 살펴봅니다.