asp.net2006. 2. 24. 00:23

지난번에 모 회사의 그룹웨어 시스템을 만드는 프로젝트에 참가한 적이 있다. ASP.NET 웹애플리케이션인데, 여기 고객들이 어느 날은 웹 페이지의 소스를 보더니, 이상한 것이 있다고 하는 거였다. 뭔지 봤더니 ASP.NET Viewstate를 보시고 말한 것이었다. 실제로, 굉장히 이상해 보인다. 전혀 의미를 알 수 없는 이상한 글자들이 적지도 않게 있으니까. 고객 입장에서는 페이지 속도가 느린 것이 혹시 이것 때문이 아닌가 싶었나 보다.


그럼 Viewstate란? .NET Framework SDK의 설명을 참조해보겠다. "페이지 자체를 포함하여 Web Forms 페이지의 각 컨트롤에는 기본 Control 컨트롤에서 상속된 ViewState 속성이 있습니다. 뷰 상태는 ASP.NET 페이지 프레임워크에서 페이지를 렌더링하기 직전에 페이지와 각 컨트롤 값을 자동으로 저장할 때 사용됩니다. 페이지가 게시될 때 페이지 처리에서 처음 수행되는 작업이 뷰 상태 복원입니다"


그럼, ASP.NET 코드를 한 번 보면

public class WebForm1 : System.Web.UI.Page

{

protected System.Web.UI.WebControls.Label Label1;

protected System.Web.UI.WebControls.Button Button1;

protected System.Web.UI.WebControls.Label Label2;

private void Page_Load(object sender, System.EventArgs e)

{

if(!Page.IsPostBack)

{

this.Label1.Text = "Label1";

this.Label2.Text = "Label2";

}

}

private void Button1_Click(object sender, System.EventArgs e)

{

this.Label2.Text = "Button Clicked";

}

}


페이지가 로드될 때, 라벨1과 라벨2에는 각각의 텍스트가 들어가게 된다. 버튼을 눌러서 Post-Back이 일어난다면 어떻게 될까? 버튼 클릭 이벤트에 있는 대로 라벨2의 텍스트는 "Button clicked"라고 바뀐다. 그러면 label1은? Button_click 이벤트가 일어나기 전에 page_load가 한번 더 실행이 되지만, if문을 사용해서 Page가 IsPostBack이 아닐 때만 라벨에 텍스트를 넣는 코드가 실행이 되는 것이다. 그러면 label1은 비어있을까? 다들 알겠지만, label1에는 "label1"이라는 텍스트가 그대로 유지가 되게 된다. 바로 이 값을 유지하기 위해서, ASP.NET이 페이지와 페이지의 각 컨트롤의 상태를 암호화시킨 형태로 HTML의 히든 필드로 넣어둔 것이 바로 Viewstate이다. 이 코드를 실행시킨 페이지의 소스를 보면 이런 형태로 뷰 스테이트가 들어가 있을 것이다.

<input type="hidden" name="__VIEWSTATE" value="dDwzMTkxMTg2NDc7dDw7bDxpPDE+Oz47bD

x0PDtsPGk8MT47aTwzPjs+O2w8dDxwPHA8bDxUZXh0Oz47bDxMYWJlbDE7Pj47Pjs7Pjt0PH

A8cDxsPFRleHQ7PjtsPEJ1dHRvbiBDbGlja2VkOz4+Oz47Oz47Pj47Pj47PhHZi18rwfZPDuHEtU+

SD6bOswOI" />


그런데 이 뷰스테이트는 양날의 검이라고도 할 수 있다. 개발자들에게는 편리한 프로그래밍 방법을 제공하지만, 주의깊게 사용하지 않는다면 성능에 엄청난 마이너스가 되기 때문이다. 기본적으로 모든 페이지와 모든 컨트롤에 뷰스테이트가 활성화되어 있기 때문이다. 그래서 불필요한 모든 컨트롤에도 뷰스테이트가 들어가게 되는 것이다. 실제로 지금 하고 있는 프로젝트에서 트리 컨트롤을 사용한 페이지가 있었는데, 페이지 로드에서 언제나 모든 데이터를 바인딩하는 로직으로 짜여져 있었기 때문에 뷰스테이트가 전혀 필요없는 구조였다. 그런데 뷰스테이트는 모든 컨트롤에 활성화되어 있었고, 뷰스테이트를 뺐더니 렌더링된 HTML의 사이즈가 70%로 감소했다.

페이지 수준에서 뷰스테이트를 비활성화시킬려면, aspx페이지의 가장 위에 있는 <@Page>지시문에  EnableViewState="false"라고 써주면 된. 컨트롤 태그 에이와 같이 직접 해줘도 된다.

<asp:Label id="Label1" enableViewState="False" runat="server"></asp:Label>


일반적인권장사항은 "서버 컨트롤 뷰 상태는 필요할 때만 저장합니다". 위에서도 말했지만 뷰스테이트는 디폴트로 모두 활성화되어 있기 때문에, 성능에 엄청난 영향을 주는 경우가 아주 많다.

Posted by kkongchi