물리 경로 (Physical Path)
// Server.MapPath()로 변환
string physicalPath = Server.MapPath("~/Content/Data");
// 결과: C:\Projects\MyApp\Content\Data
// 사용: 파일 시스템 작업
Directory.CreateDirectory(physicalPath);
File.WriteAllBytes(Path.Combine(physicalPath, "file.xlsx"), bytes);
File.Delete(Path.Combine(physicalPath, "file.xlsx"));
특징:
- 실제 디스크 경로
- 운영체제 파일 시스템이 이해하는 경로
- C#의 File, Directory 클래스가 사용
가상 경로 (Virtual Path)
// 웹 URL 경로
string virtualPath = "/Content/Data/file.xlsx";
// 사용: 다운로드 링크
return Json(new { Data = virtualPath });
특징:
- 웹 서버가 이해하는 경로
- 브라우저가 접근하는 경로
- 도메인 + 가상 경로 = 완전한 URL
분리해서 사용하는 이유
1. 역할이 다름
// 물리 경로로 다운로드 링크 만들면?
string physicalPath = "C:\\Projects\\MyApp\\Content\\file.xlsx";
return Json(new { Data = physicalPath });
// JavaScript에서
window.location.href = "C:\\Projects\\MyApp\\Content\\file.xlsx";
// 브라우저는 이걸 이해 못 함!
// 로컬 파일 시스템 접근은 보안상 차단됨! (브라우저에서 PC로 접근하려는 모습)
// 가상 경로로 다운로드 링크
string virtualPath = "/Content/file.xlsx";
return Json(new { Data = virtualPath });
// JavaScript에서
window.location.href = "/Content/file.xlsx";
// 브라우저가 이해 할수 있는 경로!
// 실제 요청: http://localhost/Content/file.xlsx
// 실행되고 있는 프로젝트 경로로 접근
2. 서버 환경마다 물리 경로가 다름
개발 서버: C:\Projects\MyApp\Content\file.xlsx
스테이징: D:\WebApps\MyApp\Content\file.xlsx
운영 서버: E:\inetpub\wwwroot\MyApp\Content\file.xlsx
가상 경로는 모든 환경에서 동일: /Content/file.xlsx
물리 경로는 환경마다 다름
3. 보안
// 물리 경로 노출 위험
return Json(new { Data = "C:\\Projects\\MyApp\\Content\\file.xlsx" });
// 사용자가 서버 구조를 알게 됨!(PC 경로 구성을 외부에 보이게됨)
// 가상 경로는 안전
return Json(new { Data = "/Content/file.xlsx" });
// 서버 구조는 숨겨짐
동작 원리
1. 파일 저장 (물리 경로)
// Step 1: 물리 경로 얻기
string physicalPath = Server.MapPath("~/Content/Data");
// C:\Projects\MyApp\Content\Data
// Step 2: 파일 시스템에 저장
File.WriteAllBytes(Path.Combine(physicalPath, "file.xlsx"), bytes);
// C:\Projects\MyApp\Content\Data\file.xlsx 생성
물리 경로를 사용하는 이유
- File.WriteAllBytes()는 운영체제 API 호출
- 운영체제는 물리 경로만 이해함
- /Content/file.xlsx 같은 가상 경로는 이해 못 함(브라우저 접근용)
2. 다운로드 링크 (가상 경로)
// Step 1: 가상 경로 생성
string virtualPath = "/Content/Data/file.xlsx";
// Step 2: 클라이언트에 전달
return Json(new { Data = virtualPath });
window.location.href = "/Content/Data/file.xlsx";
// 브라우저가 요청: http://localhost/Content/Data/file.xlsx
//서버에서 (IIS/ASP.NET):**
1. 요청 받음: GET /Content/GoodsSelectJson/file.xlsx
2. 가상 경로를 물리 경로로 변환: C:\Projects\MyApp\Content\Data\file.xlsx
3. 파일 읽기
4. 응답 전송
예시
// Controllers/PresentController.cs
public ActionResult PresentInfomation(...)
{
// 1. 물리 경로로 파일 저장
string physicalFolder = Server.MapPath("~/Content/Present");
// C:\Projects\MyApp\Content\Present
if (!Directory.Exists(physicalFolder))
{
Directory.CreateDirectory(physicalFolder);
// 물리 폴더 생성: C:\Projects\MyApp\Content\Present
}
string fileName = "items_20241126.xlsx";
string physicalFilePath = Path.Combine(physicalFolder, fileName);
// C:\Projects\MyApp\Content\Present\items_20241126.xlsx
File.WriteAllBytes(physicalFilePath, excelBytes);
// 운영체제 파일 시스템에 저장
// 2. 가상 경로로 다운로드 링크 생성
string virtualPath = $"/Content/Present/{fileName}";
// /Content/Present/items_20241126.xlsx
return Json(new
{
Success = true,
Data = virtualPath // 가상 경로 반환
});
}
// JavaScript
$.ajax({
success: function(result) {
// result.Data = "/Content/Present/items_20241126.xlsx"
// 3. 브라우저가 다운로드 요청
window.location.href = result.Data;
// 실제 요청: http://localhost/Content/Present/items_20241126.xlsx
}
});
```
```
4. IIS/ASP.NET 처리(자동으로 됨)
요청: GET /Content/Present/items_20241126.xlsx
IIS:
- 가상 경로: /Content/Present/items_20241126.xlsx
- 물리 경로 변환: C:\Projects\MyApp\Content\Present\items_20241126.xlsx
- 파일 읽기
- 응답 전송 (파일 다운로드)
파일 삭제
// Controller
[HttpPost]
public ActionResult DeleteTemporaryFile(string fileUrl)
{
// fileUrl = "/Content/Present/file.xlsx" (가상 경로)
// 가상 경로를 물리 경로로 변환
string physicalPath = Server.MapPath("~" + fileUrl);
// C:\Projects\MyApp\Content\Present\file.xlsx
// 물리 경로로 삭제
if (File.Exists(physicalPath))
{
File.Delete(physicalPath);
}
return Json(new { Success = true });
}
만약 IIS가 없다면?
// 이렇게 직접 구현해야 함
public ActionResult DownloadFile(string fileName)
{
// 가상 경로를 물리 경로로 변환
string physicalPath = Server.MapPath($"~/Content/Present/{fileName}");
if (!File.Exists(physicalPath))
{
return HttpNotFound();
}
// 파일 읽기
byte[] fileBytes = File.ReadAllBytes(physicalPath);
// 파일 전송
return File(fileBytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileName);
}
// 사용
// window.location.href = "/Present/DownloadFile?fileName=file.xlsx";
비교표
| 항목 | 물리 경로 | 가상 경로 |
| 예시 | C:\Projects\MyApp\Content\file.xlsx | /Content/file.xlsx |
| 사용 대상 | 파일 시스템 (C#) | 웹 서버 (브라우저) |
| 사용 시점 | 파일 생성/삭제/읽기 | 다운로드 링크/URL |
| 환경 의존성 | 환경마다 다름 | 모든 환경 동일 |
| 보안 | 서버 구조 노출 | 안전 |
| 브라우저 접근 | 불가능 | 가능 |
| File.WriteAllBytes | 가능 | 불가능 |
| window.location | 불가능 | 가능 |
'C# > 이모저모' 카테고리의 다른 글
| WebSocket 채팅 시스템 (0) | 2026.03.22 |
|---|---|
| WebSocket (0) | 2026.03.22 |
| 웹 애플리케이션(.NET) (0) | 2025.11.30 |
| 임시 파일 자동정리(.NET TimerQueue & .NET IHostedService) (0) | 2025.11.27 |
| IIS(Internet Information Services) (0) | 2025.11.27 |