C++ include 에러 | "No such file" 헤더 파일 못 찾는 에러 해결
이 글의 핵심
C++ include 에러에 대한 실전 가이드입니다.
들어가며: “헤더 파일을 못 찾는다는 에러가 나요"
"iostream을 include 했는데 에러가 나요”
C++에서 include 에러는 초보자가 가장 자주 겪는 컴파일 에러 중 하나입니다. 파일 경로, 순환 include, 전방 선언 등 여러 원인이 있습니다.
// ❌ 에러 코드
#include <iostrem> // 오타
int main() {
std::cout << "Hello\n";
}
// fatal error: iostrem: No such file or directory
이 글에서 다루는 것:
- include 에러 5가지 주요 원인
- include 경로 설정 방법
- 순환 include 해결법
- 전방 선언 사용법
- 헤더 가드 vs #pragma once
목차
1. include 에러 5가지 원인
원인 1: 파일명 오타
// ❌ 오타
#include <iostrem> // iostream 아님!
// fatal error: iostrem: No such file or directory
해결: 파일명을 정확히 확인.
// ✅ 올바른 코드
#include <iostream>
원인 2: 파일이 없음
// ❌ 파일이 없음
#include "myheader.h" // myheader.h 파일이 없음
// fatal error: myheader.h: No such file or directory
해결: 파일 생성 또는 경로 확인.
# 파일 존재 확인
ls myheader.h
# 또는 find로 검색
find . -name "myheader.h"
원인 3: include 경로 미설정
// ❌ include 경로 없음
#include "utils/helper.h" // utils/ 디렉토리가 include 경로에 없음
// fatal error: utils/helper.h: No such file or directory
해결: include 경로 추가.
# GCC/Clang
g++ -I./src -I./include main.cpp
# CMake
include_directories(src include)
원인 4: 대소문자 불일치 (Linux/macOS)
// ❌ 대소문자 다름
#include "MyHeader.h" // 실제 파일: myheader.h
// fatal error: MyHeader.h: No such file or directory (Linux/macOS)
// Windows에서는 OK (대소문자 구분 안 함)
해결: 파일명 대소문자를 정확히 맞추기.
원인 5: 순환 include
// ❌ 순환 include
// A.h
#include "B.h"
class A {
B b;
};
// B.h
#include "A.h"
class B {
A a;
};
// 컴파일 에러: incomplete type
해결: 전방 선언 사용 (다음 섹션).
2. include 경로 설정
<> vs ""
// <> : 시스템 include 경로에서 검색
#include <iostream>
#include <vector>
// "" : 현재 디렉토리 → 시스템 경로 순서로 검색
#include "myheader.h"
#include "utils/helper.h"
규칙:
- 표준 라이브러리:
<> - 프로젝트 헤더:
""
GCC/Clang: -I 옵션
# 프로젝트 구조
project/
├─ src/
│ ├─ main.cpp
│ └─ utils/
│ └─ helper.h
└─ include/
└─ config.h
# include 경로 추가
g++ -I./src -I./include src/main.cpp
# main.cpp에서 사용
#include "utils/helper.h" // src/utils/helper.h
#include "config.h" // include/config.h
CMake
# CMakeLists.txt
include_directories(
${CMAKE_SOURCE_DIR}/src
${CMAKE_SOURCE_DIR}/include
)
# 또는 타겟별 설정
target_include_directories(myapp PRIVATE
${CMAKE_SOURCE_DIR}/src
${CMAKE_SOURCE_DIR}/include
)
Visual Studio
프로젝트 속성 → C/C++ → 일반 → 추가 포함 디렉터리
예: $(ProjectDir)src;$(ProjectDir)include
3. 순환 include 해결
문제 상황
// ❌ 순환 include
// Player.h
#ifndef PLAYER_H
#define PLAYER_H
#include "Weapon.h"
class Player {
Weapon weapon_; // 완전한 타입 필요
};
#endif
// Weapon.h
#ifndef WEAPON_H
#define WEAPON_H
#include "Player.h"
class Weapon {
Player* owner_; // 포인터 → 전방 선언 가능
};
#endif
// 컴파일 에러: incomplete type
해결법 1: 전방 선언
// ✅ Player.h
#ifndef PLAYER_H
#define PLAYER_H
class Weapon; // 전방 선언
class Player {
Weapon* weapon_; // 포인터 → 전방 선언으로 충분
void setWeapon(Weapon* w); // 선언만
};
#endif
// ✅ Player.cpp
#include "Player.h"
#include "Weapon.h" // 여기서 완전한 정의 include
void Player::setWeapon(Weapon* w) {
weapon_ = w;
w->setOwner(this); // Weapon 멤버 함수 호출 가능
}
해결법 2: 포인터/참조로 변경
// ❌ 값 저장 (완전한 타입 필요)
class Player {
Weapon weapon_; // include "Weapon.h" 필요
};
// ✅ 포인터 저장 (전방 선언 가능)
class Player {
std::unique_ptr<Weapon> weapon_; // 전방 선언으로 충분
};
4. 전방 선언
전방 선언 가능한 경우
// ✅ 포인터
class MyClass;
MyClass* ptr;
// ✅ 참조
class MyClass;
MyClass& ref = ...;
// ✅ 함수 매개변수/반환 타입
class MyClass;
void foo(MyClass* obj);
MyClass* bar();
전방 선언 불가능한 경우
// ❌ 값 저장 (크기를 알아야 함)
class MyClass;
MyClass obj; // 컴파일 에러: incomplete type
// ❌ 멤버 함수 호출
class MyClass;
MyClass* ptr = ...;
ptr->foo(); // 컴파일 에러: incomplete type
// ❌ sizeof
class MyClass;
size_t size = sizeof(MyClass); // 컴파일 에러
// ❌ 상속
class MyClass;
class Derived : public MyClass {}; // 컴파일 에러
전방 선언 패턴
// ✅ 헤더: 전방 선언 + 포인터
// Manager.h
#ifndef MANAGER_H
#define MANAGER_H
#include <memory>
class Worker; // 전방 선언
class Manager {
std::unique_ptr<Worker> worker_;
public:
void setWorker(std::unique_ptr<Worker> w);
Worker* getWorker() const;
};
#endif
// ✅ 소스: 완전한 정의 include
// Manager.cpp
#include "Manager.h"
#include "Worker.h" // 여기서 완전한 정의
void Manager::setWorker(std::unique_ptr<Worker> w) {
worker_ = std::move(w);
}
Worker* Manager::getWorker() const {
return worker_.get();
}
5. 헤더 가드
#ifndef 방식
// MyClass.h
#ifndef MYCLASS_H
#define MYCLASS_H
class MyClass {
// ...
};
#endif // MYCLASS_H
장점: 표준, 모든 컴파일러 지원. 단점: 타이핑 많음, 파일명 바뀌면 수동 변경.
#pragma once 방식 (권장)
// MyClass.h
#pragma once
class MyClass {
// ...
};
장점: 간결, 파일명 충돌 없음. 단점: 비표준 (하지만 모든 주요 컴파일러 지원).
비교
| 항목 | #ifndef | #pragma once |
|---|---|---|
| 표준 | 표준 | 비표준 (사실상 표준) |
| 타이핑 | 많음 | 적음 |
| 파일명 충돌 | 가능 | 없음 |
| 컴파일 속도 | 느림 | 빠름 (일부 컴파일러) |
권장: #pragma once (모든 주요 컴파일러 지원).
실전 사례 분석
사례 1: 외부 라이브러리 include
에러 코드:
// ❌ 에러 코드
#include <boost/asio.hpp>
// fatal error: boost/asio.hpp: No such file or directory
해결:
# 1. 라이브러리 설치
sudo apt install libboost-all-dev
# 2. include 경로 추가
g++ -I/usr/include main.cpp
# 또는 pkg-config 사용
g++ $(pkg-config --cflags boost) main.cpp
사례 2: 프로젝트 내부 헤더
에러 코드:
// 프로젝트 구조
project/
├─ src/
│ ├─ main.cpp
│ └─ utils.cpp
└─ include/
└─ utils.h
// main.cpp
#include "utils.h" // ❌ include/ 디렉토리를 못 찾음
// fatal error: utils.h: No such file or directory
해결:
# include 경로 추가
g++ -I./include src/main.cpp src/utils.cpp
# 또는 상대 경로
#include "../include/utils.h" # 비권장 (경로 변경 시 깨짐)
정리
include 에러 해결 체크리스트
- 파일명 오타가 없는가?
- 파일이 존재하는가?
- include 경로가 설정되었는가? (-I 옵션)
- 대소문자가 일치하는가? (Linux/macOS)
- 순환 include가 있는가? (전방 선언 사용)
- 헤더 가드가 있는가? (#pragma once)
include 경로 설정 방법
| 빌드 시스템 | 방법 |
|---|---|
| GCC/Clang | -I./include |
| CMake | include_directories() |
| Visual Studio | 프로젝트 속성 → 추가 포함 디렉터리 |
| Makefile | CXXFLAGS += -I./include |
핵심 규칙
- 표준 라이브러리는
<>(iostream, vector 등) - 프로젝트 헤더는
""(myheader.h) - 헤더 가드는 필수 (#pragma once 권장)
- 순환 include는 전방 선언으로 해결
- include 경로를 명확히 설정 (-I 옵션)
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- C++ 헤더 파일 | 선언과 정의 분리 완벽 가이드
- C++ 전방 선언 | Forward Declaration 가이드
- C++ 컴파일 과정 | 전처리·컴파일·링크 단계
- C++ multiple definition 에러 해결
마치며
include 에러는 파일 경로와 순환 include를 이해하면 쉽게 해결됩니다.
핵심 원칙:
- include 경로를 명확히 설정 (-I 옵션)
- 순환 include는 전방 선언으로 해결
- 헤더 가드는 필수 (#pragma once 권장)
- 표준 라이브러리는
<>, 프로젝트 헤더는""
프로젝트가 커질수록 include 관리가 중요해집니다. 전방 선언과 헤더 가드를 적극 활용해 컴파일 속도와 의존성을 개선하세요.
다음 단계: include를 이해했다면, C++ 컴파일 과정 완벽 가이드에서 전처리·컴파일·링크 단계를 깊이 이해해 보세요.
관련 글
- C++ 시리즈 전체 보기
- C++ Adapter Pattern 완벽 가이드 | 인터페이스 변환과 호환성
- C++ ADL |
- C++ Aggregate Initialization |