개인 설정은 포털 및 쇼핑 사이트를 포함하여 대부분의 웹 응용 프로그램 유형에서 점점 더 필수적인 요소로 대두되고 있습니다. 이제는 개인 설정을 적용하지 않으면 고객에게 효과적으로 서비스를 제공하기가 어려운 것이 현실입니다. 그러나 프레젠테이션 계층에 개인 설정 계층을 구축하기란 쉽지 않은 일입니다. 우선, 관리가 용이하고 리소스를 지나치게 소비하지 않는 영구 저장소 매체가 있어야 하고, 페이지 제작자가 개인 설정 저장소와 상호 작용하도록 할 API가 필요하며, 사용이 쉽고 형식 안전성을 제공하는 데이터 모델이 있어야 합니다. 마지막으로 관리자와 최종 사용자 모두에게 저장된 데이터와 설정을 관리하는 데 사용할 도구를 제공해야 합니다. 저의 2004년 3월 (영문) 칼럼에서도 언급했듯이, ASP.NET 1.x 응용 프로그램에도 개인 설정 계층을 구축할 수 있지만 이 작업은 수행하기가 까다롭습니다. 다행히도 ASP.NET 2.0에서는 개인 설정 계층을 손쉽게 구축할 수 있도록 하는 새로운 기능이 제공됩니다.
개인 설정의 의미
ASP.NET 개인 설정 기능에는 사용자 프로필, 테마, 오류 페이지 등이 포함됩니다. ASP.NET 사용자 프로필은 안전한 형식의 API를 통해 구조적 데이터를 영구적으로 저장하기 위한 것입니다. 응용 프로그램에서는 개인 설정 기능을 사용하기 위해 고유한 개인 설정 데이터 모델을 정의합니다. 그러면 ASP.NET 런타임에서 해당 모델을 클래스로 구문 분석 및 컴파일하여 나머지 작업을 수행합니다. 개인 설정 데이터 클래스의 각 멤버는 현재 사용자에 대한 정보에 해당합니다. 개인 설정 데이터의 로드 및 저장 작업은 최종 사용자에게 투명하게 이루어지며, 페이지 제작자라도 내부에서 진행되는 작업에 대해 자세히 알 필요가 없습니다. 그림 1에는 이 기사에서 다루는 개인 설정 사이트의 예제가 나와 있습니다.

그림 1 그림 1. 프로필 정보를 소비하는 샘플 페이지
ASP.NET 개인 설정의 테마는 사용자 지정할 수 있는 사이트의 요소에 스타일 및 시각적 특성 집합을 할당합니다. 이러한 요소에는 컨트롤 속성, 페이지 스타일시트, 이미지 및 서식 파일 등이 포함됩니다. 사용자 지정 오류 페이지는 처리되지 않은 예외로 인해 오류가 발생하여 응용 프로그램이 중지되는 경우 사용자에게 중요한 정보를 제공합니다. 이번 기사에서는 사용자 프로필에 대해 알아보고 테마와 오류 페이지에 대해서는 다음 달에 다루겠습니다.
개인 설정 데이터 관리
테마를 적용하고 사용자 지정 오류 페이지를 연결하려면 대개 관리자 권한으로 Web.config 파일을 편집하면 되지만, 현재 로그인되어 있는 사용자의 사용자 프로필을 관리하는 작업을 수행하려면 기능이 추가로 필요합니다. 특히 요청이 처리되기 시작하면 시스템 수준 인프라에서 사용자 데이터를 검색하여 로드해야 합니다. 해당 요청이 끝나면 현재 설정은 동일한 사용자가 다음 번에 요청할 때 검색될 수 있도록 서버에 유지되어야 합니다.
페이지 설정에는 즐겨찾기 링크 목록, 선택한 테마 이름, UI 패널 위치 및 구성 가능한 문자열 등 사용자별 관련 정보가 포함될 수 있습니다. 필요한 경우 관리자는 실제 저장소에 액세스하여 사용자 설정을 편집할 수 있습니다. 그러나 이 기능은 사용 중인 공급자에 따라 달라지는데, 기본 공급자인 SqlProfileProvider는 데이터를 불투명 텍스트 또는 이미지 blob으로 저장하므로 데이터를 직접 편집하기가 어렵습니다. 개별 사용자가 기본 설정을 편집할 수 있도록 하려면 사용자 인터페이스를 제공해야 합니다. 이를 수행하는 가장 일반적인 방법은 클릭하면 페이지가 포스트백(postback)되고 현재 값 및 컨트롤을 포함하는 편집 패널이 표시되도록 하는 몇 개의 링크를 페이지의 고정된 영역에 추가하는 것입니다. 실제로 이와 유사한 방식을 My MSN 및 SharePoint 구동 사이트에서 구현하고 있습니다. 편집 패널은 사용자 지정 컨트롤이거나, 사용자 컨트롤(권장)일 수 있습니다. 이 항목은 이 칼럼의 뒷부분에서 다시 한 번 살펴보고 구체적인 예제를 확인해 보겠습니다.
사용자 프로필 관리
사용자 프로필은 ASP.NET 2.0 런타임이 동적으로 생성된 클래스의 공용 필드로 그룹화하는 값 컬렉션입니다. 이러한 클래스는 시스템 제공 클래스에서 파생되며 새로운 멤버가 몇 개 추가되어 확장됩니다. 이 클래스를 Serializable로 표시할 필요는 없지만 해당 내용은 개별 속성으로 저장소 매체에 유지됩니다. 저장 작업은 사용자별로 수행되며 관리자가 삭제할 때까지 그대로 보관됩니다.
데이터 저장소는 사용자에게는 전혀 표시되지 않으며 개인 설정 API를 사용하는 프로그래머에게도 일부만 표시됩니다. 또한 사용자는 데이터가 저장되는 방법과 위치를 알 필요가 없을 뿐 아니라 프로그래머는 사용할 프로필 데이터 공급자 형식만 표시하면 됩니다. 사용할 저장소(보통 SQL Server 등의 데이터베이스 시스템)와 저장소 내의 데이터 레이아웃은 프로필 공급자에 따라 결정됩니다. 그러나 사용자 지정 공급자 및 사용자 지정 저장소 모델도 사용할 수 있습니다.
ASP.NET 2.0 베타 2(이 칼럼의 모든 예제에 대해 사용함)에서 기본 프로필 공급자는 SQL Server 2005의 무료 버전인 SQL Server Express Edition을 사용합니다. 실제 저장소 매체는 aspnetdb.mdf라는 로컬 파일이며 보통 웹 응용 프로그램의 App_Data 폴더에 있습니다.
응용 프로그램이 실행되어 페이지가 표시되면 ASP.NET은 올바르게 형식이 지정된 데이터가 들어 있는 프로필 개체를 동적으로 만들고 로그인되어 있는 사용자의 현재 설정을 데이터 모델에 정의된 속성에 할당합니다. 프로필 개체는 현재 HttpContext 개체에 추가되어 Profile 속성을 통해 페이지에서 사용할 수 있도록 설정됩니다. 다음 코드 조각에서는 프로필 모델이 링크 목록을 컬렉션으로 저장하도록 정의되었다고 가정한 상태에서 특정 사용자가 만든 즐겨찾기 링크 목록을 검색하는 방법을 보여 줍니다.
If Not IsPostBack Then
' Links 속성에 기본 링크 몇 개를 추가합니다.
If Profile.Links.Count = 0 Then
Profile.Links.Add("http://www.contoso.com")
Profile.Links.Add("http://www.northwind.com")
End If
End If(참고: 프로그래머 코멘트는 샘플 프로그램 파일에는 영문으로 제공되며 기사에는 설명을 위해 번역문으로 제공됩니다.)
이 코드에서는 프로필 개체에 컬렉션 형식을 참조하는 Links 속성이 있는 것으로 가정합니다. 페이지를 로드하면 Links를 비롯한 다른 속성이 초기화되어 최근에 저장한 값을 포함하고, 페이지를 언로드하면 현재 내용이 영구 매체에 저장됩니다.개인 설정 계층을 구축하려면 먼저 사용할 프로필 개체 레이아웃을 정의해야 합니다. 이 작업은 응용 프로그램의 Web.config 파일에 섹션을 추가하여 수행합니다. 그러면 최종적으로 생성되는 데이터 모델은 속성 및 관련 형식을 설명하는 XML 데이터 블록입니다. 이 모델은 속성 목록, 속성 이름 및 속성을 나타내는 데 사용할 해당 관리되는 형식으로 구성됩니다.
속성은 이름/값 쌍을 통해 프로필 저장소 매체에 추가합니다. 그런 다음 새 속성 태그를 구성 파일의 <properties> 섹션에 추가하여 각 쌍을 정의합니다. <properties> 섹션 자체는 보다 큰 <profile> 섹션의 일부이며, 여기에도 공급자 정보가 들어 있습니다. 또한 <profile> 섹션은 <system.web> 아래에 있습니다. 다음 코드에서는 사용자 프로필 섹션의 예를 보여 줍니다.
<profile>
<properties>
<add name="BackColor" type="string" />
<add name="ForeColor" type="string" />
<add name="Links"
type="System.Collections.Specialized.StringCollection"
serializeAs="Xml" />
</properties>
</profile>
<add> 태그를 통해 정의되는 모든 속성은 동적으로 만들어진 프로필 클래스의 멤버가 됩니다. type 특성은 속성의 형식을 나타냅니다. type 정보를 설정하지 않으면 System.String이 기본값으로 사용됩니다. 또한 모든 관리되는 형식을 사용할 수 있습니다. 그림 2에는 <add> 요소가 지원하는 특성이 자세히 나와 있습니다. 이 중에서 필수 특성은 name 특성뿐입니다. 그림 2의 표에서 짐작할 수 있듯이, 사용자 계정과 프로필 데이터 간에는 명확한 관계가 설정되어 있습니다. 실제로 개인 설정 계층은 사용자가 등록 및 로그인해야 하는 응용 프로그램에서 가장 유용합니다. 그러나 ASP.NET 사용자 프로필 API는 익명 사용자도 지원하며 익명 설정을 등록된 계정으로 마이그레이션하는 도구를 제공합니다. 이에 대해서는 이후에 자세히 설명합니다.
문자열, 숫자 및 날짜와 같은 스칼라 값은 추가로 조정되지 않고 순수 문자열 값으로 저장됩니다. 그러나 개인 설정 엔진은 컬렉션이나 사용자 지정 형식을 사용하는 경우와 같은 추가적인 고급 시나리오도 완벽하게 지원합니다. 컬렉션 및 배열과 같은 스칼라가 아닌 값을 데이터 저장소 매체에 저장하려면 serialization 과정을 거쳐야 합니다. 이 칼럼의 앞부분에서 언급한 serializeAs 특성은 이 작업을 수행하는 방법을 지정합니다. serialization에 사용할 수 있는 값은 String, Xml, Binary 및 ProviderSpecific입니다. <properties> 정의에 serializeAs 특성이 없으면 String 형식이 사용됩니다. 컬렉션은 일반적으로 XML 또는 이진 형식으로 serialize됩니다. XML을 선택하면 XmlSerializer가 사용되고 이진 파일을 선택하면 BinaryFormatter가 사용됩니다.
이처럼 사용자 지정 형식을 관련 serialization 엔진(XmlSerializer 또는 BinaryFormatter)으로 serialize하여 ASP.NET 개인 설정 계층에 사용할 수 있습니다. 이 경우 클래스를 작성하여 어셈블리까지 컴파일하기만 하면 됩니다. 그런 다음 구성 파일에서 어셈블리 정규화 형식 이름을 참조합니다.
<properties>
<add name="ShoppingCart"
type="My.Namespace.DataContainer, MyAssem"
serializeAs="Binary" />
</properties>
사용자 지정 형식이 들어 있는 어셈블리는 응용 프로그램의 Bin 디렉터리 또는 GAC(전역 어셈블리 캐시)에서 ASP.NET 응용 프로그램이 사용할 수 있는 상태여야 합니다.프로필 개체를 정의하는 동안 일반 컨테이너 속성 아래에 여러 속성을 그룹화할 수도 있습니다. <group> 요소를 사용하면 하위 개체를 만들 수 있습니다.
<properties>
...
<group name="Font">
<add name="Name" type="string" defaultValue="verdana" />
<add name="SizeInPoints" type="int" defaultValue="8" />
</group>
</properties>
여기서는 font 속성이 Font 그룹의 자식으로 선언되었습니다. 즉, Name이나 SizeInPoints에 대한 액세스는 다음과 같이 Font 이름을 통해 전달됩니다.
Dim fontName as String = Profile.Font.Name
데이터 모델을 만든 후에는 실행 중에 프로필 개체의 값을 읽고 편집할 페이지를 작성합니다. 첫 번째 개인 설정 가능한 페이지를 테스트하려면 데이터 저장소 설정이라는 한 가지 단계를 더 수행해야 합니다.
데이터 저장소
프로필 지원을 사용하거나 사용하지 않으려면 Web.config 파일에서 <profile> 요소의 enabled 특성을 설정합니다. 속성이 true인 경우(기본 설정) 개인 설정 기능을 모든 페이지에 대해 사용할 수 있습니다. 기능을 사용할 수 있다는 것은 단순히 '사용하도록 설정한다'는 것이며, 해당 기능이 사용자 구성원 및 데이터 저장소에 대한 인프라를 만드는 것은 아닙니다.
ASP.NET 2.0에는 ASP.NET WSAT(웹 사이트 관리 도구)가 함께 제공됩니다. 이 도구는 그림 3과 같이 Visual Studio 2005 IDE에 완벽하게 통합되어 있습니다. 이 도구를 사용하여 프로필 데이터를 저장할 기본 데이터베이스를 만듭니다. 기본 데이터베이스는 ASP.NET 응용 프로그램의 App_Data 특수 폴더에 있는 aspnetdb.mdf라는 SQL Server 2005 파일입니다. 테이블 및 데이터베이스 스키마는 고정되어 있습니다. 이 데이터베이스에는 또한 구성원 및 역할 정보가 보관되는 테이블이 들어 있습니다. 개인 설정은 사용자마다 달라지며 데이터에 액세스하려면 사용자 ID(응용 프로그램별 로그온 ID 또는 Windows 계정 ID)가 필요하기 때문에, 사용자 및 역할에 대해 구성원 데이터베이스를 사용하는 것은 중요합니다.

그림 3 그림 3. ASP.NET 웹 사이트 관리 도구
프로필 데이터는 수명이 미리 정의되어 있지 않으며 영구적으로 저장됩니다. 이 정보는 필요하다고 생각되는 경우 웹 사이트 관리자가 삭제합니다. WSAT는 프로필 인프라를 설정하는 데 사용할 수 있는 한 가지 옵션일 뿐입니다. 보안 기능을 사용하면 WSAT에서 데이터베이스가 만들어지고, 그에 따라 필요한 Profile 데이터베이스 테이블도 자동으로 만들어집니다. 사용자 지정 공급자를 사용하는 경우 응용 프로그램을 설치하면 SQL Server 테이블, Oracle 데이터베이스 등 필요한 저장소 인프라가 마련됩니다.
페이지 및 사용자 프로필
프로필을 사용하도록 디자인된 페이지에서는 요소의 스타일과 이동 방식을 적절하게 지정하는 내부 모듈을 호출해야 합니다.그림 4에는 개인 설정할 수 있도록 디자인된 Page 클래스의 기본 형식이 나와 있습니다. Page 클래스는 OnLoad를 다시 정의하여 다시 정의 가능한 두 개의 새 보호 메서드인 InitProfile과 InitEditor를 자동으로 호출합니다. InitProfile 메서드는 페이지별 프로필 개체의 모든 멤버가 개별 기본값으로 올바르게 초기화되도록 합니다. 참조 형식에 대한 기본값을 설정하려면 defaultValue 특성에 serialize된 XML 표현을 배치하면 되고, 이진 serialization의 경우에는 이진 blob의 base64로 인코딩된 표현을 저장하면 됩니다. 기본값을 지정하지 않으면 참조 형식 속성은 매개 변수 없는 생성자(존재하며 액세스 가능한 경우)를 사용하여 구성됩니다. 적절한 생성자가 없고 기본값이 제공되지 않는 경우 초기 속성 값은 null이 됩니다. 따라서 데이터 모델에서 참조 형식을 관리하는 경우에는 대개 프로필 속성에 적절한 기본값을 할당하는 페이지별 초기화 단계를 사용합니다.
사용자가 자신의 기본 설정을 지정할 수 있는 경우에는 페이지 작업을 수행하는 동안 값을 편집할 수 있도록 해야 합니다. SharePoint 또는 ASP.NET 2.0의 웹 파트에 익숙하다면 이 말이 어떤 의미인지 아실 것입니다. 웹 파트에는 사용자의 기본 설정을 수집하기 위한 입력 컨트롤이 포함된 시각적 패널인 UI 편집기가 통합되어 있습니다. UI 편집기는 보통 메뉴 항목이나 하이퍼링크를 클릭하여 활성화합니다. 이러한 인프라는 사용자 프로필을 지원하는 모든 페이지에 제공해야 합니다. InitEditor 메서드를 사용하면 편집기의 입력 필드가 올바르게 초기화됩니다. ShowEditor 및 CloseEditor는 각각 편집기를 열고 닫는 데 사용합니다. 편집기는 페이지 내의 컨트롤(보통 사용자 컨트롤, 패널 또는 다중 뷰 컨트롤)이나 이러한 컨트롤의 조합일 수 있습니다.

그림 5 그림 5. 사용자 기본 설정을 위한 UI 편집기
그림 1에서는 프로필 정보를 사용하는 샘플 페이지를 살펴보았습니다. 여기서 알 수 있듯이 사용자마다 제공되는 페이지가 조금씩 다릅니다. 그림 5와 같이 각 페이지에는 기본 설정을 편집하기 위한 링크가 들어 있습니다. 그림 6에는 MultiView 컨트롤을 통해 편집기를 렌더링하는 태그가 나와 있습니다. ASP.NET 2.0의 MultiView 컨트롤에는 동시에 사용할 수 없는 여러 개의 패널이 들어 있습니다. 이러한 패널은 한 번에 하나씩만 표시됩니다. 샘플 다중 뷰 컨트롤에는 사용자가 편집할 수 있는 뷰와 실제 편집기가 포함된 뷰가 나열되어 있습니다. 자세한 내용은 이 칼럼과 함께 제공된 소스 코드를 참조하십시오.
익명 사용자 처리
사용자 프로필은 기본적으로 인증된 사용자를 위한 것이지만, 익명 사용자도 프로필 데이터를 저장할 수 있습니다. 그러나 익명 사용자의 경우에는 몇 가지 추가적인 요구 사항을 충족해야 합니다. 특히 기본적으로 해제되어 있는 anonymousIdentification 기능을 사용하도록 설정해야 합니다.
<anonymousIdentification enabled="true" />
SP.NET 2.0의 새로운 기능인 익명 사용자 ID를 사용하면 인증되지 않은 사용자에게도 고유한 거짓 ID를 할당할 수 있습니다. 익명 ID는 요청을 처리 중인 계정의 ID에는 아무런 영향을 주지 않습니다. 마찬가지로 보안 및 인증 측면에도 아무 영향이 없습니다. 익명 ID는 인증되지 않은 사용자도 개인 설정을 위해 일반 사용자처럼 추적할 수 있도록 이러한 사용자에게 ID를 할당하는 데 사용되는 메서드일 뿐입니다.
증되지 않은 사용자에 대해 작업을 수행하려면 개별 프로필 속성을 명시적으로 사용 가능하도록 설정해야 합니다. 그렇지 않으면 Profile 개체에 처음 액세스할 때 예외가 발생합니다. 익명 ID를 지원하려면 allowAnonymous라는 특수 부울 특성을 사용하여 데이터 모델의 속성을 표시합니다. 이 특성으로 표시되지 않은 속성은 다음과 같이 익명 사용자가 사용할 수 없습니다.
<anonymousIdentification enabled="true" />
<profile enabled="true">
<properties>
<add name="BackColor" type="System.Drawing.Color"
allowAnonymous="true" />
...
</properties>
</profile>
이 코드 조각에 따르면 익명 사용자는 배경색을 설정할 수 있지만 새 링크를 추가할 수는 없습니다.각 익명 사용자는 사이트를 처음 방문하면 고유한 익명 ID를 받습니다. 이 ID는 쿠키에 영구적으로 저장됩니다. 따라서 두 번째 사용자가 첫 번째 사용자와 같은 컴퓨터에서 브라우저를 열면 사이트에서는 두 번째 사용자가 첫 번째 사용자에게 발급되었던 것과 동일한 익명 ID를 소유한 것으로 간주합니다.
이 익명 사용자가 특정 시점에 해당 웹 사이트의 계정을 만들려고 하는 경우, 현재 익명 계정으로 연결되어 있는 모든 설정을 사용자의 새 계정으로 마이그레이션해야 합니다. 이 마이그레이션 작업은 자동으로 수행되지 않으며 모든 경우에 필요한 것도 아닙니다. 그러나 ASP.NET 2.0에서는 이러한 마이그레이션을 시스템 수준에서 지원합니다. 응용 프로그램을 익명으로 사용하는 사용자가 로그인하면 응용 프로그램은 MigrateAnonymous 이벤트를 수신합니다. 이 이벤트는 페이지에 대해 로컬이 아니므로 global.asax 파일에서 처리해야 합니다. 이 이벤트의 처리기는 프로필 속성 값을 익명 프로필에서 현재 사용자의 프로필로 복사합니다. 다음 의사 코드에서는 익명 프로필 마이그레이션 작업을 처리하는 방법을 보여 줍니다.
Sub Profile_MigrateAnonymous( _
ByVal sender As Object, ByVal e As ProfileMigrateEventArgs)
Dim anon As ProfileCommon = Profile.GetProfile(e.AnonymousID)
' 속성을 새 프로필로 마이그레이션합니다.
Profile.BackColor = anon.BackColor
...
End Sub
일반적인 처리기는 두 가지 단계를 수행합니다. 먼저 익명 사용자에 대한 프로필 정보를 가져옵니다. 이 프로필 정보는 ProfileCommon 형식 개체로 나타납니다. 현재 프로필 개체에 대해 GetProfile 메서드를 호출하여 이 개체에 대한 참조를 가져옵니다. 올바른 데이터 집합을 가져오려면 익명 사용자에 대해 생성되는 가짜 ID를 지정해야 합니다. 익명 사용자의 ID는 이벤트 데이터 구조의 AnonymousID 속성을 통해 사용할 수 있습니다. 그런 다음 처리기는 필요한 각 속성 값을 현재 로그온되어 있는 사용자의 프로필에 복사합니다.
그러면 개발자는 두 가지 정리 작업을 추가로 처리할 수 있습니다. 먼저 ProfileManager를 사용하여 익명 사용자의 프로필 데이터를 삭제함으로써 데이터베이스가 복잡해지지 않도록 할 수 있습니다. 둘째로, 사용자가 로그인한 후에 AnonymousID에 액세스해야 하는 경우가 아니면(일부 개발자는 AnonymousID에 액세스해야 함) AnonymousIdentificationModule.ClearAnonymousIdentifier를 호출해야 합니다. 그러면 익명 ID의 쿠키나 쿠키를 사용하지 않는 표현이 지워집니다. 이 작업을 수행하면 사용자가 로그인한 후에 각 페이지에서 MigrateAnonymous 이벤트가 계속해서 발생하는 현상을 막을 수 있습니다. 익명 ID는 쿠키를 사용하지 않는 작동 모드를 지원하기 때문에 쿠키를 사용하지 않는 클라이언트의 경우에는 이 방법을 사용해야만 익명 ID를 제거할 수 있습니다.
내부 구현
ASP.NET 2.0의 사용자 프로필 기능은 ProfileModule이라는 HTTP 모듈을 지원합니다. 이 모듈은 요청의 처리 과정이 시작되기 전에 해당 요청의 HTTP 컨텍스트에 프로필 데이터를 추가합니다. ProfileModule은 두 개의 HTTP 파이프라인 이벤트인 AcquireRequestState 및 EndRequest에 연결되며, 요청이 인증된 후 또는 요청이 끝나려고 할 때 실행됩니다.
개인 설정 기능이 해제되어 있는 경우 AcquireRequestState 이벤트를 처리하는 코드가 즉시 반환됩니다. 그렇지 않은 경우에는 모듈에서 전역 이벤트(Personalize 이벤트)를 발생시킨 다음 저장소 매체에서 현재 사용자에 대한 개인 설정 데이터를 로드합니다. HTTP 모듈에 의해 발생하는 다른 이벤트와 마찬가지로 Personalize 이벤트도 global.asax 파일에서 처리됩니다. Personalize 이벤트가 발생할 때 개인 설정 데이터는 아직 로드되지 않은 상태입니다. 그렇다면 Personalize 이벤트의 용도는 무엇일까요?
ASP.NET은 프로필 데이터를 엄격하게 사용자별로 관리합니다. 이름이 서로 다른 여러 사용자가 모두 동일한 프로필 데이터를 공유하는 경우, 거의 동일한 수백 개의 데이터베이스 항목을 유지 관리하는 것은 현명하지 못한 방식으로 생각될 수도 있습니다. 그러나 표준 메커니즘을 사용하는 경우에는 이 방법만 사용할 수 있습니다. 실제로 표준 프로필 엔진은 역할을 처리하는 방법을 인식하고 있지 않습니다. 이 경우 Personalize 이벤트를 사용하면 매우 편리합니다. 그림 7에서는 사용자 프로필 개체를 만드는 프로세스를 다시 정의하는 샘플 Personalize 처리기를 확인할 수 있습니다. 이 처리기는 사용자 프로필을 특정 사용자가 속해 있는 역할을 나타내는 프로필로 바꿉니다. ProfileBase 클래스의 Create 정적 메서드는 이름을 가져와 해당 사용자 이름과 관련된 프로필 개체 인스턴스를 만듭니다. 여기서 알 수 있듯이 그림 7의 코드에서는 로그온되어 있는 사용자의 이름을 사용하지 않으며, 해당 사용자가 역할에 속해 있는지 여부를 확인한 후 역할 이름을 대신 사용합니다.
Personalize 이벤트의 처리기는 ProfileEventArgs 클래스를 통해 데이터를 수신합니다. ProfileEventArgs 클래스에는 Profile이라는 읽기-쓰기 멤버가 있습니다. 이벤트 처리기가 반환되면 프로필 HTTP 모듈은 이 멤버를 확인합니다. 이 멤버가 null인 경우 모듈은 정상적으로 작업을 진행하며, 처음 필요할 때 사용자 ID를 기준으로 Profile 로드를 지연시키도록 런타임에 지시합니다. 이처럼 로드를 지연시키면 Profile을 사용하지 않는 페이지에서 Profile이 로드 및 deserialize되어 오버헤드가 발생하는 현상을 방지할 수 있습니다. 그렇지 않은 경우 모듈은 Profile 멤버의 현재 값을 페이지의 프로필 개체로 바인딩합니다.
ProfileBase.Create는 실제로 ProfileBase에서 파생된 형식의 인스턴스인 ProfileCommon을 반환합니다. Web.config 파일에 정의된 데이터 모델은 ASP.NET 런타임에 의해 C# 또는 Visual Basic .NET 클래스로 변환됩니다. 그림 8에서처럼, ProfileCommon이라는 이 클래스는 동적으로 만들어지며 ProfileBase에서 상속됩니다.
프로필 속성에 대한 안전한 형식의 액세스를 위해서는 ProfileCommon 같이 동적으로 만들어지는 클래스가 반드시 필요합니다. ProfileBase 클래스에도 요청이 완료되면 자동으로 속성을 저장소 매체에 다시 보관하는 Save 메서드가 들어 있습니다. 모든 작업은 런타임 환경에서 처리되고 HTTP 모듈에서 관리되므로 페이지 제작자는 프로필 데이터의 로드 및 저장에 대해 전혀 신경 쓰지 않아도 됩니다. 페이지와 프로필 인프라는 Page 클래스의 Profile이라는 고유한 속성을 통해 서로 연결됩니다.
ASP.NET 2.0 프로필 API는 액세스 계층과 저장소 계층의 두 가지 개별 요소로 구성됩니다. 앞서 언급했듯이, 액세스 계층에서는 속성 값을 가져와 설정하고 사용자 ID를 관리하기 위한 형식이 엄격하게 지정된 모델을 제공합니다. 또한 현재 로그온되어 있는 사용자를 대신해 데이터가 검색 및 저장되도록 합니다.
데이터 저장소에서는 특수한 공급자를 사용하여 값 저장 및 검색에 관련된 작업을 수행합니다. ASP.NET 2.0 베타 2에는 SQL Server 2005 Express Edition을 데이터 엔진으로 사용하는 기본 프로필 공급자 AspNetSqlProfileProvider가 제공됩니다. 이 프로필 공급자는 선택한 저장소 매체에 데이터를 쓰고 데이터의 최종 스키마를 작성합니다. 프로필 공급자는 형식에서 중요한 정보를 추출하는 방법을 알고 있거나, XML serialization 및 이진 개체 serialization 등을 사용하여 형식을 serialize할 수 있어야 합니다. 필요한 경우 사용자 지정 공급자를 작성할 수도 있습니다.
새로운 응용 프로그램을 빌드하거나 기본적으로 테이블 형식인 프로필 데이터 작업을 수행하는 경우에는 AspNetSqlProfileProvider를 사용하면 편리합니다. 그러나 대부분의 경우에는 ASP.NET 2.0 응용 프로그램을 처음부터 시작하는 대신 기존 ASP 또는 ASP.NET 응용 프로그램을 마이그레이션합니다. ASP.NET 프로필 계층에 통합할 데이터가 이미 들어 있는 경우도 적지 않습니다. 이 데이터가 관계형 모델에 맞지 않거나 SQL Server가 아닌 다른 저장소 매체에 이미 저장되어 있는 경우에는 사용자 지정 프로필 공급자를 작성하면 됩니다.
프로필 공급자를 통해 씬 레이어 코드를 사용하여 기존 데이터 저장소를 개인 설정 엔진과 통합할 수도 있습니다. 이 코드 계층은 데이터 저장소의 물리적 특성을 추상화하고 일반 메서드 및 속성 집합을 통해 해당 내용을 노출합니다. 사용자 지정 프로필 공급자는 ProfileProvider에서 파생되는 클래스이며 등록 방법은 다음과 같습니다.
<profile>
<providers>
<add name="MyProvider"
type="MyNamespace.MyProfileProvider, MyAssem" />
</providers>
</profile>
마지막으로, 데이터 모델의 각 속성은 <add> 태그의 공급자 특성을 사용하여 고유한 공급자를 통해 처리할 수 있습니다.
<properties> <add name="BackColor" type="string" provider="MyProvider" /> ... </properties>위의 코드에서처럼 BackColor 속성은 MyProvider 공급자를 통해 읽고 씁니다. 물론 공급자 이름은 <providers> 섹션에 있는 항목 중 하나에 해당해야 합니다.
결론
개인 설정 계층은 사용자별 정보를 보관하기 위한 다목적 도구라 할 수 있습니다. 사용자별 정보란 대개 사용자에게 적용되는 정보이지만, 반드시 사용자가 입력한 정보만 뜻하는 것은 아닙니다.
ASP.NET 사용자 프로필 API를 사용하면 완전히 자동화된 방식으로 사용자 기본 설정 및 매개 변수 데이터를 유지하는 페이지를 영구 매체에 기록할 수 있습니다. 프로그래머는 개인 설정 인프라를 설정하는 작업을 수행해야 하지만 저장소 내부 정보에 대해서는 알 필요가 없습니다. 여러분은 잘 알려진 인터페이스의 메서드를 사용하여 공급자 구성 요소를 호출하기만 하면 됩니다. 물론 ASP.NET 2.0 페이지의 개인 설정 기능은 여기서 끝나지 않습니다. 다음 달에는 테마와 사용자 지정 오류 페이지에 대해 살펴보겠습니다.
Dino에게 질문이나 의견이 있으면 cutting@microsoft.com.으로 보내시기 바랍니다.