Skip to content

Commit e9c5f1a

Browse files
committed
docs: add page for Include What You Use
1 parent 40274df commit e9c5f1a

2 files changed

Lines changed: 88 additions & 1 deletion

File tree

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# 사용하는 것만 포함하기 (Include What You Use)
2+
3+
소스 파일이나 헤더 파일이 다른 곳에 정의된 심볼을 참조한다면, 해당 심볼의 선언 또는 정의를 제대로 제공하는 헤더 파일을 **직접** 포함해야 합니다. 다른 이유로 헤더 파일을 포함해서는 안 됩니다.
4+
5+
간접 포함(transitive include)에 의존하지 마세요. 이렇게 하면 더 이상 필요하지 않은 `#include`를 헤더에서 제거하더라도 클라이언트 코드가 깨지지 않습니다. 이는 관련된 헤더에도 동일하게 적용됩니다. 예를 들어, `foo.cc``bar.h`에 정의된 심볼을 사용한다면, `foo.h``bar.h`를 포함하고 있더라도 `foo.cc``bar.h`를 직접 포함해야 합니다.
6+
7+
---
8+
9+
## 이해하기 쉽게 설명하기
10+
11+
### 기본 원칙: "내가 쓰는 건 내가 포함한다"
12+
13+
- 어떤 파일이 특정 타입, 함수, 상수 등을 **사용**한다면, 그 파일은 해당 심볼을 선언/정의하는 헤더를 **직접 포함**해야 합니다.
14+
- 다른 이유로 헤더 파일을 포함해서는 안된다는 말은, 관성, 습관, 혹시 몰라서 등으로 헤더를 넣으면 안된다는 의미입니다.
15+
- "다른 헤더가 이미 포함하고 있으니까 괜찮겠지"라는 생각은 금지입니다.
16+
17+
### 왜 간접 포함(transitive include)에 의존하면 안 될까?
18+
19+
간접 포함에 의존하면 다음과 같은 문제가 생깁니다:
20+
21+
- A 헤더가 B 헤더를 포함하고, B 헤더가 C 헤더를 포함한다고 해봅시다.
22+
- 어떤 `.cc` 파일이 C에 있는 심볼을 쓰면서 A만 포함하고, C를 직접 포함하지 않는다면, 구조가 바뀌었을 때 문제가 됩니다.
23+
- 나중에 B에서 C에 대한 `#include`를 삭제하면, 해당 `.cc` 파일은 갑자기 컴파일이 깨집니다.
24+
25+
즉, **내 파일이 사용하는 심볼이 어디에서 오는지 명확히 하기 위해** 직접 포함이 필요합니다.
26+
27+
### 예시: 나쁜 코드
28+
29+
```cpp
30+
// bar.h
31+
struct Bar {
32+
int value;
33+
};
34+
35+
// foo.h
36+
#include "bar.h"
37+
38+
void ProcessBar(const Bar& bar);
39+
40+
// foo.cc
41+
#include "foo.h" // 여기서는 bar.h를 직접 포함하지 않음
42+
43+
void ProcessBar(const Bar& bar) {
44+
// Bar를 사용하지만, foo.cc는 bar.h를 직접 포함하지 않음
45+
}
46+
```
47+
48+
위 코드에서 `foo.cc`는 `Bar` 타입을 사용하지만, `bar.h`를 직접 포함하지 않습니다. 만약 `foo.h`에서 `#include "bar.h"`를 제거하면, `foo.cc`는 컴파일 오류가 발생합니다.
49+
50+
### 예시: 좋은 코드
51+
52+
```cpp
53+
// bar.h
54+
struct Bar {
55+
int value;
56+
};
57+
58+
// foo.h
59+
#include "bar.h"
60+
61+
void ProcessBar(const Bar& bar);
62+
63+
// foo.cc
64+
#include "foo.h"
65+
#include "bar.h" // foo.cc가 직접 bar.h를 포함
66+
67+
void ProcessBar(const Bar& bar) {
68+
// Bar를 안전하게 사용 가능
69+
}
70+
```
71+
72+
이렇게 하면 `foo.h`에서 `bar.h`를 포함하는 방식이 바뀌더라도, `foo.cc`는 여전히 `bar.h`를 직접 포함하고 있으므로 안전합니다.
73+
74+
### 관련 헤더에도 동일한 규칙 적용
75+
76+
- `foo.cc``bar.h`의 심볼을 사용한다면, `foo.h``bar.h`를 포함하고 있더라도 `foo.cc`**반드시** `bar.h`를 직접 포함해야 합니다.
77+
- 이렇게 하면 각 파일이 자신이 필요로 하는 의존성을 명확히 표현하게 되어, 의존 관계가 더 투명해지고 리팩토링도 쉬워집니다.
78+
79+
### 정리
80+
81+
- **원칙**: 사용하는 것은 직접 포함한다. (Include What You Use)
82+
- **하지 말 것**: "다른 헤더가 대신 포함해 주겠지"라고 기대하지 말 것.
83+
- **효과**:
84+
- 불필요한 `#include`를 제거해도 안전
85+
- 의존 관계가 명확해짐
86+
- 리팩토링과 빌드 속도 개선에 도움이 됨

mkdocs.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,5 @@ nav:
8989
- 헤더 파일:
9090
- 헤더 파일: header_files.md
9191
- 자체 포함 헤더: self_contained_headers.md
92-
- "#define 가드": define_guard.md
92+
- "#define 가드": define_guard.md
93+
- 사용하는 것만 포함하기: include_what_you_use.md

0 commit comments

Comments
 (0)