C++ 첫 프로그램 Hello World: 컴파일러 설치부터 코드 한 줄씩 이해하기
이 글의 핵심
처음 C++를 시작하면 코드보다 컴파일러 설치와 빌드 명령에서 먼저 막히는 경우가 많습니다. 이 글은 Hello World 하나로 작성, 컴파일, 실행의 전체 흐름을 경험하게 한 뒤, using namespace std 논쟁과 endl·개행 차이, 경고 옵션을 켜야 하는 이유, cin으로 입력을 받는 첫 수정 실습까지 이어 갑니다.
Hello World가 중요한 이유
처음 C++을 맞이하면 도구 설치와 빌드 명령이 낯설 수 있습니다. 이 글에서는 최소한의 프로그램으로 성공 경험을 쌓은 뒤, 환경별로 확장해 나갈 수 있도록 구성했습니다.
C++ 학습의 첫 단계는 “Hello, World!” 프로그램입니다. 간단해 보이지만 컴파일러 설치, 코드 작성, 컴파일, 실행의 전체 과정을 경험할 수 있습니다.
개발 환경 설정
이 글의 예제는 터미널에서 g++로 컴파일하는 흐름을 기준으로 설명합니다. 통합 개발 환경(IDE)만 쓰는 경우에도, 아래 단계를 한 번쯤 따라 해 보면 “소스 파일 → 실행 파일”이 어떻게 만들어지는지 이해하는 데 도움이 됩니다.
Windows: MinGW-w64 (g++)
- MSYS2를 설치한 뒤, MSYS2 터미널에서 패키지를 갱신합니다.
pacman -Syu - MinGW-w64 도구체인을 설치합니다.
pacman -S mingw-w64-ucrt-x86_64-gcc - 설치 경로의
bin폴더(예:C:\msys64\ucrt64\bin)를 시스템 환경 변수 PATH에 추가합니다. - 새 터미널에서
g++ --version이 출력되는지 확인합니다.
참고: WSL(Windows Subsystem for Linux)을 쓰면 Linux와 동일하게 apt 등으로 g++를 설치할 수 있습니다.
MSYS2로 설치한 뒤 가장 흔히 만나는 문제는 두 가지입니다. PATH를 추가하지 않았거나 추가한 뒤 터미널을 새로 열지 않았다면 'g++'은(는) 내부 또는 외부 명령... 아닙니다(CMD) 또는 g++ : The term 'g++' is not recognized(PowerShell)가 나옵니다. 컴파일은 되는데 만든 hello.exe를 탐색기에서 더블클릭했을 때 libstdc++-6.dll을(를) 찾을 수 없어... 오류가 뜨는 경우도 있는데, 실행 파일이 MinGW의 런타임 DLL에 의존하기 때문입니다. PATH에 ucrt64\bin이 들어가 있으면 해결되고, 다른 PC에 배포할 때는 -static 옵션으로 런타임을 실행 파일에 포함시키는 방법이 있습니다. 또 하나, 프로그램이 아직 실행 중인 상태에서 다시 컴파일하면 cannot open output file hello.exe: Permission denied가 나는데, Windows가 실행 중인 파일을 덮어쓰지 못하게 잠그기 때문이니 이전 창을 닫고 다시 빌드하면 됩니다.
Windows: Visual Studio (MSVC)
- Visual Studio Community 설치 프로그램을 실행합니다.
- 워크로드에서 “C++를 사용한 데스크톱 개발”을 선택합니다. (Windows SDK, MSVC 도구가 함께 설치됩니다.)
- 새 프로젝트에서 콘솔 앱을 만들고, 생성된
main.cpp에 예제 코드를 붙여 넣어 빌드·실행합니다.
Visual Studio는 파일 탐색기에서 cl.exe만 쓰기보다, 위 워크로드로 제공되는 개발자 명령 프롬프트 또는 IDE 안의 빌드가 가장 단순합니다.
Mac: Xcode Command Line Tools
- 터미널을 열고 다음을 실행합니다.
xcode-select --install - 안내 창에서 설치를 완료합니다. Apple이 제공하는 clang 기반 도구가 포함됩니다.
- 확인:
g++ --version # 또는 clang++ --version
GUI 앱 개발이 목적이 아니라면, 전체 Xcode가 아니라 Command Line Tools만으로도 Hello World와 컴파일 학습은 충분합니다.
macOS에서 g++ --version을 실행하면 Apple clang version ...이 출력되는데, 이는 오류가 아니라 Apple이 g++ 명령을 clang으로 연결해 두었기 때문입니다. 실제 GCC가 필요하면 Homebrew로 gcc를 설치해 g++-14처럼 버전이 붙은 명령으로 호출해야 합니다. 입문 단계에서는 clang으로 충분하며, 오류 메시지가 GCC보다 친절한 편이라 오히려 배우기 좋습니다.
Linux: g++ 또는 clang++
배포판에 따라 패키지 이름이 조금 다릅니다.
Debian / Ubuntu 계열
sudo apt update
sudo apt install build-essential
g++ --version
Fedora
sudo dnf install gcc-c++
g++ --version
Arch Linux
sudo pacman -S gcc
g++ --version
clang++를 쓰고 싶다면 배포판에 맞는 clang 패키지를 설치하면 됩니다. Hello World 수준에서는 g++와 clang++ 명령만 바꾸면 대부분 동일하게 동작합니다.
Visual Studio Code 설정
VS Code는 편집기일 뿐이므로, 위에서 설치한 컴파일러(g++ 또는 MSVC)가 먼저 동작해야 합니다.
- 확장 프로그램: C/C++ (Microsoft) 설치.
- 폴더 열기:
hello.cpp가 있는 폴더를 워크스페이스로 엽니다. - 터미널 통합:
Ctrl+`(Mac:Ctrl+`또는⌃`)로 터미널을 열고, 아래처럼 컴파일·실행합니다.g++ -std=c++17 -Wall -o hello hello.cpp ./hello - 자동 빌드(선택):
터미널 → 기본 빌드 작업 구성으로tasks.json을 만들면g++명령을 단축키로 실행할 수 있습니다. 최소 예시는 다음과 같습니다.
{
"version": "2.0.0",
"tasks": [
{
"label": "build hello",
"type": "shell",
"command": "g++",
"args": ["-std=c++17", "-Wall", "-o", "hello", "hello.cpp"],
"group": { "kind": "build", "isDefault": true }
}
]
}
파일 이름이 다르면 args의 hello.cpp와 -o 뒤 실행 파일 이름을 맞춥니다.
환경별 빠른 요약
| 환경 | 컴파일러 준비 | 이 글의 예제 실행 |
|---|---|---|
| Windows | MinGW-w64(g++) 또는 Visual Studio | g++ ... 또는 VS에서 빌드 |
| Mac | Command Line Tools | 터미널에서 g++ 또는 clang++ |
| Linux | build-essential 등 | g++ 또는 clang++ |
우리가 만들 첫 프로그램
아래는 이 글에서 계속 사용하는 기본 Hello World입니다. 앞으로 설명은 이 코드를 기준으로 합니다.
#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}
코드 한 줄씩 설명하기
#include <iostream>이 하는 일
#include는 다른 파일의 내용을 이 위치에 붙여 넣으라는 전처리기 지시문입니다.<iostream>은 표준 입출력 스트림을 다루는 헤더입니다. 여기에std::cout,std::cin,std::endl등이 선언되어 있습니다.- 헤더를 빼먹으면
cout같은 이름을 컴파일러가 모릅니다. 오타(iosteam등)도 흔한 에러 원인입니다.
using namespace std 논쟁
std::를 매번 쓰기 싫다면 아래처럼 쓸 수 있습니다.
#include <iostream>
using namespace std;
int main() {
cout << "Hello, World!" << endl;
return 0;
}
장점: 타이핑이 줄어듭니다.
단점: std 안에 수많은 이름이 있어서, 프로젝트가 커지면 이름이 충돌할 수 있습니다. 또한 교재·예제가 어떤 이름을 쓰는지 한눈에 보기 어려워질 수 있습니다.
실무·학습에서의 관용: 짧은 예제·시험용 코드에서는 using namespace std;가 자주 보입니다. 반면 헤더 파일(.h)에서는 거의 쓰지 않는 것이 좋으며, 큰 프로젝트에서는 using std::cout;처럼 필요한 것만 골라 쓰거나 std::를 유지하는 편이 안전합니다. 이 글은 초보자가 헷갈리지 않도록 std::를 붙인 형태를 기본으로 두었습니다.
int main()과 반환값
- C++ 프로그램은 실행 시작점으로
main함수를 둡니다. 운영체제가 프로그램을 시작할 때main을 호출합니다. - 반환 타입을
int로 두는 것이 표준에 맞는 일반적인 형태입니다.return 0;은 정상 종료를 뜻하는 관례입니다. (0이 아닌 값은 실패·오류 코드로 쓰는 경우가 많습니다.) main에서return을 생략하면 컴파일러가0을 반환한 것으로 처리하는 규칙도 있지만, 입문 단계에서는 명시적으로return 0;을 쓰는 습관을 들이면 좋습니다.
std::cout과 << 연산자
std::cout은 표준 출력(보통 터미널 화면)으로 보내는 스트림 객체입니다.<<는 “왼쪽 스트림에 오른쪽 값을 출력하라”는 의미로 쓰이는 스트림 삽입 연산자입니다. 여러 개를 이어서 쓸 수 있습니다.std::cout << "값: " << 42 << std::endl;
소스 코드가 실행 파일이 되기까지
g++ hello.cpp -o hello 한 줄은 사실 네 단계를 한꺼번에 실행합니다. 전처리가 #include <iostream>을 수만 줄짜리 헤더 내용으로 바꿔 붙이고, 컴파일이 그 결과를 기계어로 번역하고, 어셈블이 오브젝트 파일(.o)을 만들고, 링크가 표준 라이브러리의 실제 구현과 합쳐 실행 파일을 만듭니다. 이 구분을 알면 에러 메시지의 출처를 짐작할 수 있습니다. expected ';'처럼 문법에 관한 것은 컴파일 단계, undefined reference to ...처럼 “무엇을 찾을 수 없다”는 것은 링크 단계의 에러입니다. 흔한 예로 gcc hello.cpp(g++가 아니라 gcc)로 빌드하면 컴파일은 되지만 C++ 표준 라이브러리를 링크하지 않아 undefined reference to std::cout 류의 에러가 쏟아집니다. 궁금하다면 g++ -E hello.cpp | wc -l로 전처리 결과가 몇 줄이 되는지 확인해 보세요.
std::endl과 '\n'
std::endl은 줄바꿈 문자를 출력하며, 동시에 출력 버퍼를 비웁니다(flush).- 단순히 줄만 바꾸면 될 때는
'\n'만 쓰는 경우가 많습니다. 반복문 안에서 매번 flush하면 불필요하게 느려질 수 있기 때문입니다. - 즉시 화면에 반드시 찍혀야 할 때(예: 진행 로그를 디버깅할 때)만
endl의 flush가 유용할 수 있습니다.
std::cout << "Hello\n"; // 줄바꿈만 (대부분의 입문 예제에 적합)
std::cout << "Hello" << std::endl; // 줄바꿈 + 버퍼 비우기
컴파일과 실행
g++ 명령과 자주 쓰는 옵션
| 옵션 | 의미 |
|---|---|
-o 이름 | 만들 실행 파일 이름 지정. 없으면 a.out(Mac/Linux) 또는 a.exe(Windows MinGW) 등 기본 이름이 됩니다. |
-std=c++17 | 사용할 C++ 표준 지정. 교재가 C++17을 기준으로 하면 맞춰 주세요. |
-Wall | 자주 쓰는 경고를 켭니다. 초보자일수록 경고를 읽는 연습이 중요합니다. |
한 번에 예시:
g++ -std=c++17 -Wall -o hello hello.cpp
실행 파일 실행하기
- Mac / Linux: 현재 디렉터리는 PATH에 없으므로
./를 붙입니다../hello - Windows (PowerShell / CMD): 보통 프로젝트 폴더에서:
또는hello.exe.\hello.exe
컴파일 에러 읽는 법
컴파일러는 대부분 파일 이름, 줄 번호, 에러 이유를 순서대로 알려 줍니다.
- 가장 위에 나온 에러부터 고칩니다. 한 군데가 틀리면 그 아래에 연쇄 에러가 쏟아질 수 있습니다.
error:와note:를 구분합니다.note는 원인 힌트인 경우가 많습니다.- 따옴표·세미콜론·괄호처럼 작은 실수를 의심합니다.
예시 메시지 패턴:
hello.cpp:5:10: error: expected ';' before '}' token
→ hello.cpp의 5번째 줄 근처에서 }가 나오기 전에 ;가 필요하다는 뜻입니다.
5:10은 5번째 줄의 10번째 글자를 뜻합니다. 주의할 점은 컴파일러가 가리키는 위치가 실수한 위치가 아니라 실수를 알아챈 위치라는 것입니다. 4번째 줄 끝에 세미콜론을 빠뜨리면 컴파일러는 다음 토큰을 읽고 나서야 이상함을 알아채므로 에러는 5번째 줄로 보고됩니다. 그래서 표시된 줄에 문제가 없어 보이면 바로 윗줄부터 확인하는 습관이 도움이 됩니다. 처음 C++를 배울 때 흔히 겪는 일은 괄호 하나를 빠뜨렸는데 그 아래 수십 줄에서 에러가 쏟아지는 것인데, 이때도 맨 첫 에러만 고치고 다시 컴파일하면 나머지가 한꺼번에 사라지는 경우가 대부분입니다.
첫 수정 실습
같은 hello.cpp를 조금씩 바꿔 보며 출력과 입력을 익혀 봅니다.
여러 줄 출력하기
#include <iostream>
int main() {
std::cout << "첫 번째 줄\n";
std::cout << "두 번째 줄\n";
std::cout << "세 번째 줄\n";
return 0;
}
변수 사용해 보기
#include <iostream>
int main() {
int year = 2026;
std::cout << "올해는 " << year << "년입니다.\n";
return 0;
}
변수와 자료형을 더 깊게 다룬 글에서 int, double, std::string 등을 이어서 배울 수 있습니다.
사용자 입력 받기 (std::cin)
#include <iostream>
int main() {
int age = 0;
std::cout << "나이를 입력하세요: ";
std::cin >> age;
std::cout << "입력한 나이는 " << age << "살입니다.\n";
return 0;
}
std::cin은 표준 입력(키보드)에서 값을 읽습니다.>>는 스트림 추출 연산자로, 공백을 기준으로 토큰을 나누어 읽는 방식에 익숙해지면 됩니다.
직접 실행해 보면 두 가지 동작에 놀라게 됩니다. 나이 자리에 abc처럼 숫자가 아닌 값을 입력하면 age에는 0이 들어가고(C++11부터 읽기 실패 시 0을 저장), 이후의 std::cin 읽기는 모두 무시됩니다. 입력 스트림이 실패 상태가 되었기 때문입니다. 또 std::cin >> name으로 이름을 받으면 홍 길동처럼 공백이 들어간 입력에서 홍까지만 읽힙니다. 한 줄 전체를 받으려면 std::getline(std::cin, name)을 쓰며, 이 차이와 실패 처리 방법은 변수와 자료형 글의 입력 검증 예제에서 이어서 다룹니다.
자주 하는 실수
실수 1: iostream 오타
// ❌ 잘못된 코드
#include <iosteam> // 오타!
// ✅ 올바른 코드
#include <iostream>
실수 2: main 함수 반환 타입
// ❌ 잘못된 코드
void main() { // void는 표준이 아님 (GCC: '::main' must return 'int')
}
// ✅ 올바른 코드
int main() {
return 0;
}
실수 3: 세미콜론 누락
// ❌ 잘못된 코드
std::cout << "Hello" // 세미콜론 없음
// ✅ 올바른 코드
std::cout << "Hello";
컴파일 옵션 이해하기 (추가)
기본 컴파일
g++ hello.cpp
# 결과: a.out (Mac/Linux) 또는 a.exe (Windows)
출력 파일명 지정
g++ -o hello hello.cpp
# 결과: hello (실행 파일)
C++ 표준 지정
# C++11
g++ -std=c++11 -o hello hello.cpp
# C++17 (권장)
g++ -std=c++17 -o hello hello.cpp
# C++20
g++ -std=c++20 -o hello hello.cpp
경고 옵션 (권장)
# 모든 경고 표시
g++ -Wall -Wextra -o hello hello.cpp
# 경고를 에러로 처리
g++ -Wall -Wextra -Werror -o hello hello.cpp
온라인 컴파일러 추천
설치 없이 바로 시작하고 싶다면:
-
Compiler Explorer (godbolt.org)
- 여러 컴파일러 비교 가능
- 어셈블리 코드 확인
- 공유 기능
-
OnlineGDB (onlinegdb.com)
- 디버거 포함
- 입력/출력 테스트 가능
- 간단한 UI
-
Replit (replit.com)
- 프로젝트 저장 가능
- 협업 기능
- 무료 호스팅
다음 단계
추천 학습 순서
- 이 글: Hello World, 컴파일·실행,
cout/cin맛보기. - 변수와 자료형:
int,double,std::string, 형변환. - 조건문·반복문: 분기와 반복으로 프로그램 흐름 제어.
- 함수: 나누어 쓰기와 재사용.
코드로 미리 보는 다음 단계
1단계: 변수 배우기
int age = 25;
double height = 175.5;
std::string name = "홍길동";
2단계: 입력 받기
int age;
std::cout << "나이를 입력하세요: ";
std::cin >> age;
std::cout << "당신의 나이는 " << age << "살입니다." << std::endl;
3단계: 조건문
if (age >= 20) {
std::cout << "성인입니다." << std::endl;
} else {
std::cout << "미성년자입니다." << std::endl;
}
4단계: 반복문
for (int i = 1; i <= 10; i++) {
std::cout << i << std::endl;
}
변수와 자료형을 본격적으로 다루려면 C++ 변수와 자료형 을 이어서 읽는 것을 추천합니다.
FAQ
Q1: “Hello, World!”는 왜 항상 첫 프로그램인가요?
A: “hello, world” 예제는 Brian Kernighan이 1970년대 초 B 언어 튜토리얼에서 처음 사용했고, 1978년 Kernighan과 Ritchie의 책 The C Programming Language에 실리면서 첫 프로그램의 전통이 되었습니다. 코드는 한 줄이지만 컴파일러 설치, 빌드, 실행, 출력 확인까지 개발 환경 전체가 제대로 동작하는지 한 번에 점검할 수 있다는 점이 지금까지 쓰이는 이유입니다.
Q2: std::cout에서 std::는 무엇인가요?
A: std는 “standard”의 약자로, C++ 표준 라이브러리의 네임스페이스입니다.
네임스페이스 없이 쓰기:
#include <iostream>
using namespace std; // std:: 생략 가능
int main() {
cout << "Hello, World!" << endl; // std:: 없이 사용
return 0;
}
주의: 큰 프로젝트에서는 using namespace std;를 쓰지 않는 것이 좋습니다 (이름 충돌 방지).
Q3: endl 대신 \n을 써도 되나요?
A: 네, 대부분의 경우 \n이 더 좋습니다.
// 둘 다 가능
std::cout << "Hello" << std::endl; // 줄바꿈 + 버퍼 비우기
std::cout << "Hello" << '\n'; // 줄바꿈만 (더 빠름)
차이점:
endl: 줄바꿈 + 버퍼 비우기 (느림)\n: 줄바꿈만 (빠름)
권장: 일반적으로 \n 사용, 즉시 출력이 필요할 때만 endl
Q4: 컴파일 에러가 나는데 어떻게 하나요?
A: 에러 메시지를 잘 읽어보세요.
자주 나오는 에러:
-
iostream 철자 오류
fatal error: iosteam: No such file or directory → #include <iostream> 철자 확인 -
세미콜론 누락
error: expected ';' before '}' → 각 문장 끝에 ; 추가 -
main 함수 없음
undefined reference to 'main' (Windows MinGW에서는 undefined reference to 'WinMain') → int main() { } 함수 추가, main 철자(Main, mian) 확인이 에러는 컴파일이 아니라 링크 단계에서 나오므로 줄 번호가 없습니다. 파일을 저장하지 않은 채 빌드해서 빈 파일이 컴파일된 경우에도 똑같이 나오니, 에디터의 저장 여부도 확인해 보세요.
Q5: Visual Studio Code에서는 어떻게 하나요?
A: VS Code는 에디터이므로 컴파일러를 별도로 설치해야 합니다.
Windows:
- MinGW-w64 설치
- VS Code에서 C++ Extension 설치
tasks.json으로 빌드 작업 구성 (위 “Visual Studio Code 설정” 참고)
Mac:
- Xcode Command Line Tools 설치
- VS Code에서 C++ Extension 설치
Linux:
- GCC 설치 (
sudo apt install g++) - VS Code에서 C++ Extension 설치
간단한 방법: 터미널에서 직접 컴파일
g++ hello.cpp -o hello
./hello
Q6: 한글이 깨져요!
A: 인코딩 문제입니다. 소스 파일은 UTF-8로 저장했는데 콘솔이 다른 인코딩(한국어 Windows의 기본값은 CP949)으로 해석하면 안녕하세요가 ?덈뀞?섏꽭?? 같은 문자로 보입니다. 해결하려면 소스 파일 인코딩, 컴파일러가 해석하는 인코딩, 콘솔 출력 인코딩 세 가지를 맞춰야 합니다. MSVC는 /utf-8 옵션으로 소스와 실행 문자 집합을 UTF-8로 지정하고, 콘솔은 chcp 65001로 UTF-8로 바꿉니다. 아래의 std::locale::global(std::locale(""))은 환경에 따라 효과가 다르며, Linux에서 LANG 값이 설치되지 않은 로케일을 가리키면 오히려 locale::facet::_S_create_c_locale name not valid 예외로 프로그램이 시작하자마자 종료될 수 있으니 주의하세요.
해결법:
#include <iostream>
#include <locale> // 로케일 설정
int main() {
std::locale::global(std::locale("")); // 시스템 로케일 사용
std::cout << "안녕하세요!" << std::endl;
return 0;
}
또는 파일을 UTF-8로 저장하고:
# Windows (chcp 명령)
chcp 65001
# Mac/Linux (기본 UTF-8)
# 별도 설정 불필요
같이 보면 좋은 글
- C++ 변수와 자료형
- C++ 클래스와 객체 입문
- C++ 함수 처음 만들기
- C++ Redis 클론 | Modern C++ 인메모리 KV 스토어 [#48-1]
- C++ 초보자가 자주 하는 실수 Top 15 | 컴파일 에러부터 런타임 크래시까지