C++ Hello World | '처음 시작하는 분을 위한' 입문 가이드
이 글의 핵심
C++ 입문 시 Hello World로 컴파일·실행 흐름을 익히는 것이 좋습니다. Windows·Mac·Linux에서 개발 환경을 준비하고, VS Code 설정, 소스 한 줄씩 의미, g++ 옵션, 첫 실습(변수·입력)까지 초보자 눈높이로 안내합니다.
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++를 설치할 수 있습니다.
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와 컴파일 학습은 충분합니다.
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;
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번째 줄 근처에서 }가 나오기 전에 ;가 필요하다는 뜻입니다.
첫 수정 실습
같은 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은 표준 입력(키보드)에서 값을 읽습니다.>>는 스트림 추출 연산자로, 공백을 기준으로 토큰을 나누어 읽는 방식에 익숙해지면 됩니다.
자주 하는 실수
실수 1: iostream 오타
// ❌ 잘못된 코드
#include <iosteam> // 오타!
// ✅ 올바른 코드
#include <iostream>
실수 2: main 함수 반환 타입
// ❌ 잘못된 코드
void main() { // void는 표준이 아님
}
// ✅ 올바른 코드
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++ 변수와 자료형 | int, double, string 완벽 정리 [초보자용] 을 이어서 읽는 것을 추천합니다.
FAQ
Q1: “Hello, World!”는 왜 항상 첫 프로그램인가요?
A: 1978년 Brian Kernighan이 쓴 C 언어 책에서 시작된 전통입니다. 가장 간단하면서도 컴파일러 설치부터 실행까지 전체 과정을 확인할 수 있어서 첫 프로그램으로 완벽합니다.
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 철자 오류
error: iostream: No such file or directory → #include <iostream> 철자 확인 -
세미콜론 누락
error: expected ';' before '}' → 각 문장 끝에 ; 추가 -
main 함수 없음
error: undefined reference to 'main' → int main() { } 함수 추가
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: 인코딩 문제입니다.
해결법:
#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++ 변수와 자료형 | int, double, string 완벽 정리 [초보자용]
- C++ 클래스와 객체 | “초보자를 위한” 완벽 가이드 [그림으로 이해]
- C++ 함수 | “처음 배우는” 함수 만들기 완벽 가이드 [예제 10개]
- C++ Redis 클론 | Modern C++ 인메모리 KV 스토어 [#48-1]
관련 글
- C++ 변수와 자료형 | int, double, string 완벽 정리 [초보자용]
- C++ 클래스와 객체
- C++ 초보자가 자주 하는 실수 Top 15 | 컴파일 에러부터 런타임 크래시까지
- C++ 함수
심화 부록: 구현·운영 관점
이 부록은 앞선 본문에서 다룬 주제(「C++ Hello World | ‘처음 시작하는 분을 위한’ 입문 가이드」)를 구현·런타임·운영 관점에서 다시 압축합니다. 도메인별 세부 구현은 글마다 다르지만, 입력 검증 → 핵심 연산 → 부작용(I/O·네트워크·동시성) → 관측의 흐름으로 장애를 나누면 원인 추적이 빨라집니다.
내부 동작과 핵심 메커니즘
flowchart TD A[입력·요청·이벤트] --> B[파싱·검증·디코딩] B --> C[핵심 연산·상태 전이] C --> D[부작용: I/O·네트워크·동시성] D --> E[결과·관측·저장]
sequenceDiagram participant C as 클라이언트/호출자 participant B as 경계(런타임·게이트웨이·프로세스) participant D as 의존성(API·DB·큐·파일) C->>B: 요청/이벤트 B->>D: 조회·쓰기·RPC D-->>B: 지연·부분 실패·재시도 가능 B-->>C: 응답 또는 오류(코드·상관 ID)
- 불변 조건(Invariant): 버퍼 경계, 프로토콜 상태, 트랜잭션 격리, FD 상한 등 단계별로 문장으로 적어 두면 디버깅 비용이 줄어듭니다.
- 결정성: 순수 층과 시간·네트워크·스케줄에 의존하는 층을 분리해야 테스트와 장애 분석이 쉬워집니다.
- 경계 비용: 직렬화, 인코딩, syscall 횟수, 락 경합, 할당·GC, 캐시 미스를 의심 목록에 둡니다.
- 백프레셔: 생산자가 소비자보다 빠를 때 버퍼·큐·스트림에서 속도를 줄이는 신호를 어디에 둘지 정의합니다.
프로덕션 운영 패턴
| 영역 | 운영 관점 질문 |
|---|---|
| 관측성 | 요청 단위 상관 ID, 에러율·지연 p95/p99, 의존성 타임아웃·재시도가 대시보드에 보이는가 |
| 안전성 | 입력 검증·권한·비밀·감사 로그가 코드 경로마다 일관적인가 |
| 신뢰성 | 재시도는 멱등 연산에만 적용되는가, 서킷 브레이커·백오프·DLQ가 있는가 |
| 성능 | 캐시·배치 크기·커넥션 풀·인덱스·백프레셔가 데이터 규모에 맞는가 |
| 배포 | 롤백 룬북, 카나리/블루그린, 마이그레이션·피처 플래그가 문서화되어 있는가 |
| 용량 | 피크 트래픽·디스크·FD·스레드 풀 상한을 주기적으로 검증하는가 |
스테이징은 데이터 양·네트워크 RTT·동시성을 프로덕션에 가깝게 맞출수록 재현율이 올라갑니다.
확장 예시: 엔드투엔드 미니 시나리오
앞선 본문 주제(「C++ Hello World | ‘처음 시작하는 분을 위한’ 입문 가이드」)를 배포·운영 흐름에 맞춰 옮긴 체크리스트입니다. 도메인에 맞게 단계 이름만 바꿔 적용할 수 있습니다.
- 입력 계약 고정: 스키마·버전·최대 페이로드·타임아웃·에러 코드를 경계에 둔다.
- 핵심 경로 계측: 요청 ID, 단계별 지연, 외부 호출 결과 코드를 로그·메트릭·트레이스에서 한 흐름으로 본다.
- 실패 주입: 의존성 타임아웃·5xx·부분 데이터·락 대기를 스테이징에서 재현한다.
- 호환·롤백: 설정/마이그레이션/클라이언트 버전을 되돌릴 수 있는지 확인한다.
- 부하 후 검증: 피크 대비 p95/p99, 에러율, 리소스 상한, 알림 임계값을 점검한다.
handle(request):
ctx = newCorrelationId()
validated = validateSchema(request)
authorize(validated, ctx)
result = domainCore(validated)
persistOrEmit(result, idempotentKey)
recordMetrics(ctx, latency, outcome)
return result
문제 해결(Troubleshooting)
| 증상 | 가능 원인 | 조치 |
|---|---|---|
| 간헐적 실패 | 레이스, 타임아웃, 외부 의존성, DNS | 최소 재현 스크립트, 분산 트레이스·로그 상관관계, 재시도·서킷 설정 점검 |
| 성능 저하 | N+1, 동기 I/O, 락 경합, 과도한 직렬화, 캐시 미스 | 프로파일러·APM으로 핫스팟 확인 후 한 가지씩 제거 |
| 메모리 증가 | 캐시 무제한, 구독/리스너 누수, 대용량 버퍼, 커넥션 미반납 | 상한·TTL·힙/FD 스냅샷 비교 |
| 빌드·배포만 실패 | 환경 변수, 권한, 플랫폼 차이, lockfile | CI 로그와 로컬 diff, 런타임·이미지 버전 핀 |
| 설정 불일치 | 프로필·시크릿·기본값, 리전 | 스키마 검증된 설정 단일 소스와 배포 매트릭스 표준화 |
| 데이터 불일치 | 비멱등 재시도, 부분 쓰기, 캐시 무효화 누락 | 멱등 키·아웃박스·트랜잭션 경계 재검토 |
권장 순서: (1) 최소 재현 (2) 최근 변경 범위 축소 (3) 환경·의존성 차이 (4) 관측으로 가설 검증 (5) 수정 후 회귀·부하 테스트.
배포 전에는 git add → git commit → git push 후 npm run deploy 순서를 권장합니다.
이 글에서 다루는 키워드 (관련 검색어)
C++, Hello World, 초보자, 튜토리얼, 시작하기, 환경설정 등으로 검색하시면 이 글이 도움이 됩니다.