ASP.NET Core의 응답 캐싱

작성자: Rick AndersonKirk Larkin

샘플 코드 보기 및 다운로드(다운로드 방법)

응답 캐싱은 클라이언트 또는 프록시가 웹 서버에 대해 수행하는 요청 수를 줄입니다. 또한 응답 캐싱은 웹 서버에서 응답을 생성하기 위해 수행하는 작업의 양을 줄입니다. 응답 캐싱은 헤더에 설정됩니다.

ResponseCache 특성은 응답 캐싱 헤더를 설정합니다. 클라이언트 및 중간 프록시는 RFC 9111: HTTP 캐싱에 따라 응답을 캐시하는 데 헤더를 적용해야 합니다.

HTTP 1.1 캐싱 사양을 따르는 서버 쪽 캐싱의 경우 응답 캐싱 미들웨어를 사용합니다. 미들웨어는 ResponseCacheAttribute 속성을 사용하여 서버 쪽 캐싱 동작에 영향을 줄 수 있습니다.

응답 캐싱 미들웨어:

  • HTTP 캐시 헤더를 기반으로 서버 응답을 캐싱할 수 있도록 합니다. 표준 HTTP 캐싱 의미 체계를 구현합니다. 프록시처럼 HTTP 캐시 헤더에 기반하여 캐시합니다.
  • 브라우저는 일반적으로 캐싱을 방지하는 요청 헤더를 설정하기 때문에 Razor Pages와 같은 UI 앱에는 일반적으로 도움이 되지 않습니다. ASP.NET Core 7.0 이상에서 사용할 수 있는 출력 캐싱은 UI 앱에 이점을 제공합니다. 출력 캐싱을 사용하여 구성에서 HTTP 헤더와 독립적으로 캐시할 내용을 결정합니다.
  • 캐싱 조건이 충족되는 클라이언트의 퍼블릭 GET 또는 HEAD API 요청에 도움이 될 수 있습니다.

응답 캐싱을 테스트하려면 Fiddler 또는 요청 헤더를 명시적으로 설정할 수 있는 다른 도구를 사용합니다. 헤더를 명시적으로 설정하는 것은 캐싱을 테스트하는 데 선호됩니다. 자세한 내용은 문제 해결을 참조하십시오.

HTTP 기반 응답 캐싱

RFC 9111: HTTP 캐싱은 인터넷 캐시의 작동 방식을 설명합니다. 캐싱에 사용되는 기본 HTTP 헤더는 캐시 지시문을 지정하는 데 사용되는 Cache-Control입니다. 지시문은 요청이 클라이언트에서 서버로 이동하고 서버에서 클라이언트로 다시 이동하는 방식으로 캐싱 동작을 제어합니다. 요청 및 응답은 프록시 서버를 통해 이동하고, 프록시 서버는 HTTP 1.1 캐싱 사양을 준수해야 합니다.

다음 표에는 일반적인 Cache-Control 지시문이 나와 있습니다.

지시문 작업
public 캐시에서 응답을 저장할 수 있습니다.
private 응답은 공유 캐시에 저장되지 않아야 합니다. 개인 캐시는 응답을 저장하고 다시 사용할 수 있습니다.
max-age 클라이언트는 나이가 지정된 시간(초)보다 큰 응답을 수락하지 않습니다. 예: max-age=60(60초), max-age=2592000(1달)
no-cache 요청 시: 캐시가 저장된 응답을 사용하여 요청을 충족해서는 안 됩니다. 원본 서버는 클라이언트에 대한 응답을 다시 생성하고 미들웨어는 해당 캐시에 저장된 응답을 업데이트합니다.

응답 시: 원본 서버에서 유효성 검사 없이 후속 요청에 대한 응답을 사용하지 않아야 합니다.
no-store 요청 시: 캐시에서 요청을 저장하지 않아야 합니다.

응답 시: 캐시가 응답의 일부를 저장하지 않아야 합니다.

캐싱에서 역할을 수행하는 다른 캐시 헤더가 다음 표에 나와 있습니다.

헤더 함수
Age 응답을 생성하거나 원본 서버에서 유효성을 검사한 이후의 예상 시간(초)입니다.
만료 응답이 오래된 것으로 간주되는 시간입니다.
Pragma no-cache 동작 설정에 대한 HTTP/1.0 캐시와 이전 버전과의 호환성을 위해 존재합니다. Cache-Control 헤더가 있으면 Pragma 헤더는 무시됩니다.
Vary 캐시된 응답의 원래 요청과 새 요청 모두에서 Vary 헤더 필드가 모두 일치하지 않는 경우 캐시된 응답을 보내지 않도록 지정합니다.

HTTP 기반 캐싱은 요청 Cache-Control 지시문을 사용합니다.

RFC 9111: HTTP 캐싱(섹션 5.2. Cache-Control)은 클라이언트에서 보낸 유효한 Cache-Control 헤더를 적용하는 데 캐시가 필요합니다. 클라이언트는 no-cache 헤더 값을 사용하여 요청을 수행하고 서버에서 모든 요청에 대해 새 응답을 생성하도록 강제할 수 있습니다.

HTTP 캐싱의 목표를 고려하는 경우 항상 클라이언트 Cache-Control 요청 헤더를 적용하는 것이 좋습니다. 공식 사양에서 캐싱은 클라이언트, 프록시 및 서버의 네트워크에서 요청을 충족하는 대기 시간 및 네트워크 오버 헤드를 줄이기 위한 것입니다. 원본 서버에서 로드를 제어하기 위해 반드시 필요한 방법은 아닙니다.

미들웨어가 공식 캐싱 사양을 준수하기 때문에 응답 캐싱 미들웨어를 사용하는 경우 이 캐싱 동작에 대한 개발자 제어는 없습니다. 서버 부하를 더 효율적으로 제어하기 위한 출력 캐싱 지원이 .NET 7에 추가되었습니다. 자세한 내용은 출력 캐싱을 참조 하세요.

ResponseCache 특성

ResponseCacheAttribute는 응답 캐싱에 적절한 헤더를 설정하는 데 필요한 매개 변수를 지정합니다.

Warning

인증된 클라이언트에 대한 정보가 포함된 콘텐츠에 대해 캐싱을 사용하지 않도록 설정합니다. 사용자의 ID에 따라 변경되지 않는 콘텐츠나 사용자의 로그인 여부에 따라서만 캐싱을 사용하도록 설정해야 합니다.

VaryByQueryKeys는 지정된 쿼리 키의 목록 값에 따라 저장된 응답을 변경합니다. *의 단일 값이 제공되면 미들웨어는 모든 요청 쿼리 문자열 매개 변수에 따라 다양한 응답을 제공합니다.

VaryByQueryKeys 속성을 설정하려면 응답 캐싱 미들웨어를 사용하도록 설정해야 합니다. 그렇지 않으면 런타임 예외가 throw됩니다. VaryByQueryKeys 속성에 해당하는 HTTP 헤더가 없습니다. 속성은 응답 캐싱 미들웨어에 의해 처리되는 HTTP 기능입니다. 미들웨어가 캐시된 응답을 제공하려면 쿼리 문자열 및 쿼리 문자열 값이 이전 요청과 일치해야 합니다. 예를 들어 다음 표의 요청 및 결과 시퀀스를 살펴보세요.

요청 반환한 위치
http://example.com?key1=value1 서버
http://example.com?key1=value1 미들웨어
http://example.com?key1=NewValue 서버

첫 번째 요청은 서버에서 반환되고 미들웨어에 캐시됩니다. 쿼리 문자열이 이전 요청과 일치하기 때문에 두 번째 요청은 미들웨어에서 반환됩니다. 쿼리 문자열 값이 이전 요청과 일치하지 않으므로 세 번째 요청이 미들웨어 캐시에 없습니다.

ResponseCacheAttribute를 통해 Microsoft.AspNetCore.Mvc.Internal.ResponseCacheFilter를 구성하고 만드는 데(IFilterFactory를 통해) 사용됩니다. ResponseCacheFilter는 응답의 적절한 HTTP 헤더 및 기능을 업데이트하는 작업을 수행합니다. 필터:

  • Vary, Cache-ControlPragma에 대한 기존 헤더를 제거합니다.
  • ResponseCacheAttribute에 설정된 속성에 따라 적절한 헤더를 작성합니다.
  • VaryByQueryKeys가 설정된 경우 응답 캐싱 HTTP 기능을 업데이트합니다.

Vary

이 헤더는 VaryByHeader 속성이 설정된 경우에만 기록됩니다. 속성이 Vary 속성의 값으로 설정됩니다. 다음 샘플에서는 VaryByHeader 속성을 사용합니다.

[ApiController]
public class TimeController : ControllerBase
{
    [Route("api/[controller]")]
    [HttpGet]
    [ResponseCache(VaryByHeader = "User-Agent", Duration = 30)]
    public ContentResult GetTime() => Content(
                      DateTime.Now.Millisecond.ToString());

Fiddler 또는 다른 도구를 사용하여 응답 헤더를 봅니다. 응답 헤더에는 다음이 포함됩니다.

Cache-Control: public,max-age=30
Vary: User-Agent

이전 코드는 응답 캐싱 미들웨어 서비스 AddResponseCaching을 서비스 컬렉션에 추가해야 하고 UseResponseCaching 확장 메서드와 함께 미들웨어를 사용하도록 앱을 구성합니다.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddResponseCaching();

var app = builder.Build();

app.UseHttpsRedirection();

// UseCors must be called before UseResponseCaching
//app.UseCors();

app.UseResponseCaching();

app.UseAuthorization();

app.MapControllers();

app.Run();

NoStoreLocation.None

NoStore는 대부분의 다른 속성을 재정의합니다. 이 속성을 true로 설정하면 Cache-Control 헤더가 no-store로 설정됩니다. LocationNone으로 설정된 경우:

  • Cache-Controlno-store,no-cache로 설정됩니다.
  • Pragmano-cache로 설정됩니다.

NoStorefalse이고 LocationNone인 경우 Cache-ControlPragmano-cache로 설정됩니다.

NoStore는 일반적으로 오류 페이지에 대해 true로 설정됩니다. 다음은 클라이언트에 응답을 저장하지 않도록 지시하는 응답 헤더를 생성합니다.

[Route("api/[controller]/ticks")]
[HttpGet]
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
public ContentResult GetTimeTicks() => Content(
                  DateTime.Now.Ticks.ToString());

이전 코드는 응답에 다음 헤더를 포함합니다.

Cache-Control: no-store,no-cache
Pragma: no-cache

앱의 모든 MVC 컨트롤러 또는 Razor Pages 페이지 응답에 ResponseCacheAttribute를 적용하려면 MVC 필터 또는 Razor Pages 필터를 사용하여 추가하세요.

MVC 앱에서는 다음과 같습니다.

builder.Services.AddControllersWithViews().AddMvcOptions(options => 
    options.Filters.Add(
        new ResponseCacheAttribute
        {
            NoStore = true, 
            Location = ResponseCacheLocation.None
        }));

Razor Pages 앱에 적용되는 방법은 MVC 전역 필터 목록에 ResponseCacheAttribute를 추가한 것이 Razor Pages(dotnet/aspnetcore #18890)에 적용되지 않음을 참조하세요. 이슈 주석에 제공된 예제는 Minimal API 6.0이 릴리스되기 전의 ASP.NET Core를 대상으로 하는 앱을 위해 작성한 것입니다. 6.0 이상 앱의 경우 예제의 서비스 등록을 Program.csbuilder.Services.AddSingleton...으로 변경하세요.

위치 및 기간

캐싱을 사용하도록 설정하려면 Duration을 양수 값으로 설정해야 하며 LocationAny(기본값) 또는 Client여야 합니다. 프레임워크는 Cache-Control 헤더를 위치 값으로 설정한 다음 응답의 max-age를 설정합니다.

AnyClientLocation 옵션은 각각 publicprivateCache-Control 헤더 값으로 변환됩니다. NoStore 및 Location.None 섹션에서 언급했듯이 LocationNone으로 설정하면 Cache-ControlPragma 헤더가 모두 no-cache로 설정됩니다.

Location.Any(public으로 Cache-Control 설정)는 클라이언트 또는 중간 프록시응답 캐싱 미들웨어를 비롯한 값을 캐시할 수 있음을 나타냅니다.

Location.Client(private으로 Cache-Control 설정)는 클라이언트만 값을 캐시할 수 있음을 나타냅니다. 응답 캐싱 미들웨어를 비롯한 중간 캐시는 값을 캐시하지 않아야 합니다.

캐시 제어 헤더는 클라이언트 및 중간 프록시에 응답을 캐시하는 시기와 방법에 대한 지침만 제공합니다. 클라이언트와 프록시가 RFC 9111: HTTP 캐싱에 적용된다는 보장은 없습니다. 응답 캐싱 미들웨어는 항상 사양에 의해 배치된 캐싱 규칙을 따릅니다.

다음 예제에서는 Duration을 설정하고 기본 Location 값을 그대로 두어 생성한 헤더를 보여 줍니다.

[Route("api/[controller]/ms")]
[HttpGet]
[ResponseCache(Duration = 10, Location = ResponseCacheLocation.Any, NoStore = false)]
public ContentResult GetTimeMS() => Content(
                  DateTime.Now.Millisecond.ToString());

이전 코드는 응답에 다음 헤더를 포함합니다.

Cache-Control: public,max-age=10

캐시 프로필

많은 컨트롤러 작업 특성에서 응답 캐시 설정을 복제하는 대신, MVC/Razor Pages를 설정할 때 캐시 프로필을 옵션으로 구성할 수 있습니다. 참조된 캐시 프로필에 있는 값은 ResponseCacheAttribute에서 기본값으로 사용되며 특성에 지정된 속성으로 재정의됩니다.

다음 예제에서는 30초 캐시 프로필을 보여줍니다.

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddResponseCaching();
builder.Services.AddControllers(options =>
{
    options.CacheProfiles.Add("Default30",
        new CacheProfile()
        {
            Duration = 30
        });
});

var app = builder.Build();

app.UseHttpsRedirection();

// UseCors must be called before UseResponseCaching
//app.UseCors();

app.UseResponseCaching();

app.UseAuthorization();

app.MapControllers();

app.Run();

다음 코드는 Default30 캐시 프로필을 참조합니다.

[ApiController]
[ResponseCache(CacheProfileName = "Default30")]
public class Time2Controller : ControllerBase
{
    [Route("api/[controller]")]
    [HttpGet]
    public ContentResult GetTime() => Content(
                      DateTime.Now.Millisecond.ToString());

    [Route("api/[controller]/ticks")]
    [HttpGet]
    public ContentResult GetTimeTicks() => Content(
                      DateTime.Now.Ticks.ToString());
}

Default30 캐시 프로필의 결과 헤더 응답에는 다음이 포함됩니다.

Cache-Control: public,max-age=30

[ResponseCache] 특성은 다음에 적용될 수 있습니다.

  • Razor Pages: 특성을 처리기 메서드에 적용할 수 없습니다. UI 앱과 함께 사용되는 브라우저는 응답 캐싱을 방지합니다.
  • MVC 컨트롤러.
  • MVC 작업 메서드: 메서드 수준 특성은 클래스 수준 특성에 지정된 설정을 재정의합니다.

다음 코드는 컨트롤러 수준 및 메서드 수준에서 [ResponseCache] 특성을 적용합니다.

[ApiController]
[ResponseCache(VaryByHeader = "User-Agent", Duration = 30)]
public class Time4Controller : ControllerBase
{
    [Route("api/[controller]")]
    [HttpGet]
    public ContentResult GetTime() => Content(
                      DateTime.Now.Millisecond.ToString());

    [Route("api/[controller]/ticks")]
    [HttpGet]
    public ContentResult GetTimeTicks() => Content(
                  DateTime.Now.Ticks.ToString());

    [Route("api/[controller]/ms")]
    [HttpGet]
    [ResponseCache(Duration = 10, Location = ResponseCacheLocation.Any, NoStore = false)]
    public ContentResult GetTimeMS() => Content(
                      DateTime.Now.Millisecond.ToString());
}

추가 리소스

샘플 코드 보기 및 다운로드(다운로드 방법)

응답 캐싱은 클라이언트 또는 프록시가 웹 서버에 대해 수행하는 요청 수를 줄입니다. 또한 응답 캐싱은 웹 서버에서 응답을 생성하기 위해 수행하는 작업의 양을 줄입니다. 응답 캐싱은 클라이언트, 프록시 및 미들웨어에서 응답을 캐시하는 방법을 지정하는 헤더에 의해 제어됩니다.

응답 [ResponseCache] 캐싱 헤더 설정에 참여합니다. 클라이언트 및 중간 프록시는 RFC 9111: HTTP 캐싱에 따라 응답을 캐시하는 데 헤더를 적용해야 합니다.

HTTP 1.1 캐싱 사양을 따르는 서버 쪽 캐싱의 경우 응답 캐싱 미들웨어를 사용합니다. 미들웨어는 [ResponseCache] 속성을 사용하여 서버 쪽 캐싱 헤더를 설정할 수 있습니다.

HTTP 기반 응답 캐싱

RFC 9111: HTTP 캐싱은 인터넷 캐시의 작동 방식을 설명합니다. 캐싱에 사용되는 기본 HTTP 헤더는 캐시 지시문을 지정하는 데 사용되는 Cache-Control입니다. 지시문은 요청이 클라이언트에서 서버로 이동하고 서버에서 클라이언트로 다시 이동하는 방식으로 캐싱 동작을 제어합니다. 요청 및 응답은 프록시 서버를 통해 이동하고, 프록시 서버는 HTTP 1.1 캐싱 사양을 준수해야 합니다.

다음 표에는 일반적인 Cache-Control 지시문이 나와 있습니다.

지시문 작업
public 캐시에서 응답을 저장할 수 있습니다.
private 응답은 공유 캐시에 저장되지 않아야 합니다. 개인 캐시는 응답을 저장하고 다시 사용할 수 있습니다.
max-age 클라이언트는 나이가 지정된 시간(초)보다 큰 응답을 수락하지 않습니다. 예: max-age=60(60초), max-age=2592000(1달)
no-cache 요청 시: 캐시가 저장된 응답을 사용하여 요청을 충족해서는 안 됩니다. 원본 서버는 클라이언트에 대한 응답을 다시 생성하고 미들웨어는 해당 캐시에 저장된 응답을 업데이트합니다.

응답 시: 원본 서버에서 유효성 검사 없이 후속 요청에 대한 응답을 사용하지 않아야 합니다.
no-store 요청 시: 캐시에서 요청을 저장하지 않아야 합니다.

응답 시: 캐시가 응답의 일부를 저장하지 않아야 합니다.

캐싱에서 역할을 수행하는 다른 캐시 헤더가 다음 표에 나와 있습니다.

헤더 함수
Age 응답을 생성하거나 원본 서버에서 유효성을 검사한 이후의 예상 시간(초)입니다.
만료 응답이 오래된 것으로 간주되는 시간입니다.
Pragma no-cache 동작 설정에 대한 HTTP/1.0 캐시와 이전 버전과의 호환성을 위해 존재합니다. Cache-Control 헤더가 있으면 Pragma 헤더는 무시됩니다.
Vary 캐시된 응답의 원래 요청과 새 요청 모두에서 Vary 헤더 필드가 모두 일치하지 않는 경우 캐시된 응답을 보내지 않도록 지정합니다.

HTTP 기반 캐싱은 요청 Cache-Control 지시문을 사용합니다.

RFC 9111: HTTP 캐싱(섹션 5.2. Cache-Control)은 클라이언트에서 보낸 유효한 Cache-Control 헤더를 적용하는 데 캐시가 필요합니다. 클라이언트는 no-cache 헤더 값을 사용하여 요청을 수행하고 서버에서 모든 요청에 대해 새 응답을 생성하도록 강제할 수 있습니다.

HTTP 캐싱의 목표를 고려하는 경우 항상 클라이언트 Cache-Control 요청 헤더를 적용하는 것이 좋습니다. 공식 사양에서 캐싱은 클라이언트, 프록시 및 서버의 네트워크에서 요청을 충족하는 대기 시간 및 네트워크 오버 헤드를 줄이기 위한 것입니다. 원본 서버에서 로드를 제어하기 위해 반드시 필요한 방법은 아닙니다.

미들웨어가 공식 캐싱 사양을 준수하기 때문에 응답 캐싱 미들웨어를 사용하는 경우 이 캐싱 동작에 대한 개발자 제어는 없습니다. 서버 부하를 더 효율적으로 제어하기 위해 출력 캐싱을 지원하는 기능은 이후 버전의 ASP.NET Core에 대한 디자인 제안입니다. 자세한 내용은 출력 캐싱에 대한 지원 추가(dotnet/aspnetcore #27387)를 참조하세요.

ASP.NET Core의 기타 캐싱 기술

메모리 내 캐싱

메모리 내 캐싱은 서버 메모리를 사용하여 캐시된 데이터를 저장합니다. 이 유형의 캐싱은 단일 서버 또는 고정 세션을 사용하는 여러 서버에 적합합니다. 세션 선호도를 고정 세션이라고 도 합니다. 세션 선호도는 클라이언트의 요청이 처리를 위해 항상 동일한 서버로 라우팅되는 것을 의미합니다.

자세한 내용은 ASP.NET Core 메모리 내 캐시Azure Application Gateway 세션 선호도 이슈 해결을 참조하세요.

분산 캐시

앱이 클라우드 또는 서버 팜에서 호스팅될 때 분산 캐시를 사용하여 메모리에 데이터를 저장합니다. 캐시는 요청을 처리하는 서버에서 공유됩니다. 클라이언트에 대해 캐시된 데이터를 사용할 수 있는 경우 클라이언트는 그룹의 모든 서버에서 처리한 요청을 제출할 수 있습니다. ASP.NET Core는 SQL Server, RedisNCache 분산 캐시와 함께 작동합니다.

자세한 내용은 ASP.NET Core의 분산 캐싱을 참조하세요.

캐시 태그 도우미

캐시 태그 도우미를 사용하여 MVC 보기 또는 Razor Page에서 콘텐츠를 캐시합니다. 캐시 태그 도우미는 메모리 내 캐싱을 사용하여 데이터를 저장합니다.

자세한 내용은 ASP.NET Core MVC의 캐시 태그 도우미를 참조하세요.

분산 캐시 태그 도우미

분산된 캐시 태그 도우미를 사용하여 분산 클라우드 또는 웹 팜 시나리오의 MVC 보기나 Razor Page에서 콘텐츠를 캐시합니다. 분산 캐시 태그 도우미는 SQL Server, Redis 또는 NCache를 사용하여 데이터를 저장합니다.

자세한 내용은 ASP.NET Core의 분산 캐시 태그 도우미를 참조하세요.

ResponseCache 특성

ResponseCacheAttribute는 응답 캐싱에 적절한 헤더를 설정하는 데 필요한 매개 변수를 지정합니다.

Warning

인증된 클라이언트에 대한 정보가 포함된 콘텐츠에 대해 캐싱을 사용하지 않도록 설정합니다. 사용자의 ID에 따라 변경되지 않는 콘텐츠나 사용자의 로그인 여부에 따라서만 캐싱을 사용하도록 설정해야 합니다.

VaryByQueryKeys는 지정된 쿼리 키의 목록 값에 따라 저장된 응답을 변경합니다. *의 단일 값이 제공되면 미들웨어는 모든 요청 쿼리 문자열 매개 변수에 따라 다양한 응답을 제공합니다.

VaryByQueryKeys 속성을 설정하려면 응답 캐싱 미들웨어를 사용하도록 설정해야 합니다. 그렇지 않으면 런타임 예외가 throw됩니다. VaryByQueryKeys 속성에 해당하는 HTTP 헤더가 없습니다. 속성은 응답 캐싱 미들웨어에 의해 처리되는 HTTP 기능입니다. 미들웨어가 캐시된 응답을 제공하려면 쿼리 문자열 및 쿼리 문자열 값이 이전 요청과 일치해야 합니다. 예를 들어 다음 표에 표시된 요청 및 결과의 순서를 고려합니다.

요청 결과
http://example.com?key1=value1 서버에서 반환됩니다.
http://example.com?key1=value1 미들웨어에서 반환됩니다.
http://example.com?key1=value2 서버에서 반환됩니다.

첫 번째 요청은 서버에서 반환되고 미들웨어에 캐시됩니다. 쿼리 문자열이 이전 요청과 일치하기 때문에 두 번째 요청은 미들웨어에서 반환됩니다. 쿼리 문자열 값이 이전 요청과 일치하지 않으므로 세 번째 요청이 미들웨어 캐시에 없습니다.

ResponseCacheAttribute를 통해 Microsoft.AspNetCore.Mvc.Internal.ResponseCacheFilter를 구성하고 만드는 데(IFilterFactory를 통해) 사용됩니다. ResponseCacheFilter는 응답의 적절한 HTTP 헤더 및 기능을 업데이트하는 작업을 수행합니다. 필터:

  • Vary, Cache-ControlPragma에 대한 기존 헤더를 제거합니다.
  • ResponseCacheAttribute에 설정된 속성에 따라 적절한 헤더를 작성합니다.
  • VaryByQueryKeys가 설정된 경우 응답 캐싱 HTTP 기능을 업데이트합니다.

Vary

이 헤더는 VaryByHeader 속성이 설정된 경우에만 기록됩니다. 속성이 Vary 속성의 값으로 설정됩니다. 다음 샘플에서는 VaryByHeader 속성을 사용합니다.

[ResponseCache(VaryByHeader = "User-Agent", Duration = 30)]
public class Cache1Model : PageModel
{

샘플 앱을 사용하여 브라우저의 네트워크 도구를 통해 응답 헤더를 봅니다. 다음 응답 헤더는 Cache1 페이지 응답과 함께 전송됩니다.

Cache-Control: public,max-age=30
Vary: User-Agent

NoStoreLocation.None

NoStore는 대부분의 다른 속성을 재정의합니다. 이 속성을 true로 설정하면 Cache-Control 헤더가 no-store로 설정됩니다. LocationNone으로 설정된 경우:

  • Cache-Controlno-store,no-cache로 설정됩니다.
  • Pragmano-cache로 설정됩니다.

NoStorefalse이고 LocationNone인 경우 Cache-ControlPragmano-cache로 설정됩니다.

NoStore는 일반적으로 오류 페이지에 대해 true로 설정됩니다. 샘플 앱의 Cache2 페이지는 클라이언트가 응답을 저장하지 않도록 지시하는 응답 헤더를 생성합니다.

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class Cache2Model : PageModel
{

샘플 앱은 다음 헤더가 있는 Cache2 페이지를 반환합니다.

Cache-Control: no-store,no-cache
Pragma: no-cache

앱의 모든 MVC 컨트롤러 또는 Razor Pages 페이지 응답에 ResponseCacheAttribute를 적용하려면 MVC 필터 또는 Razor Pages 필터를 사용하여 추가하세요.

MVC 앱에서는 다음과 같습니다.

services.AddMvc().AddMvcOptions(options => 
    options.Filters.Add(
        new ResponseCacheAttribute
        {
            NoStore = true, 
            Location = ResponseCacheLocation.None
        }));

Razor Pages 앱에 적용되는 방법은 MVC 전역 필터 목록에 ResponseCacheAttribute를 추가한 것이 Razor Pages(dotnet/aspnetcore #18890)에 적용되지 않음을 참조하세요.

위치 및 기간

캐싱을 사용하도록 설정하려면 Duration을 양수 값으로 설정해야 하며 LocationAny(기본값) 또는 Client여야 합니다. 프레임워크는 Cache-Control 헤더를 위치 값으로 설정한 다음 응답의 max-age를 설정합니다.

AnyClientLocation 옵션은 각각 publicprivateCache-Control 헤더 값으로 변환됩니다. NoStore 및 Location.None 섹션에서 언급했듯이 LocationNone으로 설정하면 Cache-ControlPragma 헤더가 모두 no-cache로 설정됩니다.

Location.Any(public으로 Cache-Control 설정)는 클라이언트 또는 중간 프록시응답 캐싱 미들웨어를 비롯한 값을 캐시할 수 있음을 나타냅니다.

Location.Client(private으로 Cache-Control 설정)는 클라이언트만 값을 캐시할 수 있음을 나타냅니다. 응답 캐싱 미들웨어를 비롯한 중간 캐시는 값을 캐시하지 않아야 합니다.

캐시 제어 헤더는 응답을 캐시하는 시기와 방법에 대한 지침만 클라이언트 및 중간 프록시에 제공합니다. 클라이언트와 프록시가 RFC 9111: HTTP 캐싱에 적용된다는 보장은 없습니다. 응답 캐싱 미들웨어는 항상 사양에 의해 배치된 캐싱 규칙을 따릅니다.

다음 예제에서는 샘플 앱의 Cache3 페이지 모델과 Duration을 설정하고 기본 Location 값을 그대로 두어 생성된 헤더를 보여 줍니다.

[ResponseCache(Duration = 10, Location = ResponseCacheLocation.Any, NoStore = false)]
public class Cache3Model : PageModel
{

샘플 앱은 다음 헤더가 있는 Cache3 페이지를 반환합니다.

Cache-Control: public,max-age=10

캐시 프로필

많은 컨트롤러 작업 특성에서 응답 캐시 설정을 복제하는 대신, Startup.ConfigureServices에서 MVC/Razor Pages를 설정할 때 캐시 프로필을 옵션으로 구성할 수 있습니다. 참조된 캐시 프로필에 있는 값은 ResponseCacheAttribute에서 기본값으로 사용되며 특성에 지정된 속성으로 재정의됩니다.

캐시 프로필을 설정합니다. 다음 예제에서는 샘플 앱의 Startup.ConfigureServices에서 30초 캐시 프로필을 보여 줍니다.

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddMvc(options =>
    {
        options.CacheProfiles.Add("Default30",
            new CacheProfile()
            {
                Duration = 30
            });
    });
}

샘플 앱의 Cache4 페이지 모델은 Default30 캐시 프로필을 참조합니다.

[ResponseCache(CacheProfileName = "Default30")]
public class Cache4Model : PageModel
{

ResponseCacheAttribute는 다음과 같은 대상에 적용할 수 있습니다.

  • Razor Pages: 특성을 처리기 메서드에 적용할 수 없습니다.
  • MVC 컨트롤러.
  • MVC 작업 메서드: 메서드 수준 특성은 클래스 수준 특성에 지정된 설정을 재정의합니다.

다음은 Default30 캐시 프로필에 의해 Cache4 페이지 응답에 적용된 결과 헤더입니다.

Cache-Control: public,max-age=30

추가 리소스