작성자: Rick Anderson
HTML, CSS, 이미지 및 JavaScript와 같은 정적 파일은 기본적으로 ASP.NET Core 앱이 클라이언트에 직접 제공하는 자산입니다.
Blazor 이 문서의 지침을 추가하거나 대체하는 정적 파일 지침은 ASP.NET Core Blazor 정적 파일을 참조하세요.
정적 파일 제공
정적 파일은 프로젝트의 웹 루트 디렉터리 내에 저장됩니다. 기본 디렉터리는 {content root}/wwwroot
이지만, UseWebRoot 메서드를 통해 변경할 수 있습니다. 자세한 내용은 콘텐츠 루트 및 웹 루트를 참조하세요.
CreateBuilder 메서드는 콘텐츠 루트를 현재 디렉터리로 설정합니다.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.MapStaticAssets();
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
정적 파일은 웹 루트에 상대적인 경로를 통해 액세스할 수 있습니다. 예를 들어 웹 애플리케이션 프로젝트 템플릿에는 wwwroot
폴더 내에 여러 폴더가 포함되어 있습니다.
wwwroot
css
js
lib
wwwroot/images/MyImage.jpg
파일이 포함된 앱을 고려합니다.
images
폴더의 파일에 액세스하기 위한 URI 형식은 https://<hostname>/images/<image_file_name>
입니다. 예를 들어 https://localhost:5001/images/MyImage.jpg
정적 자산 라우팅 엔드포인트 규칙 매핑(MapStaticAssets
)
성능이 좋은 웹앱을 만들려면 브라우저에 대한 자산 배달을 최적화해야 합니다. MapStaticAssets의 가능한 최적화는 다음과 같습니다.
- 파일이 변경되거나 브라우저가 캐시를 지울 때까지 지정된 자산을 한 번 제공합니다. ETag 헤더와 Last-Modified 헤더를 설정하세요.
- 앱이 업데이트된 후 브라우저에서 이전 또는 오래된 자료를 사용하지 않도록 합니다. Last-Modified 헤더를 설정합니다.
- 적절한 캐싱 헤더를 설정합니다.
- 캐싱 미들웨어사용합니다.
- 가능하면 압축된 버전의 자산을 제공합니다. 이 최적화에는 축소가 포함되지 않습니다.
- CDN을 사용하여 사용자에게 더 가까운 자산을 제공합니다.
- 지문 자산은 이전 버전의 파일을 다시 사용할 수 없도록.
MapStaticAssets
:
- 빌드 및 게시 프로세스 중에 정적 웹 자산에 대해 수집된 정보를 브라우저에 제공하는 파일을 최적화하기 위해 이 정보를 처리하는 런타임 라이브러리와 통합합니다.
- 앱에서 정적 자산의 배달을 최적화하는 라우팅 엔드포인트 규칙입니다. 페이지 및 MVC를 비롯한 BlazorRazor 모든 UI 프레임워크에서 작동하도록 설계되었습니다.
MapStaticAssets
및 UseStaticFiles
MapStaticAssets 는 .NET 9 이상의 ASP.NET Core에서 사용할 수 있습니다. UseStaticFiles 는 .NET 9 이전 버전에서 사용해야 합니다.
UseStaticFiles
정적 파일을 제공하지만 MapStaticAssets
동일한 수준의 최적화를 제공하지는 않습니다.
MapStaticAssets
는 앱이 런타임 시 알고 있는 자산을 제공하는 데 최적화되어 있습니다. 앱이 디스크 또는 포함된 리소스와 같은 다른 위치에서 자산을 제공하는 경우, UseStaticFiles
를 사용해야 합니다.
Map Static Assets는 UseStaticFiles
호출할 때 사용할 수 없는 다음과 같은 이점을 제공합니다.
- JavaScript(JS) 및 스타일시트를 포함하여 앱의 모든 자산에 대한 빌드 시간 압축이지만 이미 압축된 이미지 및 글꼴 자산은 제외됩니다.
Gzip(
Content-Encoding: gz
) 압축은 개발 중에 사용됩니다. Brotli(Content-Encoding: br
) 압축이 있는 Gzip은 게시 중에 사용됩니다. - 빌드 시 각 파일 콘텐츠의 SHA-256 해시를 Base64로 인코딩된 문자열로 변환하여 모든 자산에 대한 지문을 생성합니다. 이렇게 하면 이전 파일이 캐시된 경우에도 이전 버전의 파일을 다시 사용할 수 없습니다. 지문 자산은
immutable
지시문사용하여 캐시되므로 브라우저에서 변경될 때까지 자산을 다시 요청하지 않습니다.immutable
지시문을 지원하지 않는 브라우저의 경우max-age
지시문 추가됩니다.- 자산이 지문이 아닌 경우에도 파일의 지문 해시를
ETags
값으로 사용하여 각 정적 자산에 대해 콘텐츠 기반ETag
생성됩니다. 이렇게 하면 콘텐츠가 변경되거나 파일이 처음으로 다운로드되는 경우에만 브라우저에서 파일을 다운로드할 수 있습니다. - 내부적으로 프레임워크는 물리적 자산을 지문에 매핑하므로 앱에서 다음을 수행할 수 있습니다.
- 자산이 지문이 아닌 경우에도 파일의 지문 해시를
-
Visual Studio 핫 리로드 개발 테스트 중:
- 앱이 실행되는 동안 파일이 변경되는 문제를 방지하기 위해 자산에서 무결성 정보가 제거됩니다.
- 정적 자산은 브라우저가 항상 현재 콘텐츠를 검색하도록 캐시되지 않습니다.
맵 정적 자산은 축소 또는 기타 파일 변환을 위한 기능을 제공하지 않습니다. 축소는 일반적으로 사용자 지정 코드 또는 타사 도구의해 처리됩니다.
다음 기능은 UseStaticFiles
지원되지만 MapStaticAssets
지원되지는 않습니다.
- 디스크, 포함된 리소스 또는 기타 위치에서 파일을 제공
- 웹 루트 외부의 파일 제공
- HTTP 응답 헤더 설정
- 디렉터리 검색
- 기본 문서 제공
FileExtensionContentTypeProvider
- 여러 위치에서 파일 제공
- 디스크, 포함된 리소스 또는 기타 위치에서 파일을 제공
- 웹 루트 외부의 파일 제공
- HTTP 응답 헤더 설정
- 디렉터리 검색
- 기본 문서 제공
FileExtensionContentTypeProvider
- 여러 위치에서 파일 제공
웹 루트의 파일 제공
기본 웹앱 템플릿은 MapStaticAssets에서 Program.cs
메서드를 호출하여 정적 파일을 제공할 수 있습니다.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.MapStaticAssets();
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
매개 변수가 없는 MapStaticAssets
메서드 오버로드는 웹 루트에 있는 파일을 제공 가능으로 표시합니다. 다음 마크업 참조는 wwwroot/images/MyImage.jpg
입니다.
<img src="~/images/MyImage.jpg" class="img" alt="My image" />
위의 태그에서 물결표 문자(~
)는 웹 루트를 가리킵니다.
웹 루트 외부의 파일 제공
제공할 정적 파일이 웹 루트 외부에 있는 디렉터리 계층 구조를 고려해보세요.
wwwroot
css
images
js
MyStaticFiles
images
red-rose.jpg
요청은 정적 파일 미들웨어를 다음과 같이 구성하여 red-rose.jpg
파일에 액세스할 수 있습니다.
using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles(); //Serve files from wwwroot
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
RequestPath = "/StaticFiles"
});
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
위의 코드에서 MyStaticFiles 디렉터리 계층 구조는 StaticFiles URI 세그먼트를 통해 공개적으로 노출됩니다.
https://<hostname>/StaticFiles/images/red-rose.jpg
에 대한 요청은 red-rose.jpg
파일을 제공합니다.
다음 마크업 참조는 MyStaticFiles/images/red-rose.jpg
입니다.
<img src="~/StaticFiles/images/red-rose.jpg" class="img" alt="A red rose" />
여러 위치에서 파일을 제공하려면 여러 위치에서 파일 제공을 참조하세요.
HTTP 응답 헤더 설정
StaticFileOptions 개체를 사용하여 HTTP 응답 헤더를 설정할 수 있습니다. 다음 코드는 웹 루트에서 제공되는 정적 파일을 구성하는 것 외에도 Cache-Control 헤더를 설정합니다.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
var cacheMaxAgeOneWeek = (60 * 60 * 24 * 7).ToString();
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
ctx.Context.Response.Headers.Append(
"Cache-Control", $"public, max-age={cacheMaxAgeOneWeek}");
}
});
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
위의 코드는 정적 파일을 1주일 동안 로컬 캐시에서 공개적으로 사용할 수 있도록 합니다.
정적 파일 권한 부여
ASP.NET Core 템플릿은 MapStaticAssets을 호출하기 전에 UseAuthorization를 호출합니다. 대부분의 앱은 이 패턴을 따릅니다. 권한 부여 미들웨어 전에 MapStaticAssets
호출되는 경우:
- 정적 파일에서 권한 부여 검사가 수행되지 않습니다.
-
wwwroot
아래에 있는 정적 파일과 같이 정적 파일 미들웨어가 제공하는 정적 파일은 공개적으로 액세스할 수 있습니다.
권한 부여에 따라 정적 파일을 제공하려면 정적 파일 권한 부여참조하세요.
여러 위치에서 파일 제공
Razor 파일을 표시하는 다음 /MyStaticFiles/image3.png
페이지를 고려하세요.
@page
<p> Test /MyStaticFiles/image3.png</p>
<img src="~/image3.png" class="img" asp-append-version="true" alt="Test">
UseStaticFiles
및 UseFileServer
는 기본적으로 wwwroot
를 가리키는 파일 공급자로 설정됩니다. 다른 위치에서 파일을 제공하기 위해 다른 파일 공급자와 UseStaticFiles
및 UseFileServer
의 추가 인스턴스를 제공할 수 있습니다. 다음 예제에서는 UseStaticFiles
를 두 번 호출하여 wwwroot
및 MyStaticFiles
모두에서 파일을 제공합니다.
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles"))
});
위의 코드를 사용하여 다음을 수행합니다.
-
/MyStaticFiles/image3.png
파일이 표시됩니다. 이미지 태그 도우미 는에 의존 하기 때문에 적용되지 않습니다. WebRootFileProvider
폴더를 포함하도록MyStaticFiles
가 업데이트되지 않았습니다.
다음 코드는 WebRootFileProvider
를 업데이트하여 이미지 태그 도우미가 버전을 제공할 수 있도록 합니다.
var webRootProvider = new PhysicalFileProvider(builder.Environment.WebRootPath);
var newPathProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles"));
var compositeProvider = new CompositeFileProvider(webRootProvider,
newPathProvider);
// Update the default provider.
app.Environment.WebRootFileProvider = compositeProvider;
app.MapStaticAssets();
비고
이전 방법은 Pages 및 MVC 앱에 Razor 적용됩니다. Blazor Web App에 적용되는 지침은 ASP.NET Core Blazor 정적 파일을 참조하세요.
IWebHostEnvironment.WebRootPath를 업데이트하여 wwwroot 외부의 파일 제공
IWebHostEnvironment.WebRootPath가 wwwroot
이외의 폴더로 설정된 경우:
- 개발 환경에서는
wwwroot
및 업데이트된IWebHostEnvironment.WebRootPath
모두에서 찾은 정적 자산이wwwroot
에서 제공됩니다. - 개발 환경 이외의 환경에서는 중복된 정적 자산이 업데이트된
IWebHostEnvironment.WebRootPath
폴더에서 제공됩니다.
빈 웹 템플릿으로 만든 웹앱을 고려합니다.
Index.html
및wwwroot
의wwwroot-custom
파일 포함업데이트된
Program.cs
파일과 함께WebRootPath = "wwwroot-custom"
을 설정합니다.var builder = WebApplication.CreateBuilder(new WebApplicationOptions { Args = args, // Look for static files in "wwwroot-custom" WebRootPath = "wwwroot-custom" }); var app = builder.Build(); app.UseDefaultFiles(); app.MapStaticAssets(); app.Run();
위의 코드에서 /
에 대한 요청은
- 개발 환경에서는
wwwroot/Index.html
을 반환합니다. - 개발 환경 이외의 환경에서는
wwwroot-custom/Index.html
을 반환합니다.
wwwroot-custom
의 자산이 반환되도록 하려면 다음 방법 중 하나를 사용합니다.
wwwroot
에서 중복 명명된 자산을 삭제합니다."ASPNETCORE_ENVIRONMENT"
에서Properties/launchSettings.json
를"Development"
이외의 값으로 설정합니다.프로젝트 파일에서
<StaticWebAssetsEnabled>false</StaticWebAssetsEnabled>
를 설정하여 정적 웹 자산을 완전히 사용하지 않도록 설정합니다. 경고, 정적 웹 자산을 사용하지 않도록 설정하면 Razor 클래스 라이브러리를 사용할 수 없습니다.프로젝트 파일에 다음 XML을 추가합니다.
<ItemGroup> <Content Remove="wwwroot\**" /> </ItemGroup>
다음 코드에서는 IWebHostEnvironment.WebRootPath
를 개발이 아닌 값으로 업데이트하여 중복 콘텐츠가 wwwroot-custom
가 아니라 wwwroot
에서 반환되도록 합니다.
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Examine Hosting environment: logging value
EnvironmentName = Environments.Staging,
WebRootPath = "wwwroot-custom"
});
var app = builder.Build();
app.Logger.LogInformation("ASPNETCORE_ENVIRONMENT: {env}",
Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"));
app.Logger.LogInformation("app.Environment.IsDevelopment(): {env}",
app.Environment.IsDevelopment().ToString());
app.UseDefaultFiles();
app.MapStaticAssets();
app.Run();
추가 리소스
ASP.NET Core