Share via


ASP.NET 뷰 상태 개요

업데이트: 2007년 11월

뷰 상태는 ASP.NET 페이지 프레임워크에서 라운드트립 간에 페이지 및 컨트롤 값을 유지하기 위해 사용하는 방법입니다. 페이지에 대한 HTML 태그가 렌더링되면 포스트백 동안 유지해야 할 값과 페이지의 현재 상태가 base64로 인코딩된 문자열로 serialize됩니다. 그런 다음 이 정보는 뷰 상태 숨김 필드에 배치됩니다.

이 항목의 내용은 다음과 같습니다.

  • 시나리오

  • ViewState 기능

  • 배경

  • 클래스 참조

  • 추가 리소스

  • 새로운 기능

시나리오

뷰 상태는 포스트백 간에 유지되어야 하는 정보를 보존하기 위해 ASP.NET 페이지 프레임워크에 의해 자동으로 사용됩니다. 이 정보에는 컨트롤의 기본값이 아닌 값이 포함됩니다.

뷰 상태를 사용하여 페이지 고유의 응용 프로그램 데이터를 저장할 수도 있습니다.

맨 위로 이동

기능

뷰 상태는 포스트백 동안 유지해야 하는 값을 저장할 수 있는 ASP.NET 페이지의 리포지토리입니다. 페이지 프레임워크는 뷰 상태를 사용하여 포스트백 간에 컨트롤 설정을 유지합니다.

사용자 응용 프로그램에서 뷰 상태를 사용하여 다음을 수행할 수 있습니다.

  • 세션 상태 또는 사용자 프로필에 저장하지 않고 값을 포스트백 간에 유지합니다.

  • 정의한 페이지 또는 컨트롤 속성의 값을 저장합니다.

  • SQL Server 데이터베이스 또는 다른 데이터 저장소에 뷰 상태 정보를 저장할 수 있도록 하는 사용자 지정 뷰 상태 공급자를 만듭니다.

예를 들어 정보를 뷰 상태에 저장하면 다음 번에 페이지가 서버로 전송될 때 페이지를 로드하는 동안 사용자 코드에서 이 정보에 액세스할 수 있습니다. 사용과 관련된 권장 사항을 보려면 ASP.NET 상태 관리 권장 사항을 참조하십시오.

맨 위로 이동

배경

웹 응용 프로그램은 상태 비저장 특성을 가지고 있습니다. 서버에서 페이지가 요청될 때마다 웹 페이지 클래스의 새 인스턴스가 만들어집니다. 이렇게 되면 일반적으로 라운드트립이 발생할 때마다 페이지 및 해당 컨트롤에 있는 모든 정보가 손실됩니다. 예를 들어 기본적으로 사용자가 HTML 웹 페이지의 텍스트 상자에 정보를 입력하면 해당 정보가 서버로 전송되지만 이 정보가 브라우저에 반환되는 응답에 포함되지는 않습니다.

웹 프로그래밍의 이러한 본질적인 제한을 해결하기 위해 ASP.NET 페이지 프레임워크에서는 웹 서버에 대한 라운드트립이 발생할 때마다 페이지 및 컨트롤 값을 유지할 수 있는 몇 가지 상태 관리 기능을 제공합니다. 이러한 기능 중 하나가 뷰 상태입니다(ASP.NET 상태 관리 개요).

기본적으로 ASP.NET 페이지 프레임워크는 뷰 상태를 사용하여 라운드트립 간에 페이지 및 컨트롤 값을 유지합니다. 페이지에 대한 HTML이 렌더링되면 포스트백 동안 유지해야 할 값과 페이지의 현재 상태가 base64로 인코딩된 문자열로 serialize됩니다. 그런 다음 이 문자열은 페이지의 숨김 필드에 배치됩니다.

페이지의 ViewState 속성을 사용하여 코드에서 뷰 상태에 액세스할 수 있습니다. ViewState 속성은 뷰 상태 데이터가 포함된 키/값 쌍이 들어 있는 사전입니다.

보안 정보:

악의가 있는 사용자는 간단한 방법으로 숨김 필드의 내용을 보고 수정할 수 있습니다. 뷰 상태 데이터를 보호하는 방법에 대한 자세한 내용은 이 항목 뒷부분의 뷰 상태 보안을 참조하십시오.

뷰 상태에 정보를 저장해야 하는 경우에 유용한 권장 사항을 보려면 ASP.NET 상태 관리 권장 사항을 참조하십시오.

사용자 지정 PageStatePersister 클래스를 구현하여 페이지 데이터를 저장하면 기본 동작을 변경하고 뷰 상태를 SQL Server 데이터베이스 같은 다른 위치에 저장할 수 있습니다. 페이지 상태를 숨김 필드 대신 스트림에 저장하는 방법에 대한 예제는 PageStatePersister 클래스의 예제를 참조하십시오.

뷰 상태를 사용할 때 고려할 사항

뷰 상태는 특정 ASP.NET 페이지에 대한 상태 정보를 제공합니다. 여러 페이지에 대한 정보를 사용해야 하거나 웹 사이트를 방문할 때마다 정보를 유지해야 할 경우에는 다른 방법을 사용하여 상태를 유지 관리해야 합니다. 응용 프로그램 상태, 세션 상태 또는 프로필 속성을 사용할 수 있습니다.

뷰 상태 정보는 XML로 serialize된 다음 base-64 인코딩을 사용하여 인코딩되며 이런 경우 많은 양의 데이터가 생성될 수 있습니다. 페이지가 서버에 게시될 때 뷰 상태의 내용은 페이지 포스트백 정보의 일부분으로 전송됩니다. 뷰 상태에 많은 양의 정보가 포함되면 페이지 성능에 영향을 줄 수 있습니다. 뷰 상태의 크기로 인해 성능 문제가 발생하는지 확인하기 위해 응용 프로그램에서 일반적인 데이터를 사용하여 페이지 성능을 테스트하십시오. 뷰 상태를 사용하는 다른 방법을 보려면 ASP.NET 상태 관리 권장 사항을 참조하십시오.

개별 컨트롤에 대한 컨트롤 정보를 저장할 필요가 없을 경우에는 컨트롤의 뷰 상태를 사용하지 않도록 설정할 수 있습니다. 포스트백할 때마다 페이지의 컨트롤이 데이터 저장소로부터 새로 고쳐질 경우에는 뷰 상태의 크기를 줄이기 위해 해당 컨트롤의 뷰 상태를 비활성화할 수 있습니다. 예를 들어 GridView 컨트롤과 같은 컨트롤의 뷰 상태를 비활성화할 수 있습니다.

참고:

뷰 상태 기능을 명시적으로 해제하더라도 페이지에 대해 다시 게시가 발생하고 있음을 나타내기 위해 숨김 필드가 브라우저에 전송됩니다.

또 다른 고려 사항은 숨김 필드의 데이터 양이 커지면 일부 프록시와 방화벽에서 이를 포함하는 페이지에 액세스하지 못하게 한다는 점입니다. 허용되는 최대 데이터 양은 방화벽 및 프록시 구현에 따라 달라질 수 있으므로 숨김 필드가 클 경우 간헐적으로 문제가 발생할 수 있습니다. ViewState 속성에 저장된 데이터의 양이 페이지의 MaxPageStateFieldLength 속성에 지정된 값을 초과하면 해당 페이지가 뷰 상태를 여러 개의 숨김 필드로 분할합니다. 따라서 개별 숨김 필드의 크기가 방화벽이 거부하는 크기 아래로 줄어듭니다.

일부 모바일 장치에서는 숨겨진 필드를 전혀 사용할 수 없습니다. 따라서 이러한 장치에서는 뷰 상태가 작동하지 않습니다. 자세한 내용 및 다른 방법을 보려면 ASP.NET 모바일 웹 개발 개요를 참조하십시오.

컨트롤 상태

뷰 상태 외에도 ASP.NET은 컨트롤 상태를 지원합니다. 페이지 또는 컨트롤에 대해 뷰 상태가 해제되어 있더라도 페이지에서는 컨트롤 상태를 사용하여 다시 게시할 때마다 컨트롤 정보를 유지할 수 있습니다. 뷰 상태와 마찬가지로 컨트롤 상태도 하나 이상의 숨김 필드에 저장됩니다.

뷰 상태에 값 저장

사전 개체를 노출하는 페이지의 ViewState 속성을 사용하여 뷰 상태 정보에 액세스할 수 있습니다. 이 사전을 사용하여 사용자 지정 값을 저장할 수 있습니다. 일반적인 용도는 페이지에서 정의한 사용자 지정 속성의 값을 저장하는 것입니다.

뷰 상태는 숨김 필드로 전송되므로 페이지의 PreRenderComplete 이벤트가 발생하기 전까지는 뷰 상태를 변경할 수 있습니다. 페이지가 브라우저에 렌더링된 후에는 뷰 상태 변경 내용이 저장되지 않습니다.

웹 페이지의 소스를 보고 base-64로 인코딩된 문자열을 디코딩할 수 있는 사용자는 숨김 뷰 상태 필드에 있는 정보를 볼 수 있습니다. 이로 인해 보안 문제가 발생할 수 있습니다. 뷰 상태의 보안 문제에 대한 자세한 내용은 이 항목 뒷부분의 뷰 상태 보안을 참조하십시오.

참고:

ViewState 속성을 사용하려면 ASP.NET 웹 페이지에 특성이 있는 form 요소가 있어야 합니다.

뷰 상태에 값을 저장하려면 저장할 값을 포함하는 새 항목을 만든 다음 뷰 상태 사전에 추가하십시오. 다음 예제에서는 뷰 상태에 문자열 및 정수 값을 저장하는 코드가 있는 ASP.NET 웹 페이지를 보여 줍니다.

<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script >
  ' Sample ArrayList for the page.
  Dim PageArrayList As ArrayList

  Function CreateArray() As ArrayList
    ' Create a sample ArrayList.
    Dim result As ArrayList
    result = New ArrayList(4)
    result.Add("item 1")
    result.Add("item 2")
    result.Add("item 3")
    result.Add("item 4")
    Return result
  End Function

  Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
    If (Me.ViewState("arrayListInViewState") IsNot Nothing) Then
      PageArrayList = CType(Me.ViewState("arrayListInViewState"), ArrayList)
    Else
      ' ArrayList isn't in view state, so it must be created and populated.
      PageArrayList = CreateArray()
    End If
    ' Code that uses PageArrayList.
  End Sub

  Sub Page_PreRender(ByVal sender As Object, ByVal e As EventArgs)
    ' Save PageArrayList before the page is rendered.
    Me.ViewState.Add("arrayListInViewState", PageArrayList)
  End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head >
    <title>View state sample</title>
</head>
<body>
    <form id="form1" >
    <div>
    </div>
    </form>
</body>
</html>

<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script >
  // Sample ArrayList for the page.
  ArrayList PageArrayList;

  ArrayList CreateArray()
  {
    // Create a sample ArrayList.
    ArrayList result = new ArrayList(4);
    result.Add("item 1");
    result.Add("item 2");
    result.Add("item 3");
    result.Add("item 4");
    return result;
  }

  void Page_Load(object sender, EventArgs e)
  {
    if (ViewState["arrayListInViewState"] != null)
    {
      PageArrayList = (ArrayList)ViewState["arrayListInViewState"];
    }
    else
    {
      // ArrayList isn't in view state, so it must be created and populated.
      PageArrayList = CreateArray();
    }
    // Code that uses PageArrayList.
  }
    
  void Page_PreRender(object sender, EventArgs e)
  {
    // Save PageArrayList before the page is rendered.
    ViewState.Add("arrayListInViewState", PageArrayList);
  }
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head >
    <title>View state sample</title>
</head>
<body>
    <form id="form1" >
    <div>
    </div>
    </form>
</body>
</html>

뷰 상태에 저장할 수 있는 데이터 형식

다음과 같은 형식의 개체를 뷰 상태에 저장할 수 있습니다.

  • Strings

  • 정수

  • Boolean 값

  • Array 개체

  • ArrayList 개체

  • 해시 테이블

  • 사용자 지정 형식 변환기. 자세한 내용은 TypeConverter 클래스를 참조하십시오.

다른 데이터 형식도 저장할 수 있지만 뷰 상태에 대해 해당 값을 serialize할 수 있도록 Serializable 특성을 사용하여 클래스를 컴파일해야 합니다.

뷰 상태에서 값 읽기

뷰 상태에서 값을 읽으려면 페이지의 ViewState 속성을 가져온 다음 뷰 상태 사전에서 값을 읽습니다.

다음 예제에서는 뷰 상태에서 arrayListInViewState라는 ArrayList 개체를 가져온 다음 이 개체에 GridView 컨트롤을 데이터 소스로 바인딩하는 방법을 보여 줍니다.

Dim arrayList As ArrayList
arrayList = CType(ViewState("arrayListInViewState"), ArrayList)

Me.GridView1.DataSource = arrayList
Me.GridView1.DataBind()

arrayList = new ArrayList();
arrayList = (ArrayList)ViewState["arrayListInViewState"];

this.GridView1.DataSource = arrayList;
this.GridView1.DataBind();

뷰 상태에 있는 값은 String으로 형식화됩니다. Visual Basic에서는 Option Strict On을 설정할 경우 이전 예제와 같이 뷰 상태 값을 사용하기 전에 적절한 형식으로 캐스팅해야 합니다. C#에서는 항상 뷰 상태 값을 읽을 때 적절한 형식으로 캐스팅해야 합니다.

뷰 상태에서 존재하지 않는 값을 가져오려는 경우 예외가 throw되지 않습니다. 뷰 상태에 값이 있는지 확인하려면 먼저 개체가 존재하는지 확인하십시오. 다음 예제에서는 뷰 상태 항목을 확인하는 방법을 보여 줍니다.

If ViewState("color") Is Nothing Then
    ' No such value in view state, take appropriate action.
End If
if (ViewState["color"] == null)
    // No such value in view state, take appropriate action.

형식 검사 등 다른 방법으로 존재하지 않는 뷰 상태 항목을 사용하려고 하면 NullReferenceException 예외가 throw됩니다.

맨 위로 이동

뷰 상태 보안

기본적으로 뷰 상태 데이터는 페이지에서 숨김 필드로 저장되고 base64 인코딩을 사용하여 인코딩됩니다. 또한 MAC(컴퓨터 인증 코드) 키를 사용하여 데이터에서 뷰 상태 데이터의 해시가 만들어집니다. 해시 값은 인코딩된 뷰 상태 데이터에 추가되고, 결과 문자열은 페이지에 저장됩니다. 페이지가 서버에 포스트백될 때 ASP.NET 페이지 프레임워크는 해시 값을 다시 계산하여 이 값을 뷰 상태에 저장된 값과 비교합니다. 해시 값이 일치하지 않으면 뷰 상태 데이터가 잘못되었을 수 있음을 나타내는 예외가 발생합니다.

해시 값을 만들면 ASP.NET 페이지 프레임워크에서 뷰 상태 데이터가 손상되었는지 여부를 테스트할 수 있습니다. 그러나 손상되지 않은 경우에도 악의적인 사용자가 뷰 상태 데이터를 가로채고 읽을 수 있습니다.

MAC를 사용하여 뷰 상태 해시 값 계산

뷰 상태 해시 값을 비교하는 데 사용되는 MAC 키는 자동 생성되거나 Machine.config 파일에서 지정됩니다. 키가 자동 생성되는 경우에는 컴퓨터의 MAC 주소를 기준으로 생성됩니다. 이 주소는 해당 컴퓨터에서 네트워크 어댑터의 고유한 GUID 값입니다.

악의적인 사용자가 뷰 상태의 해시 값을 기준으로 MAC 키를 리버스 엔지니어링하기는 어렵습니다. 따라서 MAC 인코딩은 일반적으로 뷰 상태 데이터가 변경되었는지 여부를 확인할 수 있는 좋은 방법입니다.

일반적으로 해시 생성에 사용된 MAC 키가 클수록 서로 다른 문자열의 해시 값이 같아질 가능성은 줄어듭니다. 키가 자동으로 생성되는 경우 ASP.NET은 SHA-1 인코딩을 사용하여 큰 키를 만듭니다. 하지만 웹 팜 환경에서는 키가 모든 서버에서 동일해야 합니다. 키가 동일하지 않고 페이지를 만든 서버가 아닌 다른 서버에 페이지가 다시 게시되면 ASP.NET 페이지 프레임워크가 예외를 발생시킵니다. 따라서 웹 팜 환경에서는 ASP.NET에서 키를 자동으로 생성하는 대신 Machine.config 파일에서 키를 지정해야 합니다. 이 경우에는 해시된 값에 충분한 보안을 제공할 수 있을 정도로 긴 키를 만들어야 합니다. 그러나 키가 길수록 해시를 만드는 시간이 오래 걸립니다. 따라서 보안 요구 사항과 성능 요구 사항의 균형을 맞춰야 합니다.

뷰 상태 암호화

MAC 인코딩은 뷰 상태 데이터의 손상을 방지하는 데 도움이 되지만 사용자가 데이터를 보지 못하도록 할 수는 없습니다. 사용자가 이 데이터를 보지 못하도록 하는 방법은 두 가지입니다. 페이지를 SSL로 전송하거나, 뷰 상태 데이터를 암호화하면 됩니다. 페이지를 SSL로 전송하면 페이지를 볼 수 없는 사용자가 무단으로 데이터에 액세스하거나 데이터 패킷을 가로채지 못하도록 방지할 수 있습니다.

하지만 SSL은 페이지의 암호화를 해독하여 브라우저에 표시하기 때문에 페이지를 요청한 사용자는 여전히 뷰 상태 데이터를 볼 수 있습니다. 권한이 있는 사용자가 뷰 상태 데이터에 액세스해도 괜찮은 경우에는 이것이 문제가 되지 않습니다. 그러나 컨트롤에서 사용자가 액세스해서는 안 되는 정보를 뷰 상태를 사용하여 저장해야 하는 경우가 있습니다. 예를 들어, 뷰 상태에 항목 식별자(데이터 키)를 저장하는 데이터 바인딩된 컨트롤이 페이지에 포함될 수 있습니다. 이러한 식별자에 고객 ID와 같은 중요한 데이터가 포함된 경우에는 페이지를 SSL로 전송하는 것 외에도(또는 이 방법 대신) 뷰 상태 데이터를 암호화해야 합니다.

데이터를 암호화하려면 페이지의 ViewStateEncryptionMode 속성을 true로 설정합니다. 뷰 상태에 정보를 저장하는 경우 사용자는 일반적인 읽기 및 쓰기 기술을 사용할 수 있으며, 모든 암호화 및 해독 작업은 페이지에서 처리됩니다. 뷰 상태 데이터를 암호화하면 응용 프로그램의 성능에 영향을 줄 수 있습니다. 따라서 필요할 경우에만 암호화를 사용하십시오.

컨트롤 상태 암호화

컨트롤 상태를 사용하는 컨트롤에서는 RegisterRequiresViewStateEncryption 메서드를 호출하여 뷰 상태를 암호화해야 할 수도 있습니다. 뷰 상태를 암호화해야 하는 컨트롤이 페이지에 있는 경우 페이지에 있는 모든 뷰 상태가 암호화됩니다.

사용자별 뷰 상태 인코딩

웹 사이트에서 사용자를 인증하는 경우 Page_Init 이벤트 처리기에서 ViewStateUserKey 속성을 설정하여 페이지의 뷰 상태를 특정 사용자와 연결할 수 있습니다. 이렇게 하면 원 클릭 공격을 막을 수 있습니다. 원 클릭 공격에서는 악의적인 사용자가 이전에 생성된 페이지의 뷰 상태로 미리 채워진 유효한 웹 페이지를 만들 수 있습니다. 그런 다음 공격자는 공격 대상의 ID를 사용하여 페이지를 서버에 전송하는 링크를 공격 대상이 클릭하도록 유도합니다.

ViewStateUserKey 속성을 설정하면 공격자의 ID를 사용하여 원본 페이지의 뷰 상태에 대한 해시가 만들어집니다. 공격 대상이 페이지를 다시 전송하게 된 경우 사용자 키가 다르기 때문에 해시 값이 달라집니다. 페이지의 유효성 검사가 실패하고 예외가 throw됩니다.

ViewStateUserKey 속성을 사용자 이름 또는 ID와 같이 각 사용자에 대해 고유한 값과 연결해야 합니다.

공유 호스팅 환경의 구성 보안

공유 호스팅 환경에서는 악의적인 사용자가 컴퓨터의 다른 응용 프로그램에 영향을 줄 수 있는 상태 관리 속성을 수정할 가능성이 있습니다. 이 작업은 Machine.config 파일을 직접 수정하거나, 구성 클래스를 통해 수정하거나, 기타 관리 및 구성 도구를 사용하여 수행될 수 있습니다. 구성 파일의 섹션을 암호화하면 응용 프로그램 구성이 수정되지 않도록 방지하는 데 도움이 됩니다. 자세한 내용은 보호되는 구성을 사용하여 구성 정보 암호화를 참조하십시오.

클래스 참조

ViewState

동일한 페이지에 대한 여러 요청 사이에 값을 유지하기 위한 사전 개체를 제공합니다.

PageStatePersister

SQL Server 데이터베이스에서와 같이 뷰 상태 정보를 저장하기 위한 사용자 지정 메커니즘을 정의할 수 있는 수단을 제공합니다.

맨 위로 이동

참고 항목

개념

ASP.NET 상태 관리 개요

ASP.NET 상태 관리 권장 사항

참조

맨 위로 이동