1. 도입
파일이나 폴더 존재 여부를 확인하는 게 왜 중요할까?
일기를 쓰는 기능을 만든다고 가정해봅시다. 애플리케이션에서 파일 끝에 항목을 추가하는 기능이 있다고 할 때, 파일이 존재하면 문제없지만 파일이 우연히 삭제되어 있으면 프로그램은 예외를 던지고 당신의 인생 철학이나, 적당히, 날씨에 대한 모든 재치 있는 문구가 흔적도 없이 사라질 수 있습니다. 비슷하게, 새 파일을 만들 때 기존 파일이 없는지 확인하는 건 데이터를 잃지 않기 위해 중요합니다.
실제 애플리케이션—특히 기업용이나 산업용 개발에서—파일과 폴더 존재 여부를 미리 체크하면 사용자 실수나 치명적 장애를 피할 수 있고, 팀의 시간과 노력을 절약하며, 무엇보다 불필요한 골칫거리를 줄여 줍니다.
.NET에서 파일 시스템 다루기
.NET 플랫폼에서 파일과 폴더 작업에 유용한 기본 클래스들은 다음과 같습니다(이들은 System.IO 네임스페이스에 있습니다):
존재 여부 확인에는 두 가지 메서드면 충분합니다:
- File.Exists(path) — 파일이 존재하면 true를 반환합니다.
- Directory.Exists(path) — 폴더가 존재하면 true를 반환합니다.
2. 파일을 열기 전에 존재 여부 확인
실생활 예제
일기 내용을 보여주는 기능을 추가했다고 합시다:
string diaryPath = "diary.txt";
if (File.Exists(diaryPath))
{
// 파일이 존재하므로 읽어서 출력
using var reader = new StreamReader(diaryPath);
string content = reader.ReadToEnd();
Console.WriteLine("당신의 일기:\n" + content);
}
else
{
Console.WriteLine("일기 파일을 찾을 수 없습니다!");
// 필요하면 새 파일을 바로 생성할 수 있습니다
File.WriteAllText(diaryPath, "이것은 당신의 일기의 시작입니다.\n");
Console.WriteLine("새 일기 파일이 생성되었습니다.");
}
실제 프로젝트에서 이런 방식은 필수적입니다: '기적'에 기대지 않고 스스로 상황을 제어합니다.
3. 파일에 쓰기 전에 존재 여부 확인
시나리오: 애플리케이션이 스케줄에 따라 리포트를 생성합니다. 새 리포트가 이전 리포트를 덮어쓰지 않도록 해야 합니다.
이를 위해 파일이 이미 있는지 확인하는 것이 유용합니다. 만약 있다면 사용자가 다른 이름을 입력하게 하거나 고유한 이름으로 파일을 생성할 수 있습니다.
string reportPath = "report.txt";
if (File.Exists(reportPath))
{
Console.WriteLine($"파일 '{reportPath}'이(가) 이미 존재합니다. 오래된 파일을 삭제하거나 이름을 바꿔주세요.");
}
else
{
using var writer = new StreamWriter(reportPath);
writer.WriteLine("이것은 오늘의 새 리포트입니다!");
Console.WriteLine("리포트 파일이 성공적으로 생성되었습니다.");
}
이런 확인은 사용자(그리고 당신 자신)를 덮어쓰여진 파일 같은 불쾌한 놀라움으로부터 보호합니다.
4. 쓰기 전에 폴더 존재 여부 확인
파일은 프로젝트 루트에 바로 놓이는 경우가 드뭅니다. 보통 logs/, reports/, data/ 같은 전용 디렉터리에 넣습니다. 파일을 쓰기 전에 해당 폴더가 있는지 확인해야 합니다.
string logsDir = "logs";
string logPath = Path.Combine(logsDir, "log.txt"); // Path.Combine은 경로 조합을 안전하게 도와줍니다
if (!Directory.Exists(logsDir))
{
Console.WriteLine("폴더 'logs'를 찾을 수 없습니다. 생성합니다...");
Directory.CreateDirectory(logsDir);
}
using var writer = new StreamWriter(logPath, append: true);
writer.WriteLine($"[{DateTime.Now}] 애플리케이션이 시작되었습니다.");
Console.WriteLine("로그 파일에 기록이 성공적으로 이루어졌습니다.");
참고로 Directory.CreateDirectory는 폴더가 이미 있어도 예외를 던지지 않습니다 — 그냥 무시하므로, 이런 스타일이 괜찮으면 명시적 체크를 생략해도 됩니다.
5. 중요한 뉘앙스
특성: 상대경로와 절대경로
초보자가 자주 하는 실수는 상대경로와 절대경로를 혼동하는 것입니다. 예를 들어 File.Exists("data.txt")를 쓰면 프로그램은 현재 작업 디렉터리에서 파일을 찾습니다. 그 현재 작업 디렉터리가 어디냐는? 애플리케이션이 어디서 실행되었는지에 따라 다릅니다.
안정성을 위해 절대경로를 사용하거나 Path.Combine으로 경로를 구성하세요:
string myDocs = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string filePath = Path.Combine(myDocs, "myapp", "settings.txt");
경로를 명시적으로 지정하면 파일을 잃어버릴 위험이 줄어듭니다.
체크 시의 중요한 디테일
- 가끔 존재 여부를 체크한 다음 같은 파일/폴더에 대해 즉시 추가 동작을 합니다. File.Exists와 그 이후 생성/삭제 사이에 시간이 흐르며 다른 프로세스가 상태를 바꿀 수 있습니다. 중요한 시나리오에서는 try-catch로 예외 처리를 추가하세요.
- 존재 여부뿐 아니라 접근 권한도 확인하세요. 파일은 있어도 사용자가 접근 권한이 없을 수 있습니다.
- 디렉터리 검사에는 Directory.Exists를 사용하고, File.Exists를 사용하지 마세요 — 그러면 항상 false가 됩니다.
- 경로가 여러 중첩 디렉터리로 구성된 경우, 예를 들어 "data/2024/04"처럼, Directory.CreateDirectory("data/2024/04")는 전체 체인을 생성합니다 — 편리하고 불필요한 체크를 줄여줍니다.
만약 확인을 하지 않는다면?
존재하지 않는 파일을 읽으려고 하면 FileNotFoundException이 발생합니다. 존재하지 않는 폴더에 파일을 만들려고 하면 DirectoryNotFoundException이 발생합니다. 프로그램이 일반 사용자 권한으로 실행된다면 사용자는 오류를 보고 불만을 가질 것입니다. 산업 환경에서는 데이터/돈/시간을 잃을 수 있습니다. 그래서 '존재 여부 확인'은 귀찮은 짓이 아니라 사용자(그리고 자신의 정신 건강)를 위한 배려입니다.
GO TO FULL VERSION