ASP.NET Core에서 세션 및 앱 상태Session and app state in ASP.NET Core

작성자: Rick Anderson, Steve Smith, Diana LaRoseLuke LathamBy Rick Anderson, Steve Smith, Diana LaRose, and Luke Latham

HTTP는 상태 비저장 프로토콜입니다.HTTP is a stateless protocol. HTTP 요청은 추가 단계를 수행하지 않고 사용자 값 또는 앱 상태를 유지하지 않는 독립적인 메시지입니다.Without taking additional steps, HTTP requests are independent messages that don't retain user values or app state. 이 문서에서는 요청 간 사용자 데이터와 앱 상태를 유지하는 몇 가지 방법에 대해 설명합니다.This article describes several approaches to preserve user data and app state between requests.

예제 코드 살펴보기 및 다운로드(다운로드 방법)View or download sample code (how to download)

상태 관리State management

상태는 여러 방법을 사용하여 저장할 수 있습니다.State can be stored using several approaches. 각 방법은 이 항목 뒷부분에서 설명합니다.Each approach is described later in this topic.

저장소 접근 방식Storage approach 저장소 메커니즘Storage mechanism
쿠키Cookies HTTP 쿠키(서버 쪽 앱 코드를 사용하여 저장된 데이터 포함)HTTP cookies (may include data stored using server-side app code)
세션 상태Session state HTTP 쿠키 및 서버 쪽 앱 코드HTTP cookies and server-side app code
TempDataTempData HTTP 쿠키 또는 세션 상태HTTP cookies or session state
쿼리 문자열Query strings HTTP 쿼리 문자열HTTP query strings
숨겨진 필드Hidden fields HTTP 양식 필드HTTP form fields
HttpContext.ItemsHttpContext.Items 서버 쪽 앱 코드Server-side app code
캐시Cache 서버 쪽 앱 코드Server-side app code
종속성 주입Dependency Injection 서버 쪽 앱 코드Server-side app code

쿠키Cookies

쿠키는 요청 간에 데이터를 저장합니다.Cookies store data across requests. 쿠키는 모든 요청과 함께 전송되므로 해당 크기는 최소로 유지되어야 합니다.Because cookies are sent with every request, their size should be kept to a minimum. 이상적으로 식별자만 앱에 저장된 데이터와 함께 쿠키에 저장되어야 합니다.Ideally, only an identifier should be stored in a cookie with the data stored by the app. 대부분의 브라우저는 쿠키 크기를 4096바이트로 제한합니다.Most browsers restrict cookie size to 4096 bytes. 제한된 수의 쿠키만 각 도메인에 사용할 수 있습니다.Only a limited number of cookies are available for each domain.

쿠키는 변조될 수 있기 때문에 앱에서 유효성을 검사해야 합니다.Because cookies are subject to tampering, they must be validated by the app. 쿠키는 사용자가 삭제할 수 있으며 클라이언트에서 만료됩니다.Cookies can be deleted by users and expire on clients. 그러나 쿠키는 일반적으로 클라이언트에서 데이터 지속성의 가장 안정적인 형태입니다.However, cookies are generally the most durable form of data persistence on the client.

쿠키는 종종 개인 설정에 사용됩니다. 여기서 콘텐츠는 알려진 사용자에 대해 사용자 지정됩니다.Cookies are often used for personalization, where content is customized for a known user. 사용자만 식별되고 대부분의 경우 인증되지 않습니다.The user is only identified and not authenticated in most cases. 쿠키는 사용자의 이름, 계정 이름 또는 고유한 사용자 ID(예: GUID)를 저장할 수 있습니다.The cookie can store the user's name, account name, or unique user ID (such as a GUID). 사용자는 쿠키를 사용하여 선호하는 웹 사이트 배경색과 같은 사용자의 개인 설정에 액세스할 수 있습니다.You can then use the cookie to access the user's personalized settings, such as their preferred website background color.

쿠키를 발급하고 개인 정보 보호 문제를 다룰 때 유럽 연합 GDPR(일반 데이터 보호 규정)에 유의합니다.Be mindful of the European Union General Data Protection Regulations (GDPR) when issuing cookies and dealing with privacy concerns. 자세한 내용은 ASP.NET Core의 GDPR(일반 데이터 보호 규정) 지원을 참조하세요.For more information, see General Data Protection Regulation (GDPR) support in ASP.NET Core.

세션 상태Session state

세션 상태는 사용자가 웹앱을 탐색하는 동안 사용자 데이터를 저장하기 위한 ASP.NET Core 시나리오입니다.Session state is an ASP.NET Core scenario for storage of user data while the user browses a web app. 세션 상태는 앱에서 유지 관리하는 저장소를 사용하여 클라이언트의 요청 간에 데이터를 유지합니다.Session state uses a store maintained by the app to persist data across requests from a client. 세션 데이터는 캐시에 의해 백업되고 임시 데이터로 간주되므로 사이트는 세션 데이터 없이 계속 작동합니다.The session data is backed by a cache and considered ephemeral data—the site should continue to function without the session data.

참고

SignalR Hub가 HTTP 컨텍스트와 독립적으로 실행될 수 있으므로, 세션은 SignalR 앱에서 지원되지 않습니다.Session isn't supported in SignalR apps because a SignalR Hub may execute independent of an HTTP context. 예를 들어, 허브에서 긴 폴링 요청이 HTTP 컨텍스트 수명을 초과하여 계속 열려 있을 경우 이 문제가 발생할 수 있습니다.For example, this can occur when a long polling request is held open by a hub beyond the lifetime of the request's HTTP context.

ASP.NET Core는 각 요청과 함께 앱으로 전송되는 세션 ID를 포함하는 쿠키를 클라이언트에 제공하여 세션 상태를 유지합니다.ASP.NET Core maintains session state by providing a cookie to the client that contains a session ID, which is sent to the app with each request. 앱은 세션 ID를 사용하여 세션 데이터를 가져옵니다.The app uses the session ID to fetch the session data.

세션 상태는 다음과 같은 동작을 보여 줍니다.Session state exhibits the following behaviors:

  • 세션 쿠키는 브라우저에 특정되기 때문에 브라우저 간에 세션이 공유되지 않습니다.Because the session cookie is specific to the browser, sessions aren't shared across browsers.
  • 세션 쿠키는 브라우저 세션이 끝나면 삭제됩니다.Session cookies are deleted when the browser session ends.
  • 쿠키가 만료된 세션에 대해 수신되면 동일한 세션 쿠키를 사용하는 새 세션이 생성됩니다.If a cookie is received for an expired session, a new session is created that uses the same session cookie.
  • 빈 세션은 유지되지 않습니다. 요청 간 세션을 유지하려면 세션에 하나 이상의 값이 설정되어 있어야 합니다.Empty sessions aren't retained—the session must have at least one value set into it to persist the session across requests. 세션이 유지되지 않으면 새 요청마다 새 세션 ID가 생성됩니다.When a session isn't retained, a new session ID is generated for each new request.
  • 앱은 마지막 요청 이후 제한된 시간 동안 세션을 유지합니다.The app retains a session for a limited time after the last request. 앱은 세션 시간 제한을 설정하거나 20분의 기본값을 사용합니다.The app either sets the session timeout or uses the default value of 20 minutes. 세션 상태는 특정 세션과 관련된 사용자 데이터를 저장하되, 데이터가 세션 간에 영구적으로 저장할 필요가 없는 경우에 적합합니다.Session state is ideal for storing user data that's specific to a particular session but where the data doesn't require permanent storage across sessions.
  • 세션 데이터는 ISession.Clear 구현이 호출되거나 세션이 만료될 때 삭제됩니다.Session data is deleted either when the ISession.Clear implementation is called or when the session expires.
  • 클라이언트 브라우저가 닫혔거나 세션 쿠키가 삭제 또는 클라이언트에서 만료되었을 때 앱 코드에 이를 알려주는 기본 메커니즘은 없습니다.There's no default mechanism to inform app code that a client browser has been closed or when the session cookie is deleted or expired on the client.

경고

중요한 데이터를 세션 상태에 저장하지 마세요.Don't store sensitive data in session state. 사용자는 브라우저를 닫지 않고 세션 쿠키를 지울 수 있습니다.The user might not close the browser and clear the session cookie. 일부 브라우저는 브라우저 창이 닫혀도 유효한 세션 쿠키를 유지 관리합니다.Some browsers maintain valid session cookies across browser windows. 세션은 단일 사용자로 제한될 수 없으므로 다음 사용자는 동일한 세션 쿠키로 앱을 계속 검색할 수 있습니다.A session might not be restricted to a single user—the next user might continue to browse the app with the same session cookie.

메모리 내 캐시 공급자는 앱이 있는 서버의 메모리에 세션 데이터를 저장합니다.The in-memory cache provider stores session data in the memory of the server where the app resides. 서버 팜 시나리오:In a server farm scenario:

세션 상태 구성Configure session state

Microsoft.AspNetCore.App 메타패키지에 포함된 Microsoft.AspNetCore.Session 패키지는 세션 상태 관리용 미들웨어를 제공합니다.The Microsoft.AspNetCore.Session package, which is included in the Microsoft.AspNetCore.App metapackage, provides middleware for managing session state. 세션 미들웨어를 활성화하려면 Startup은 다음을 포함해야 합니다.To enable the session middleware, Startup must contain:

Microsoft.AspNetCore.Session 패키지는 세션 상태 관리용 미들웨어를 제공합니다.The Microsoft.AspNetCore.Session package provides middleware for managing session state. 세션 미들웨어를 활성화하려면 Startup은 다음을 포함해야 합니다.To enable the session middleware, Startup must contain:

다음 코드에서는 IDistributedCache의 기본 메모리 내 구현을 사용하여 메모리 내 세션 공급자를 설정하는 방법을 보여 줍니다.The following code shows how to set up the in-memory session provider with a default in-memory implementation of IDistributedCache:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddDistributedMemoryCache();

        services.AddSession(options =>
        {
            // Set a short timeout for easy testing.
            options.IdleTimeout = TimeSpan.FromSeconds(10);
            options.Cookie.HttpOnly = true;
        });

        services.AddMvc()
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();
        app.UseSession();
        app.UseHttpContextItemsMiddleware();
        app.UseMvc();
    }
}
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDistributedMemoryCache();

        services.AddSession(options =>
        {
            // Set a short timeout for easy testing.
            options.IdleTimeout = TimeSpan.FromSeconds(10);
            options.CookieHttpOnly = true;
        });

        services.AddMvc();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseSession();
        app.UseHttpContextItemsMiddleware();
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

미들웨어의 순서가 중요합니다.The order of middleware is important. 앞의 예에서 UseMvc 이후에 UseSession이 호출되면 InvalidOperationException 예외가 발생합니다.In the preceding example, an InvalidOperationException exception occurs when UseSession is invoked after UseMvc. 자세한 내용은 미들웨어 순서 지정을 참조하세요.For more information, see Middleware Ordering.

HttpContext.Session은 세션 상태가 구성된 후에 사용할 수 있습니다.HttpContext.Session is available after session state is configured.

UseSession이 호출되기 전에 HttpContext.Session에 액세스할 수 없습니다.HttpContext.Session can't be accessed before UseSession has been called.

앱이 응답 스트림에 쓰기 시작한 후에는 새 세션 쿠키가 있는 새 세션을 만들 수 없습니다.A new session with a new session cookie can't be created after the app has begun writing to the response stream. 예외는 웹 서버 로그에 기록되며 브라우저에는 표시되지 않습니다.The exception is recorded in the web server log and not displayed in the browser.

세션 상태를 비동기적으로 로드Load session state asynchronously

ASP.NET Core에서 기본 세션 공급자는 ISession.LoadAsync 메서드가 TryGetValue, Set 또는 Remove 메서드 전에 명시적으로 호출된 경우에만 기본 IDistributedCache 백업 저장소에서 비동기적으로 세션 레코드를 로드합니다.The default session provider in ASP.NET Core loads session records from the underlying IDistributedCache backing store asynchronously only if the ISession.LoadAsync method is explicitly called before the TryGetValue, Set, or Remove methods. LoadAsync가 먼저 호출되지 않은 경우 기본 세션 레코드가 동기적으로 로드되며, 이는 크기에 따라 성능 저하를 초래할 수 있습니다.If LoadAsync isn't called first, the underlying session record is loaded synchronously, which can incur a performance penalty at scale.

이 패턴을 앱에 적용하려면 LoadAsync 메서드가 TryGetValue, Set 또는 Remove 이전에 호출되지 않은 경우 예외를 throw하는 버전으로 DistributedSessionStoreDistributedSession 구현을 래핑합니다.To have apps enforce this pattern, wrap the DistributedSessionStore and DistributedSession implementations with versions that throw an exception if the LoadAsync method isn't called before TryGetValue, Set, or Remove. 서비스 컨테이너에 래핑된 버전을 등록합니다.Register the wrapped versions in the services container.

세션 옵션Session options

세션 기본값을 재정의하려면 SessionOptions를 사용합니다.To override session defaults, use SessionOptions.

옵션Option 설명Description
쿠키Cookie 쿠키를 만드는 데 사용되는 설정을 결정합니다.Determines the settings used to create the cookie. Name의 기본값은 SessionDefaults.CookieName(.AspNetCore.Session)입니다.Name defaults to SessionDefaults.CookieName (.AspNetCore.Session). Path의 기본값은 SessionDefaults.CookiePath(/)입니다.Path defaults to SessionDefaults.CookiePath (/). SameSite의 기본값은 SameSiteMode.Lax(1)입니다.SameSite defaults to SameSiteMode.Lax (1). HttpOnly의 기본값은 true입니다.HttpOnly defaults to true. IsEssential의 기본값은 false입니다.IsEssential defaults to false.
IdleTimeoutIdleTimeout IdleTimeout은 콘텐츠가 삭제되기 전까지 세션이 유휴 상태일 수 있는 시간을 나타냅니다.The IdleTimeout indicates how long the session can be idle before its contents are abandoned. 각 세션 액세스는 시간 제한을 다시 설정합니다.Each session access resets the timeout. 이는 쿠키가 아닌 세션의 콘텐츠에만 적용됩니다.Note this only applies to the content of the session, not the cookie. 기본값은 20분입니다.The default is 20 minutes.
IOTimeoutIOTimeout 저장소에서 세션을 로드하거나 저장소로 다시 커밋할 수 있는 최대 시간입니다.The maximim amount of time allowed to load a session from the store or to commit it back to the store. 이는 비동기 작업에만 적용될 수 있습니다.Note this may only apply to asynchronous operations. 이 시간 제한은 InfiniteTimeSpan을 사용하여 비활성화할 수 있습니다.This timeout can be disabled using InfiniteTimeSpan. 기본값은 1분입니다.The default is 1 minute.

세션은 쿠키를 사용하여 단일 브라우저에서 요청을 추적하고 식별합니다.Session uses a cookie to track and identify requests from a single browser. 기본적으로 이 쿠키는 .AspNetCore.Session이라고 하며 /의 경로를 사용합니다.By default, this cookie is named .AspNetCore.Session, and it uses a path of /. 쿠키 기본값은 도메인을 지정하지 않으므로(HttpOnly 기본값이 true임으로) 페이지의 클라이언트 쪽 스크립트에 사용할 수 없습니다.Because the cookie default doesn't specify a domain, it isn't made available to the client-side script on the page (because HttpOnly defaults to true).

옵션Option 설명Description
CookieDomainCookieDomain 쿠키를 만드는 데 사용되는 도메인을 결정합니다.Determines the domain used to create the cookie. CookieDomain은 기본적으로 설정되지 않습니다.CookieDomain isn't set by default.
CookieHttpOnlyCookieHttpOnly 브라우저가 클라이언트 쪽 JavaScript의 쿠키 액세스를 허용할지 결정합니다.Determines if the browser should allow the cookie to be accessed by client-side JavaScript. 기본값은 true이며, 이는 쿠키가 HTTP 요청에만 전달되고 페이지의 스크립트에는 제공되지 않음을 의미합니다.The default is true, which means the cookie is only passed to HTTP requests and isn't made available to script on the page.
CookieNameCookieName 세션 ID를 유지하는 데 사용되는 쿠키 이름을 결정합니다Determines the cookie name used to persist the session ID. 기본값은 SessionDefaults.CookieName(.AspNetCore.Session)입니다.The default is SessionDefaults.CookieName (.AspNetCore.Session).
CookiePathCookiePath 쿠키를 만드는 데 사용되는 경로를 결정합니다.Determines the path used to create the cookie. 기본값은 SessionDefaults.CookiePath(/)입니다.Defaults to SessionDefaults.CookiePath (/).
CookieSecureCookieSecure 쿠키를 HTTPS 요청에서만 전송할지를 결정합니다.Determines if the cookie should only be transmitted on HTTPS requests. 기본값은 CookieSecurePolicy.None(2)입니다.The default is CookieSecurePolicy.None (2).
IdleTimeoutIdleTimeout IdleTimeout은 콘텐츠가 삭제되기 전까지 세션이 유휴 상태일 수 있는 시간을 나타냅니다.The IdleTimeout indicates how long the session can be idle before its contents are abandoned. 각 세션 액세스는 시간 제한을 다시 설정합니다.Each session access resets the timeout. 이는 쿠키가 아닌 세션의 콘텐츠에만 적용됩니다.Note this only applies to the content of the session, not the cookie. 기본값은 20분입니다.The default is 20 minutes.

세션은 쿠키를 사용하여 단일 브라우저에서 요청을 추적하고 식별합니다.Session uses a cookie to track and identify requests from a single browser. 기본적으로 이 쿠키는 .AspNet.Session이라고 하며 /의 경로를 사용합니다.By default, this cookie is named .AspNet.Session, and it uses a path of /.

쿠키 세션 기본값을 재정의하려면 SessionOptions를 사용합니다.To override cookie session defaults, use SessionOptions:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddDistributedMemoryCache();

    services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    services.AddSession(options =>
    {
        options.Cookie.Name = ".AdventureWorks.Session";
        options.IdleTimeout = TimeSpan.FromSeconds(10);
    });
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddDistributedMemoryCache();

    services.AddSession(options =>
    {
        options.CookieName = ".AdventureWorks.Session";
        options.IdleTimeout = TimeSpan.FromSeconds(10);
    });

    services.AddMvc();
}

앱은 IdleTimeout 속성을 사용하여 서버 캐시의 콘텐츠가 중단되기 전에 유휴 상태일 수 있는 세션의 기간을 결정합니다.The app uses the IdleTimeout property to determine how long a session can be idle before its contents in the server's cache are abandoned. 이 속성은 쿠키 만료와 무관합니다.This property is independent of the cookie expiration. 세션 미들웨어를 통해 전달되는 각 요청은 시간 제한을 다시 설정합니다.Each request that passes through the Session Middleware resets the timeout.

세션 상태는 잠그지 않음입니다.Session state is non-locking. 두 요청이 동시에 세션의 콘텐츠를 수정하려고 하는 경우 마지막 요청이 첫 번째 요청을 재정의합니다.If two requests simultaneously attempt to modify the contents of a session, the last request overrides the first. Session일관된 세션으로 구현됩니다. 즉, 모든 콘텐츠는 함께 저장됩니다.Session is implemented as a coherent session, which means that all the contents are stored together. 두 요청이 서로 다른 세션 값을 수정하려고 할 때 마지막 요청이 첫 번째 요청에 의해 수행된 세션 변경 내용을 재정의할 수 있습니다.When two requests seek to modify different session values, the last request may override session changes made by the first.

세션 값 설정 및 가져오기Set and get Session values

세션 상태는 HttpContext.Session이 포함된 Razor Pages PageModel 클래스 또는 MVC Controller 클래스에서 액세스됩니다.Session state is accessed from a Razor Pages PageModel class or MVC Controller class with HttpContext.Session. 이 속성은 ISession 구현입니다.This property is an ISession implementation.

ISession 구현은 정수 및 문자열 값을 설정 및 검색하는 몇 가지 확장 메서드를 제공합니다.The ISession implementation provides several extension methods to set and retreive integer and string values. 확장 메서드는 Microsoft.AspNetCore.Http.Extensions 패키지가 프로젝트에서 참조될 때, Microsoft.AspNetCore.Http 네임스페이스에 있습니다(확장 메서드에 액세스하려면 using Microsoft.AspNetCore.Http; 문 추가).The extension methods are in the Microsoft.AspNetCore.Http namespace (add a using Microsoft.AspNetCore.Http; statement to gain access to the extension methods) when the Microsoft.AspNetCore.Http.Extensions package is referenced by the project. 두 패키지 모두 Microsoft.AspNetCore.App 메타패키지에 포함되어 있습니다.Both packages are included in the Microsoft.AspNetCore.App metapackage.

ISession 구현은 정수 및 문자열 값을 설정 및 검색하는 몇 가지 확장 메서드를 제공합니다.The ISession implementation provides several extension methods to set and retreive integer and string values. 확장 메서드는 Microsoft.AspNetCore.Http.Extensions 패키지가 프로젝트에서 참조될 때, Microsoft.AspNetCore.Http 네임스페이스에 있습니다(확장 메서드에 액세스하려면 using Microsoft.AspNetCore.Http; 문 추가).The extension methods are in the Microsoft.AspNetCore.Http namespace (add a using Microsoft.AspNetCore.Http; statement to gain access to the extension methods) when the Microsoft.AspNetCore.Http.Extensions package is referenced by the project.

ISession 확장명 메서드:ISession extension methods:

다음 예제에서는 Razor Pages 페이지에서 IndexModel.SessionKeyName 키(샘플 앱의 _Name)의 세션 값을 검색합니다.The following example retrieves the session value for the IndexModel.SessionKeyName key (_Name in the sample app) in a Razor Pages page:

@page
@using Microsoft.AspNetCore.Http
@model IndexModel

...

Name: @HttpContext.Session.GetString(IndexModel.SessionKeyName)

다음 예제에서는 정수와 문자열을 설정하고 가져오는 방법을 보여 줍니다.The following example shows how to set and get an integer and a string:

public class IndexModel : PageModel
{
    public const string SessionKeyName = "_Name";
    public const string SessionKeyAge = "_Age";
    const string SessionKeyTime = "_Time";

    public string SessionInfo_Name { get; private set; }
    public string SessionInfo_Age { get; private set; }
    public string SessionInfo_CurrentTime { get; private set; }
    public string SessionInfo_SessionTime { get; private set; }
    public string SessionInfo_MiddlewareValue { get; private set; }

    public void OnGet()
    {
        // Requires: using Microsoft.AspNetCore.Http;
        if (string.IsNullOrEmpty(HttpContext.Session.GetString(SessionKeyName)))
        {
            HttpContext.Session.SetString(SessionKeyName, "The Doctor");
            HttpContext.Session.SetInt32(SessionKeyAge, 773);
        }

        var name = HttpContext.Session.GetString(SessionKeyName);
        var age = HttpContext.Session.GetInt32(SessionKeyAge);
public class HomeController : Controller
{
    const string SessionKeyName = "_Name";
    const string SessionKeyYearsMember = "_YearsMember";
    const string SessionKeyDate = "_Date";

    public IActionResult Index()
    {
        // Requires using Microsoft.AspNetCore.Http;
        HttpContext.Session.SetString(SessionKeyName, "Rick");
        HttpContext.Session.SetInt32(SessionKeyYearsMember, 3);

        return RedirectToAction("SessionNameYears");
    }

    public IActionResult SessionNameYears()
    {
        var name = HttpContext.Session.GetString(SessionKeyName);
        var yearsMember = HttpContext.Session.GetInt32(SessionKeyYearsMember);

        return Content($"Name: \"{name}\",  Membership years: \"{yearsMember}\"");
    }

메모리 내 캐시를 사용하는 경우에도, 분산된 캐시 시나리오를 사용하려면 모든 세션 데이터를 직렬화해야 합니다.All session data must be serialized to enable a distributed cache scenario, even when using the in-memory cache. 최소 문자열 및 숫자 직렬화가 제공됩니다(ISession의 메서드와 확장 메서드 참조).Minimal string and number serializers are provided (see the methods and extension methods of ISession). 복합 형식은 JSON과 같은 다른 메커니즘을 사용하여 사용자가 직렬화해야 합니다.Complex types must be serialized by the user using another mechanism, such as JSON.

다음 확장 메서드를 추가하여 직렬화 가능 개체를 설정하고 가져옵니다.Add the following extension methods to set and get serializable objects:

public static class SessionExtensions
{
    public static void Set<T>(this ISession session, string key, T value)
    {
        session.SetString(key, JsonConvert.SerializeObject(value));
    }

    public static T Get<T>(this ISession session, string key)
    {
        var value = session.GetString(key);

        return value == null ? default(T) : 
            JsonConvert.DeserializeObject<T>(value);
    }
}
public static class SessionExtensions
{
    public static void Set<T>(this ISession session, string key, T value)
    {
        session.SetString(key, JsonConvert.SerializeObject(value));
    }

    public static T Get<T>(this ISession session,string key)
    {
        var value = session.GetString(key);
        return value == null ? default(T) : 
            JsonConvert.DeserializeObject<T>(value);
    }
}

다음 예제에서는 확장 메서드를 사용하여 직렬화 가능 개체를 설정하고 가져오는 방법을 보여 줍니다.The following example shows how to set and get a serializable object with the extension methods:

// Requires you add the Set and Get extension method mentioned in the topic.
if (HttpContext.Session.Get<DateTime>(SessionKeyTime) == default(DateTime))
{
    HttpContext.Session.Set<DateTime>(SessionKeyTime, currentTime);
}
public IActionResult SetDate()
{
    // Requires you add the Set extension method mentioned in the topic.
    HttpContext.Session.Set<DateTime>(SessionKeyDate, DateTime.Now);

    return RedirectToAction("GetDate");
}

public IActionResult GetDate()
{
    // Requires you add the Get extension method mentioned in the topic.
    var date = HttpContext.Session.Get<DateTime>(SessionKeyDate);
    var sessionTime = date.TimeOfDay.ToString();
    var currentTime = DateTime.Now.TimeOfDay.ToString();

    return Content($"Current time: {currentTime} - "
                 + $"session time: {sessionTime}");
}

TempDataTempData

ASP.NET Core는 Razor Pages 페이지 모델의 TempData 속성 또는 MVC 컨트롤러의 TempData를 공개합니다.ASP.NET Core exposes the TempData property of a Razor Pages page model or TempData of an MVC controller. 이 속성은 판독될 때까지 데이터를 저장합니다.This property stores data until it's read. KeepPeek 메서드를 사용하여 삭제 없이 데이터를 검사할 수 있습니다.The Keep and Peek methods can be used to examine the data without deletion. TempData는 두 개 이상의 요청에 데이터가 필요한 리디렉션에 특히 유용합니다.TempData is particularly useful for redirection when data is required for more than a single request. TempData는 TempData 공급자가 쿠키 또는 세션 상태를 사용하여 구현합니다.TempData is implemented by TempData providers using either cookies or session state.

TempData 공급자TempData providers

ASP.NET Core 2.0 이상에서 쿠키 기반 TempData 공급자는 TempData를 쿠키에 저장하는 데 기본적으로 사용됩니다.In ASP.NET Core 2.0 or later, the cookie-based TempData provider is used by default to store TempData in cookies.

쿠키 데이터는 IDataProtector를 사용하여 암호화되고, Base64UrlTextEncoder로 인코딩된 후 청크 분할됩니다.The cookie data is encrypted using IDataProtector, encoded with Base64UrlTextEncoder, then chunked. 쿠키가 청크 분할되므로 ASP.NET Core 1.x에서 확인한 단일 쿠키 크기 제한은 적용되지 않습니다.Because the cookie is chunked, the single cookie size limit found in ASP.NET Core 1.x doesn't apply. 암호화된 데이터를 압축하는 것은 범죄위반 공격과 같은 보안 문제를 일으킬 수 있으므로 쿠키 데이터는 압축되지 않습니다.The cookie data isn't compressed because compressing encrypted data can lead to security problems such as the CRIME and BREACH attacks. 쿠키 기반 TempData 공급자에 대한 자세한 내용은 CookieTempDataProvider를 참조하세요.For more information on the cookie-based TempData provider, see CookieTempDataProvider.

ASP.NET Core 1.0 및 1.1에서는 세션 상태 TempData 공급자가 기본 공급자입니다.In ASP.NET Core 1.0 and 1.1, the session state TempData provider is the default provider.

TempData 공급자 선택Choose a TempData provider

TempData 공급자를 선택하는 데는 다음과 같은 몇 가지 고려 사항이 수반됩니다.Choosing a TempData provider involves several considerations, such as:

  1. 앱이 이미 세션 상태를 사용합니까?Does the app already use session state? 그런 경우 세션 상태 TempData 공급자 사용에는 앱에 대한 추가 비용이 없습니다(데이터 크기 제외).If so, using the session state TempData provider has no additional cost to the app (aside from the size of the data).
  2. 앱은 상대적으로 적은 양의 데이터에 TempData만 제한적으로 사용합니까(최대 500바이트)?Does the app use TempData only sparingly for relatively small amounts of data (up to 500 bytes)? 그런 경우 쿠키 TempData 공급자는 TempData를 전달하는 각 요청에 적은 비용을 추가합니다.If so, the cookie TempData provider adds a small cost to each request that carries TempData. 그렇지 않은 경우 세션 상태 TempData 공급자는 TempData가 사용될 때까지 각 요청에서 많은 양의 데이터를 왕복 작업하지 않도록 하는 데 도움이 될 수 있습니다.If not, the session state TempData provider can be beneficial to avoid round-tripping a large amount of data in each request until the TempData is consumed.
  3. 앱이 여러 서버의 서버 팜에서 실행됩니까?Does the app run in a server farm on multiple servers? 그런 경우 데이터 보호 외부에서 쿠키 TempData 공급자를 사용하는 데 필요한 추가 구성은 없습니다(데이터 보호키 저장소 공급자 참조).If so, there's no additional configuration required to use the cookie TempData provider outside of Data Protection (see Data Protection and Key storage providers).

참고

대부분의 웹 클라이언트(예: 웹 브라우저)는 각 쿠키의 최대 크기, 쿠키의 총 수 또는 둘 다에 제한을 적용합니다.Most web clients (such as web browsers) enforce limits on the maximum size of each cookie, the total number of cookies, or both. 쿠키 TempData 공급자를 사용하는 경우 앱이 이러한 제한을 초과하지 않는지 확인합니다.When using the cookie TempData provider, verify the app won't exceed these limits. 데이터의 총 크기를 고려합니다.Consider the total size of the data. 암호화 및 청크 분할로 인한 쿠키 크기 증가를 고려합니다.Account for increases in cookie size due to encryption and chunking.

TempData 공급자 구성Configure the TempData provider

쿠키 기반 TempData 공급자는 기본적으로 활성화됩니다.The cookie-based TempData provider is enabled by default.

세션 기반 TempData 공급자를 활성화하려면 AddSessionStateTempDataProvider 확장 메서드를 사용합니다.To enable the session-based TempData provider, use the AddSessionStateTempDataProvider extension method:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
        .AddSessionStateTempDataProvider();

    services.AddSession();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();
    app.UseSession();
    app.UseMvc();
}

다음 Startup 클래스 코드는 세션 기반 TempData 공급자를 구성합니다.The following Startup class code configures the session-based TempData provider:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddSession();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseSession();
    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

미들웨어의 순서가 중요합니다.The order of middleware is important. 앞의 예에서 UseMvc 이후에 UseSession이 호출되면 InvalidOperationException 예외가 발생합니다.In the preceding example, an InvalidOperationException exception occurs when UseSession is invoked after UseMvc. 자세한 내용은 미들웨어 순서 지정을 참조하세요.For more information, see Middleware Ordering.

중요

.NET Framework를 대상으로 하고 세션 기반 TempData 공급자를 사용하는 경우 Microsoft.AspNetCore.Session 패키지를 프로젝트에 추가합니다.If targeting .NET Framework and using the session-based TempData provider, add the Microsoft.AspNetCore.Session package to the project.

쿼리 문자열Query strings

제한된 양의 데이터는 새 요청의 쿼리 문자열에 추가하여 한 요청에서 다른 요청으로 전달할 수 있습니다.A limited amount of data can be passed from one request to another by adding it to the new request's query string. 이는 이메일 또는 소셜 네트워크를 통해 공유되도록 포함된 상태가 있는 링크를 허용하는 영구적인 방식으로 상태를 캡처하는 데 유용합니다.This is useful for capturing state in a persistent manner that allows links with embedded state to be shared through email or social networks. URL 쿼리 문자열은 공용이므로 중요한 데이터에 쿼리 문자열을 사용하지 마세요.Because URL query strings are public, never use query strings for sensitive data.

의도하지 않은 공유 외에도 쿼리 문자열에 데이터를 포함하면 사용자가 인증되는 동안 악성 사이트를 방문하도록 유도할 수 있는 CSRF(교차 사이트 요청 위조) 공격에 대한 기회를 만들 수 있습니다.In addition to unintended sharing, including data in query strings can create opportunities for Cross-Site Request Forgery (CSRF) attacks, which can trick users into visiting malicious sites while authenticated. 공격자는 앱에서 사용자 데이터를 도용하거나 사용자를 대신하여 악의적인 작업을 수행할 수 있습니다.Attackers can then steal user data from the app or take malicious actions on behalf of the user. 유지된 모든 앱 또는 세션 상태를 CSRF 공격으로부터 보호해야 합니다.Any preserved app or session state must protect against CSRF attacks. 자세한 내용은 교차 사이트 요청 위조(XSRF/CSRF) 공격 방지를 참조하세요.For more information, see Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks.

숨겨진 필드Hidden fields

데이터는 숨겨진 양식 필드에 저장되고 다음 요청에서 다시 게시될 수 있습니다.Data can be saved in hidden form fields and posted back on the next request. 이는 다중 페이지 폼에서 일반적입니다.This is common in multi-page forms. 클라이언트는 잠재적으로 데이터를 변조할 수 있으므로 앱은 항상 숨겨진 필드에 저장된 데이터의 유효성을 다시 검사해야 합니다.Because the client can potentially tamper with the data, the app must always revalidate the data stored in hidden fields.

HttpContext.ItemsHttpContext.Items

HttpContext.Items 컬렉션은 단일 요청을 처리하는 동안 데이터를 저장하는 데 사용됩니다.The HttpContext.Items collection is used to store data while processing a single request. 컬렉션의 콘텐츠는 요청이 처리된 후 삭제됩니다.The collection's contents are discarded after a request is processed. Items 컬렉션은 구성 요소 또는 미들웨어가 요청 중에 다른 시점에서 작동하고 매개 변수를 전달할 직접적인 방법이 없는 경우에 통신을 지원하기 위해 자주 사용됩니다.The Items collection is often used to allow components or middleware to communicate when they operate at different points in time during a request and have no direct way to pass parameters.

다음 예제에서 미들웨어Items 컬렉션에 isVerified를 추가합니다.In the following example, middleware adds isVerified to the Items collection.

app.Use(async (context, next) =>
{
    // perform some verification
    context.Items["isVerified"] = true;
    await next.Invoke();
});

파이프라인의 뒷부분에서 다른 미들웨어는 isVerified 값에 액세스할 수 있습니다.Later in the pipeline, another middleware can access the value of isVerified:

app.Run(async (context) =>
{
    await context.Response.WriteAsync($"Verified: {context.Items["isVerified"]}");
});

단일 앱에서만 사용되는 미들웨어의 경우 string 키가 허용됩니다.For middleware that's only used by a single app, string keys are acceptable. 앱 인스턴스 간에 공유되는 미들웨어는 키 충돌을 방지하기 위해 고유한 개체 키를 사용해야 합니다.Middleware shared between app instances should use unique object keys to avoid key collisions. 다음 예제에서는 미들웨어 클래스에 정의된 고유한 개체 키를 사용하는 방법을 보여 줍니다.The following example shows how to use a unique object key defined in a middleware class:

public class HttpContextItemsMiddleware
{
    private readonly RequestDelegate _next;
    public static readonly object HttpContextItemsMiddlewareKey = new Object();

    public HttpContextItemsMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        httpContext.Items[HttpContextItemsMiddlewareKey] = "K-9";

        await _next(httpContext);
    }
}

public static class HttpContextItemsMiddlewareExtensions
{
    public static IApplicationBuilder 
        UseHttpContextItemsMiddleware(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<HttpContextItemsMiddleware>();
    }
}
// You may need to install the Microsoft.AspNetCore.Http.Abstractions package
public class HttpContextItemsMiddleware
{
    private readonly RequestDelegate _next;
    public static readonly object HttpContextItemsMiddlewareKey = new Object();

    public HttpContextItemsMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        httpContext.Items[HttpContextItemsMiddlewareKey] = "K-9";

        await _next(httpContext);
    }
}

public static class HttpContextItemsMiddlewareExtensions
{
    public static IApplicationBuilder 
        UseHttpContextItemsMiddleware(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<HttpContextItemsMiddleware>();
    }
}

다른 코드는 미들웨어 클래스에 의해 노출된 키를 사용하여 HttpContext.Items에 저장된 값에 액세스할 수 있습니다.Other code can access the value stored in HttpContext.Items using the key exposed by the middleware class:

HttpContext.Items
    .TryGetValue(HttpContextItemsMiddleware.HttpContextItemsMiddlewareKey, 
        out var middlewareSetValue);
SessionInfo_MiddlewareValue = 
    middlewareSetValue?.ToString() ?? "Middleware value not set!";
public IActionResult GetMiddlewareValue()
{
    var middlewareSetValue = 
        HttpContext.Items[HttpContextItemsMiddleware.HttpContextItemsMiddlewareKey];

    return Content($"Value: {middlewareSetValue}");
}

이 방법은 또한 코드에서 키 문자열을 사용하지 않아도 된다는 이점이 있습니다.This approach also has the advantage of eliminating the use of key strings in the code.

캐시Cache

캐싱은 데이터 저장 및 검색하는 효율적인 방법입니다.Caching is an efficient way to store and retrieve data. 앱은 캐시된 항목의 수명을 제어할 수 있습니다.The app can control the lifetime of cached items.

캐시된 데이터는 특정 요청, 사용자 또는 세션과 연관되지 않습니다.Cached data isn't associated with a specific request, user, or session. 다른 사용자의 요청으로 검색될 수 있는 사용자별 데이터를 캐시하지 않도록 주의합니다.Be careful not to cache user-specific data that may be retrieved by other users' requests.

자세한 내용은 캐시 응답 항목을 참조하세요.For more information, see the Cache responses topic.

종속성 주입Dependency Injection

종속성 주입을 사용하여 모든 사용자에게 데이터를 사용할 수 있도록 합니다.Use Dependency Injection to make data available to all users:

  1. 데이터를 포함하는 서비스를 정의합니다.Define a service containing the data. 예를 들어 MyAppData라는 클래스가 정의됩니다.For example, a class named MyAppData is defined:

    public class MyAppData
    {
        // Declare properties and methods
    }
    
  2. Startup.ConfigureServices에 서비스 클래스를 추가합니다.Add the service class to Startup.ConfigureServices:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<MyAppData>();
    }
    
  3. 데이터 서비스 클래스를 사용합니다.Consume the data service class:

    public class IndexModel : PageModel
    {
        public IndexModel(MyAppData myService)
        {
            // Do something with the service
            //    Examples: Read data, store in a field or property
        }
    }
    
    public class HomeController : Controller
    {
        public HomeController(MyAppData myService)
        {
            // Do something with the service
            //    Examples: Read data, store in a field or property
        }
    }
    

일반적인 오류Common errors

  • "'Microsoft.AspNetCore.Session.DistributedSessionStore'를 활성화하려고 시도하는 동안 'Microsoft.Extensions.Caching.Distributed.IDistributedCache' 형식에 대한 서비스를 확인할 수 없습니다.""Unable to resolve service for type 'Microsoft.Extensions.Caching.Distributed.IDistributedCache' while attempting to activate 'Microsoft.AspNetCore.Session.DistributedSessionStore'."

    이는 일반적으로는 하나 이상의 IDistributedCache 구현을 구성하는 데 실패하여 발생됩니다.This is usually caused by failing to configure at least one IDistributedCache implementation. 자세한 내용은 분산 캐시 사용메모리 내 캐시를 참조하세요.For more information, see Work with a distributed cache and Cache in-memory.

  • 세션 미들웨어가 세션 유지에 실패할 경우(예: 백업 저장소를 사용할 수 없는 경우) 미들웨어는 예외를 기록하고 요청은 정상적으로 계속됩니다.In the event that the session middleware fails to persist a session (for example, if the backing store isn't available), the middleware logs the exception and the request continues normally. 이로 인해 예기치 않은 동작이 발생합니다.This leads to unpredictable behavior.

    예를 들어 사용자는 세션에 쇼핑 카트를 저장합니다.For example, a user stores a shopping cart in session. 사용자가 카트에 항목을 추가하지만 커밋이 실패합니다.The user adds an item to the cart but the commit fails. 앱은 실패에 대해 알지 못하므로 항목이 카트에 추가되었다고 보고하지만, 이는 사실이 아닙니다.The app doesn't know about the failure so it reports to the user that the item was added to their cart, which isn't true.

    권장되는 오류 확인 방법은 앱이 세션에 작성을 완료하면 앱 코드에서 await feature.Session.CommitAsync();를 호출하는 것입니다.The recommended approach to check for errors is to call await feature.Session.CommitAsync(); from app code when the app is done writing to the session. 백업 저장소를 사용할 수 없는 경우 CommitAsync에서 예외를 throw합니다.CommitAsync throws an exception if the backing store is unavailable. CommitAsync가 실패하면 앱에서 예외를 처리할 수 있습니다.If CommitAsync fails, the app can process the exception. LoadAsync는 같은 조건에서 데이터 저장소를 사용할 수 없는 경우 throw됩니다.LoadAsync throws under the same conditions where the data store is unavailable.

추가 자료Additional resources

웹 팜에 ASP.NET Core 호스트