파일 구조
지금까지 우리는 하나의 파일 안에서 모든 코드를 작성했습니다. 하지만 실제 프로그램은 수십, 수백 개의 파일로 이루어져 있습니다. C++에서는 이 파일들을 어떻게 정리할까요?
C++은 다른 언어들과 조금 다릅니다. package나 module 같은 키워드 대신, **헤더 파일(.h)**과 **소스 파일(.cpp)**을 나누고, #include로 연결하는 방식을 사용합니다.
헤더 파일과 소스 파일
C++에서는 하나의 기능을 만들 때 보통 두 개의 파일을 만듭니다:
- 헤더 파일 (.h): “이런 기능이 있습니다”라고 선언하는 파일
- 소스 파일 (.cpp): 그 기능이 실제로 어떻게 작동하는지 적는 파일
// calculator.h (헤더 파일 - 선언)
int add(int a, int b);
int subtract(int a, int b);
// calculator.cpp (소스 파일 - 구현)
#include "calculator.h"
int add(int a, int b) {
return a + b;
}
int subtract(int a, int b) {
return a - b;
}
왜 굳이 두 파일로 나눌까요? 레스토랑에 비유하면, 헤더 파일은 메뉴판(어떤 요리가 있는지)이고, 소스 파일은 조리법(어떻게 만드는지)입니다. 손님(다른 파일)은 메뉴판만 보면 되지, 조리법까지 알 필요는 없습니다.
#include의 의미
우리가 처음부터 써왔던 #include <iostream>의 의미를 이제 정확히 이해할 수 있습니다.
#include <iostream>
이것은 “iostream이라는 헤더 파일을 여기에 포함시켜라”라는 뜻입니다.
#include에는 두 가지 형태가 있습니다:
#include <iostream> // 표준 라이브러리에서 가져오기
#include "calculator.h" // 내가 만든 파일에서 가져오기
< >: C++이 미리 만들어 놓은 표준 도구함에서 가져옵니다" ": 현재 프로젝트 안에서 가져옵니다
다른 파일의 기능 사용하기
// main.cpp
#include <iostream>
#include "calculator.h"
int main() {
int result = add(3, 5);
std::cout << result << std::endl; // 8
return 0;
}
#include "calculator.h"를 적으면, calculator.h에 선언된 함수들을 사용할 수 있게 됩니다.
네임스페이스 (namespace)
프로젝트가 커지면, 같은 이름의 함수가 여러 곳에 생길 수 있습니다. 이를 방지하기 위해 C++은 네임스페이스를 사용합니다.
namespace math_utils {
int add(int a, int b) {
return a + b;
}
}
namespace string_utils {
std::string add(std::string a, std::string b) {
return a + b;
}
}
사용할 때는:
int result1 = math_utils::add(3, 5); // 숫자 덧셈
std::string result2 = string_utils::add("Hello", " World"); // 문자열 연결
우리가 매번 써왔던 std::가 바로 이것입니다! std는 C++ 표준 라이브러리의 네임스페이스입니다.
std::cout→ std 네임스페이스에 있는 coutstd::endl→ std 네임스페이스에 있는 endl
실제 프로젝트는 이렇게 생겼습니다
my_game/
├── CMakeLists.txt ← 빌드 설정 파일
├── main.cpp ← 프로그램 시작점
├── include/ ← 헤더 파일 모음
│ ├── character.h
│ ├── weapon.h
│ └── utils.h
└── src/ ← 소스 파일 모음
├── character.cpp
├── weapon.cpp
└── utils.cpp
이렇게 정리하면, “캐릭터 관련 기능이 궁금하면 character.h를 보고, 구현이 궁금하면 character.cpp를 보면 되겠구나!” 하고 바로 찾을 수 있습니다.
C++의 표준 라이브러리
자주 사용되는 표준 헤더 파일들:
| 헤더 | 설명 |
|---|---|
<iostream> | 입출력 (cout, cin) |
<string> | 문자열 처리 |
<vector> | 동적 배열 |
<map> | 키-값 쌍 자료구조 |
<algorithm> | 정렬, 검색 등 알고리즘 |
<cmath> | 수학 함수 |
#include <vector>
#include <algorithm>
std::vector<int> numbers = {3, 1, 4, 1, 5};
std::sort(numbers.begin(), numbers.end());
정리하자면:
- 헤더 파일 (.h) = 기능을 선언하는 메뉴판
- 소스 파일 (.cpp) = 기능을 구현하는 조리법
- #include = 다른 파일의 코드를 가져다 쓰기
- namespace = 이름 충돌을 방지하는 울타리 (std:: 의 정체!)
- 표준 라이브러리 = C++이 미리 만들어 놓은 도구 모음
C++의 파일 구조는 처음에는 복잡하게 느껴지지만, 이 원리를 이해하면 대규모 프로그램도 체계적으로 관리할 수 있습니다!