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 파일을 직접 수정하거나, 구성 클래스를 통해 수정하거나, 기타 관리 및 구성 도구를 사용하여 수행될 수 있습니다. 구성 파일의 섹션을 암호화하면 응용 프로그램 구성이 수정되지 않도록 방지하는 데 도움이 됩니다. 자세한 내용은 보호되는 구성을 사용하여 구성 정보 암호화를 참조하십시오.
클래스 참조
동일한 페이지에 대한 여러 요청 사이에 값을 유지하기 위한 사전 개체를 제공합니다. |
|
SQL Server 데이터베이스에서와 같이 뷰 상태 정보를 저장하기 위한 사용자 지정 메커니즘을 정의할 수 있는 수단을 제공합니다. |
맨 위로 이동
참고 항목
개념
참조
맨 위로 이동