1. 소개
왜 굳이 Path 클래스가 필요할까?
파일 작업은 경로와 떼려야 뗄 수 없습니다. 경로는 프로그램에게 어디서 파일이나 폴더를 찾아야 하는지 알려주죠.
일상에서는 주소가 있죠: 시 [도시이름], 거리 [거리이름], 번지 [집번호]. 컴퓨터에서 파일 경로는 대략 이렇게 보입니다:
"C:\Program Files\MyApp\data.txt"
또는, 크로스플랫폼을 생각한다면:
"/home/username/documents/data.txt"
문제는 운영체제마다 경로 구분자가 다르고, 길이나 허용 문자에 제약이 있을 수 있다는 점입니다. 사용자가 경로를 직접 입력하면 쉽게 실수할 수 있어요: Windows에서는 이스케이프된 역슬래시(\\)를 몰라서 헤맬 수 있고, Unix 계열에서는 경로가 /로 시작한다는 걸 모를 수도 있습니다.
별짓하지 말고 .NET이 제공하는 정적 클래스 System.IO.Path를 쓰세요. 경로 파싱, 변경, 결합 같은 작업을 대신 처리해줍니다. 이제 이 히어로를 좀 더 자세히 알아봅시다!
Path가 해결해주는 주요 과제
- 파일 확장자 가져오기.
- 전체 경로에서 파일이나 디렉터리 이름 추출하기.
- 조각들을 합쳐 절대/상대 경로 만들기.
- 해당 OS에서 경로가 유효한지 검사하기.
- 파일 확장자 교체하기.
- 기본 디렉터리와 상위 폴더 판별하기.
- 경로 구분자의 크로스플랫폼 처리.
- 임시 파일 및 디렉터리 작업.
표: 주요 메서드와 속성 — Path
| 메서드/속성 | 무엇을 하는가 |
|---|---|
|
확장자를 포함한 파일 이름 |
|
파일 확장자 (예: .txt) |
|
파일이 있는 폴더 경로 |
|
확장자 없는 파일 이름 |
|
경로 조각들을 깔끔하고 크로스플랫폼하게 합침 |
|
파일 확장자 변경 |
|
절대 경로 반환 |
|
경로에서 금지된 문자들 |
|
이름에서 금지된 문자들 |
|
임시 파일용 폴더 경로 |
|
유일한 임시 파일을 생성하고 그 경로 반환 |
|
디렉터리 구분자 (예: \ 또는 /) |
|
대체 구분자 |
|
환경 변수 내 경로 구분자 (; 또는 :) |
2. 경로의 부분들 얻기
거의 모든 Path의 메서드는 정적입니다. 인스턴스 만들 필요 없이 Path.메서드이름(...)처럼 호출하면 됩니다.
자주 쓰이는 도구들: GetFileName, GetDirectoryName, GetExtension, GetFileNameWithoutExtension. 언제든 경로에서 파일 이름만, 확장자만, 혹은 부모 폴더만 필요할 수 있습니다.
예제:
using System;
using System.IO;
string path = @"C:\Projects\MyApp\data\info.json";
Console.WriteLine(Path.GetFileName(path)); // info.json
Console.WriteLine(Path.GetFileNameWithoutExtension(path)); // info
Console.WriteLine(Path.GetExtension(path)); // .json
Console.WriteLine(Path.GetDirectoryName(path)); // C:\Projects\MyApp\data
| 코드 | 결과 |
|---|---|
|
info.json |
|
|
|
.json |
|
info |
|
C:\Projects\MyApp\data |
3. 경로 결합: Combine
초보자가 가장 자주 하는 실수는 문자열 덧셈으로 경로를 만드는 것입니다. 그러지 맙시다!
틀린 코드 예시:
// 오류 유발 가능!
string fullPath = "C:\\Projects\\MyApp\\" + "data\\info.json";
슬래시를 깜빡하거나 구분자를 잘못 쓰면? 정답은 Path.Combine을 사용하는 겁니다.
string folder = @"C:\Projects\MyApp";
string filename = "data\\info.json";
string fullPath = Path.Combine(folder, filename);
// 어떤 플랫폼에서도 경로 조각을 올바르게 합칩니다!
Console.WriteLine(fullPath); // C:\Projects\MyApp\data\info.json
상대경로와 함께 사용하기
상대 경로를 건네줘도 Path.Combine이 잘 처리합니다. 경로를 조각으로 분리해서 전달하세요!
string baseDir = "C:/work";
string subDir = "docs";
string file = "readme.txt";
string path = Path.Combine(baseDir, subDir, file);
// 결과: "C:/work/docs/readme.txt" (또는 플랫폼에 따라 역슬래시)
팁: 내부적으로 Path.Combine은 현재 OS에 맞는 구분자를 사용합니다. Windows는 \, Linux/Mac은 /. 덕분에 코드가 자동으로 크로스플랫폼 호환성이 생깁니다.
4. 경로 유효성 검사
이를 위해 제공되는 메서드들이 있습니다: GetInvalidPathChars, GetInvalidFileNameChars.
예를 들어 사용자가 UI에 파일 이름이나 경로를 입력했을 때, 문자열에 허용되지 않는 문자가 없는지 확인하려면 Path에게 물어보면 됩니다.
char[] invalidPathChars = Path.GetInvalidPathChars();
char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
string userInput = "data*?.txt";
foreach (char c in userInput)
{
if (Array.Exists(invalidFileNameChars, x => x == c))
{
Console.WriteLine($"파일 이름에 허용되지 않는 문자: {c}");
}
}
// 출력: 파일 이름에 허용되지 않는 문자: *
사용자나 신뢰할 수 없는 소스에서 경로를 받을 때는 특히 중요합니다!
5. 유용한 메서드들
확장자 바꾸기: ChangeExtension
가끔 파일 확장자만 바꿔야 할 때가 있죠. 한 줄이면 충분합니다!
string oldPath = @"C:\data\report.csv";
string newPath = Path.ChangeExtension(oldPath, ".bak");
Console.WriteLine(newPath); // C:\data\report.bak
ChangeExtension은 경로의 나머지 부분은 건드리지 않고 확장자만 교체합니다.
절대 경로 얻기: GetFullPath
상대 경로를 절대 경로로 바꾸고 싶다면 이 메서드를 쓰세요.
string relPath = @"..\..\logs\2024.log";
string absPath = Path.GetFullPath(relPath);
Console.WriteLine(absPath);
// 예: C:\Projects\MyApp\logs\2024.log
실제 결과는 애플리케이션의 현재 작업 디렉터리(Directory.GetCurrentDirectory())에 따라 달라집니다.
경로 구분자: Path.DirectorySeparatorChar
Windows에서는 구분자가 \, Linux에서는 /라는 걸 기억하세요.
직접 하드코딩하지 말고 다음 속성들을 사용합시다:
- Path.DirectorySeparatorChar — 현재 OS의 기본 디렉터리 구분자 ('\\'는 Windows, '/'는 Linux).
- Path.AltDirectorySeparatorChar — 대체 구분자 (Windows에서도 '/'가 동작할 수 있음).
- Path.PathSeparator — 환경 변수 내 경로 구분자 (Windows는 ';', Linux는 ':').
사용 예:
Console.WriteLine(Path.DirectorySeparatorChar); // \ (Windows)
Console.WriteLine(Path.AltDirectorySeparatorChar); // / (Windows)
Console.WriteLine(Path.PathSeparator); // ; (Windows)
직접 디렉터리 순회 루틴을 만들 때 유용합니다.
6. 임시 파일 및 디렉터리 작업
프로그램이 임시 파일을 필요로 할 때가 있습니다 — 중간 결과 저장이나 원자적 업데이트 등에요.
- Path.GetTempPath() — 시스템 임시 파일 폴더의 경로를 반환합니다.
- Path.GetTempFileName() — 고유한 이름의 임시 파일을 만들고 그 경로를 반환합니다.
예제:
string tempDir = Path.GetTempPath();
Console.WriteLine($"임시 파일용 폴더: {tempDir}");
string tempFile = Path.GetTempFileName();
Console.WriteLine($"생성된 임시 파일: {tempFile}");
이 메서드들은 이름 충돌을 막아주고, 어디에 기술적 파일을 둘지 고민할 필요를 줄여줍니다.
7. 자주 하는 실수와 웃긴 케이스들
첫째, 문자열 덧셈으로 경로를 만든다. "아 그냥 folder + "\\\" + file 하면 되지!" 실제로는 이중 슬래시, 누락된 슬래시, Linux에서의 잘못된 구분자 등 골치 아픈 문제를 만듭니다. Path.Combine을 쓰세요.
둘째, 금지된 문자를 잊어버리는 경우. 예: 사용자가 파일 이름에 * («별표»)를 넣으면 예외가 납니다.
셋째, 상대 경로와 절대 경로를 혼동해서 파일을 엉뚱한 곳에서 찾는 경우가 많습니다. 예: "notebook.txt"가 기대한 위치에 없을 수 있습니다.
조언: 경로와 관련된 작업(합치기, 파싱, 확장자 변경, 오류 방어 등)이 필요할 때마다 먼저 스스로에게 물어보세요: "이거 Path의 메서드로 해결되지 않나?" 99% 확률로 이미 Microsoft가 엣지케이스까지 테스트해둔 메서드가 있습니다.
GO TO FULL VERSION