-
[C#] "파일을 찾을 수 없습니다" – FileNotFoundException, 경로의 함정개발/C# 2026. 1. 22. 14:59반응형
안녕하세요!
프로그램을 만들다 보면 텍스트 파일을 읽거나, 설정값(JSON, XML)을 불러오고, 또 연구용 **이미지(PCB 기판 등)**를 로드할 일이 정말 많죠. 그런데 로컬에서는 잘 되던 게 배포만 하면, 혹은 디버깅만 시작하면 **FileNotFoundException**을 뿜어내며 멈출 때가 있습니다.
"내 눈앞에 파일이 있는데 왜 못 찾는다는 거야!"라고 외치고 싶은 분들을 위해, 오늘은 이 에러의 원인과 **'절대 안 틀리는 경로 설정법'**을 정리해 드립니다.
1. 왜 못 찾는 걸까요? (범인은 '작업 디렉터리')
C#에서 파일을 찾을 때 가장 많이 하는 실수가 바로 **상대 경로(.\data.txt)**를 믿는 것입니다.
우리는 비주얼 스튜디오에서 코딩을 하지만, 실제 프로그램이 실행되는 곳은 프로젝트 폴더가 아니라 bin\Debug\net8.0 같은 깊숙한 곳입니다.
- 내가 생각하는 위치: Project/data.txt
- 실제 프로그램 실행 위치: Project/bin/Debug/net8.0/
프로그램은 자기 실행 위치를 기준으로 파일을 찾기 때문에, 원본 폴더에 있는 파일은 당연히 못 찾게 되는 거죠.
2. 실전 해결법: 상황별 '무적' 경로 만들기
방법 1: 비주얼 스튜디오 설정 활용 (가장 추천!)
파일을 매번 복사할 필요 없이, 빌드할 때마다 자동으로 실행 폴더로 옮겨지게 설정하세요.
- 파일 우클릭 → 속성 클릭
- 출력 디렉터리로 복사 항목을 '새로 만들기 제어' 또는 **'항상 복사'**로 변경
이렇게 하면 프로그램 실행 위치에 항상 파일이 따라다니므로 에러 날 일이 없습니다.
방법 2: 실행 경로를 직접 가져오기
코드 안에서 "내 실행 파일이 어디 있지?"를 물어보고 그 위치를 기준으로 경로를 합치는 방법입니다.
// 현재 실행 중인 프로그램의 폴더 경로를 가져옵니다. string baseDir = AppDomain.CurrentDomain.BaseDirectory; // Path.Combine을 쓰면 역슬래시(\) 문제를 신경 쓸 필요가 없습니다. string filePath = Path.Combine(baseDir, "data", "config.json"); if (File.Exists(filePath)) { string content = File.ReadAllText(filePath); Console.WriteLine("성공적으로 읽었습니다!"); }3. 경로 꿀팁
① Directory.GetCurrentDirectory()는 믿지 마세요
이 함수는 '현재 작업 디렉터리'를 가져오는데, 사용자가 바탕화면에서 바로 가기로 실행하거나 관리자 권한으로 실행하면 엉뚱한 곳(예: C:\Windows\System32)을 가리킬 때가 있습니다. 파일 찾을 땐 무조건 **AppDomain.CurrentDomain.BaseDirectory**를 쓰세요.
② Path.Combine은 선택이 아닌 필수
경로를 합칠 때 "data\\" + "file.txt" 처럼 직접 문자열을 더하지 마세요. OS마다 경로 구분자가 다를 수도 있고, 슬래시 개수 때문에 에러가 나기 쉽습니다. **Path.Combine**은 이 모든 걸 완벽하게 처리해 줍니다.
③ 파일이 있는지 '먼저' 물어보기
if (!File.Exists(path)) { // 에러를 터뜨리기 전에 로그를 남기거나 사용자에게 친절하게 알려주세요. Console.WriteLine($"[경고] {path} 위치에 파일이 없네요. 경로를 확인해 주세요!"); return; }마무리하며
**FileNotFoundException**은 사실 컴퓨터가 "나 어디서부터 찾아야 할지 모르겠어!"라고 도움을 요청하는 신호입니다. 오늘 알려드린 '실행 디렉터리' 개념과 Path.Combine만 잘 활용해도 경로 문제로 밤샐 일은 사라질 거예요.
혹시 여러분도 경로 때문에 삽질했던 웃픈(?) 기억이 있으신가요? 댓글로 공유해 주세요. 같이 웃으며 이겨냅시다! ㅎㅎ
반응형'개발 > C#' 카테고리의 다른 글
C# 인터페이스를 활용한 의존성 주입(DI) 완벽 이해 (0) 2026.01.23 C# 설계의 핵심: 인터페이스 vs 추상 클래스, 5분 만에 끝내는 완벽 비교 (0) 2026.01.23 [C#] Struct vs Class, 성능 차이 진짜 날까? (언제 무엇을 쓸지 정해드립니다) (0) 2026.01.20 C# foreach 돌리다 터지는 '열거 작업 수정' 에러, 해결 가이드Enumerable was modified (0) 2026.01.19 [C#] WinForms "크로스 스레드 작업이 잘못되었습니다" (0) 2026.01.15