[2026] C++ path | 경로 처리 가이드

[2026] C++ path | 경로 처리 가이드

이 글의 핵심

C++17 std::filesystem::path로 플랫폼 독립 경로 결합·정규화·부분 추출을 합니다. / 연산자, canonical, extension 등 실전 패턴을 정리합니다.

들어가며

std::filesystem::path는 C++17의 플랫폼 독립적 경로 처리 클래스입니다.

실무에서 마주한 현실

개발을 배울 때는 모든 게 깔끔하고 이론적입니다. 하지만 실무는 다릅니다. 레거시 코드와 씨름하고, 급한 일정에 쫓기고, 예상치 못한 버그와 마주합니다. 이 글에서 다루는 내용도 처음엔 이론으로 배웠지만, 실제 프로젝트에 적용하면서 “아, 이래서 이렇게 설계하는구나” 하고 깨달은 것들입니다. 특히 기억에 남는 건 첫 프로젝트에서 겪은 시행착오입니다. 책에서 배운 대로 했는데 왜 안 되는지 몰라 며칠을 헤맸죠. 결국 선배 개발자의 코드 리뷰를 통해 문제를 발견했고, 그 과정에서 많은 걸 배웠습니다. 이 글에서는 이론뿐 아니라 실전에서 마주칠 수 있는 함정들과 해결 방법을 함께 다루겠습니다.

1. path란?

기본 사용

아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
int main() {
    fs::path p = "/home/user/file.txt";
    fs::path p2 = "C:\\Users\\user\\file.txt";  // Windows
    
    std::cout << p << std::endl;
    std::cout << p2 << std::endl;
    
    return 0;
}

특징:

  • 플랫폼 독립적
  • 자동 구분자 변환 (/, \)
  • 다양한 메서드 제공

2. 경로 조작

경로 분해

다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
int main() {
    fs::path p = "/home/user/documents/report.pdf";
    
    std::cout << "전체: " << p << std::endl;
    std::cout << "파일명: " << p.filename() << std::endl;      // "report.pdf"
    std::cout << "확장자: " << p.extension() << std::endl;     // ".pdf"
    std::cout << "기본명: " << p.stem() << std::endl;          // "report"
    std::cout << "부모: " << p.parent_path() << std::endl;     // "/home/user/documents"
    std::cout << "루트: " << p.root_path() << std::endl;       // "/"
    
    return 0;
}

경로 결합

다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

fs::path dir = "/home/user";
fs::path file = "file.txt";
// / 연산자
fs::path full = dir / file;  // "/home/user/file.txt"
// /= 연산자
fs::path p = "/home/user";
p /= "documents";
p /= "file.txt";
std::cout << p << std::endl;  // "/home/user/documents/file.txt"
// append
fs::path p2 = "/home";
p2.append("user").append("file.txt");

3. 경로 변환

절대 경로

아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

fs::path p = "file.txt";
// 절대 경로로 변환
fs::path abs = fs::absolute(p);
std::cout << abs << std::endl;  // "/current/directory/file.txt"

정규 경로

아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

// 실행 예제
fs::path p = "/home/user/../user/./file.txt";
// 정규 경로 (파일 존재 필요)
fs::path canonical = fs::canonical(p);
std::cout << canonical << std::endl;  // "/home/user/file.txt"
// weakly_canonical (파일 존재 불필요)
fs::path p2 = "/home/user/nonexistent.txt";
fs::path weak = fs::weakly_canonical(p2);
std::cout << weak << std::endl;

상대 경로

아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

fs::path abs = "/home/user/documents/file.txt";
fs::path base = "/home/user";
// 상대 경로 계산
fs::path rel = fs::relative(abs, base);
std::cout << rel << std::endl;  // "documents/file.txt"

4. 경로 확인

경로 타입

다음은 cpp를 활용한 상세한 구현 코드입니다. 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

fs::path p = "/home/user/file.txt";
// 절대 경로?
if (p.is_absolute()) {
    std::cout << "절대 경로" << std::endl;
}
// 상대 경로?
if (p.is_relative()) {
    std::cout << "상대 경로" << std::endl;
}
// 비어있음?
if (p.empty()) {
    std::cout << "빈 경로" << std::endl;
}
// 경로 존재?
if (fs::exists(p)) {
    std::cout << "존재함" << std::endl;
}

5. 확장자 처리

확장자 변경

아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

fs::path p = "document.txt";
// 확장자 변경
p.replace_extension(".pdf");
std::cout << p << std::endl;  // "document.pdf"
// 확장자 제거
p.replace_extension();
std::cout << p << std::endl;  // "document"
// 확장자 추가
p.replace_extension(".docx");
std::cout << p << std::endl;  // "document.docx"

확장자 확인

아래 코드는 cpp를 사용한 구현 예제입니다. 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

fs::path p = "image.png";
if (p.extension() == ".png") {
    std::cout << "PNG 파일" << std::endl;
}
// 여러 확장자 확인
std::vector<std::string> image_exts = {".png", ".jpg", ".jpeg", ".gif"};
if (std::find(image_exts.begin(), image_exts.end(), p.extension()) != image_exts.end()) {
    std::cout << "이미지 파일" << std::endl;
}

6. 경로 비교

다음은 cpp를 활용한 상세한 구현 코드입니다. 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

fs::path p1 = "/home/user/file.txt";
fs::path p2 = "/home/user/file.txt";
fs::path p3 = "/home/user/other.txt";
if (p1 == p2) {
    std::cout << "같음" << std::endl;
}
if (p1 != p3) {
    std::cout << "다름" << std::endl;
}
// 대소문자 구분 (플랫폼 의존)
// Windows: 구분 안 함
// Linux: 구분함

7. 실전 예제

예제 1: 파일 확장자 일괄 변경

다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 에러 처리를 통해 안정성을 확보합니다, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
void rename_extensions(const fs::path& dir, 
                       const std::string& old_ext, 
                       const std::string& new_ext) {
    for (const auto& entry : fs::directory_iterator(dir)) {
        if (entry.is_regular_file() && entry.path().extension() == old_ext) {
            fs::path new_path = entry.path();
            new_path.replace_extension(new_ext);
            fs::rename(entry.path(), new_path);
            std::cout << "변경: " << entry.path().filename() 
                      << " → " << new_path.filename() << std::endl;
        }
    }
}
int main() {
    rename_extensions("./images", ".jpeg", ".jpg");
    return 0;
}

예제 2: 백업 경로 생성

다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

fs::path create_backup_path(const fs::path& original) {
    fs::path backup = original;
    backup.replace_extension();
    
    std::string backup_name = backup.filename().string() + "_backup";
    backup = backup.parent_path() / backup_name;
    backup.replace_extension(original.extension());
    
    return backup;
}
int main() {
    fs::path original = "/home/user/document.txt";
    fs::path backup = create_backup_path(original);
    
    std::cout << "원본: " << original << std::endl;
    std::cout << "백업: " << backup << std::endl;
    // 백업: /home/user/document_backup.txt
    
    return 0;
}

정리

핵심 요약

  1. path: C++17 플랫폼 독립 경로
  2. / 연산자: 경로 결합
  3. filename(): 파일명 추출
  4. extension(): 확장자 추출
  5. absolute(): 절대 경로 변환
  6. canonical(): 정규 경로 (존재 필요)

주요 메서드

메서드설명
filename()파일명
extension()확장자
stem()확장자 제외 파일명
parent_path()부모 경로
root_path()루트 경로
replace_extension()확장자 변경

다음 단계


관련 글

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3