IBM®
메인 컨텐츠로 가기
    Korea [국가변경]    이용약관
 
 
   
        제품    서비스 & 솔루션    고객지원 & 다운로드    회원 서비스    
메인 컨텐츠로 가기

한국 developerWorks  >  XML  >

XML 스키마에서 열거 목록(Enumerated List) 확장하기

열거 목록을 확장하는 다양한 방법을 살펴보자

developerWorks
문서 옵션

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.

샘플 코드

영어원문

영어원문


제안 및 의견
피드백

난이도 : 중급

W. Paul Kiel, President, xmlHelpline.com Consulting

옮긴이: 박재호 이해영 dwkorea@kr.ibm.com

2008 년 11 월 11 일

목록에 새 값을 추가하는 기능은 일반적이고도 필수적인 요구사항입니다. 그래서 스키마 설계자는 설계 당시에 예상하지 못했던 값을 나중에 추가하는 방법을 아키텍처에 넣으려고 애씁니다. 스키마 설계자가 확장과 구현이 쉬운 열거 목록을 생성하는 방법은 무엇일까요? 이 기사에서는 열거 목록을 확장하는 다양한 방법을 살펴봅니다.

스키마 설계자와 구현자는 XML 스키마에서 기존 열거형 목록을 확장하는 방법이 필요하다. 불행하게도 XML 스키마 명세서를 살펴보면 열거형 목록에 확장성을 제공하지 않는다(관련 링크는 참고자료에서 제공한다). 즉, 열거형 목록은 설계 당시에 선택한 값으로 고정되어 변경할 방법이 없다. 이러한 제약에도 불구하고 사람들은 다양한 우회책을 찾아내어 열거형 목록을 확장한다. 기존 스키마를 변경하지 못하는 상황에 처한 내 고객들도 비슷한 기능을 자주 요청한다. 역호환성을 그대로 유지하면서 새 기능을 추가하려는 의도에서다. 이 기사에서는 스키마 설계자가 열거형 목록에 확장성을 부여하는 방법을 살펴본다.

열거형 목록은 미리 정의한 값 목록이다. 예를 들어, 국가 코드를 DE(독일), US(미국), JP(일본) 등 고정된 값을 담은 목록으로 정의할 수 있다. 그런데 TL(동티모어), BA(보스니아 헤르체고비나) 등 새로운 국가 코드를 추가하고 싶다면? 이전 목록을 사용하던 사람들이 새 목록에 맞춰 코드를 모두 손봐야 할까?

XML 스키마로 데이터를 모델링할 때 열거형 목록을 생성하려면 엘리먼트 값을 명시적으로 나열한다. 즉, 국가 코드 목록을 정의하려면 국가 코드를 하나씩 열거한다. 이런 목록에 새 값을 추가하는 기능은 일반적이고도 필수적이므로, 스키마 설계자들은 열거형 목록을 확장하는 방법을 찾기 위해, (구체적으로는) 설계 당시에 예상치 못했던 값을 나중에 허용하는 방법을 설계에 넣으려고 애써왔다.

확장 가능한 열거형 목록 만들기

해결책을 고민하는 과정에서 다음 네 가지 핵심 요구사항을 고려했다. 요구사항에 따라 적합한 해결책이 달라진다.

  • 첫째, 설계 후에 목록을 확장한다. 새 협력업체를 재빨리 추가하거나, 중요한 데이터 필드를 추가하거나, 막판에 목록을 확장하거나, 어떤 상황이든 현실에서는 설계가 끝난 후에 값을 추가할 필요가 생긴다.
  • 둘째, 구문분석기에서 엘리먼트 값을 검증한다. 그래야 구현이 쉬워진다.
  • 셋째, 한 번에 구문분석과 검증을 모두 수행한다. 따라서 구문분석과 검증을 따로 수행하는 Genericode 방식은 고려하지 않는다. 새 기술 요구사항을 추가하려면 비용이나 시간이 너무 드는 환경도 있기 때문이다.
  • 마지막으로, 기존 스키마와 역호환성을 제공한다. 새 목록이 기존 목록과 호환되지 않는다면 확장이라고 보기 어렵다.

아예 열거형 목록을 확장해서는 안 된다고 말하는 사람들도 있다. 모델에 자료를 추가하고 모델을 키워갈 작정이라면 처음부터 큰 모델을 만든 후 필요한 만큼 제한해서 사용하라고 주장하는 데이터 모델러도 있다. 스키마 설계자에게 원래 스키마와 데이터 모델을 통제할 권한이 있다면 이상적인 해결책이다. 하지만 현실에 맞춰 설계가 완전히 끝난 후에 목록을 확장하겠다면 이 방법은 통하지 않는다.

어떤 사람들은 XML 스미카를 검증하는 구문분석기 밖에서 목록을 확장하는 해결책을 찾는다. Genericode는 XML 스키마를 검증하는 원래 단계 이후에 별도 단계로 열거형 목록을 검증한다(관련 링크는 참고자료에서 제공한다). 이론은 좋다. 앞으로 이 방식이 널리 퍼질지도 모르겠다. 하지만 구문분석기를 한 번만 돌리면서 열거형 목록까지 검증하겠다면 이 방식은 통하지 않는다. 때로는 두 번째 검증 단계가 불가능한 상황도 있다.

물론, 새 엘리먼트로 새 열거형 목록을 생성하는 방법이 항상 존재한다. 하지만 이 방법은 원래 스키마와 역호환성을 제공하지 못한다. 역호환성을 유지하면서 확장 가능한 리스트를 생성하는 방법이 필요하다(참고자료 참조).

이 기사에서는 내가 고객들에게서 받았던 요구사항을 그대로 가정한다. 1) 기존 열거형 목록에 새 값을 추가한다. 2) XML 스키마 구문분석기는 한 번만 거쳐 열거형 목록까지 검증한다.

열거형 목록 확장 요구사항

앞으로 살펴볼 예제에서는 네 가지 요구사항을 가정한다.

  • 설계 후에 열거형 목록 확장을 허용한다.
  • 구문분석기로 열거형 목록을 검증한다.
  • 구문분석기를 한 번만 거쳐서 열거형 목록까지 검증한다.
  • 원래 스키마와 역호환성을 유지한다.

예를 들어, 도메인 업계 컨소시엄 열거형 목록을 (또는 다른 기존 리스트를) 사용하려고 유스 케이스를 위해 해당 스키마 부분을 가져온 팀이 있다. Listing 1에서 보듯이, 기존 스키마는 MaritalStatus를 나타내는 열거형 목록을 정의한다.


Listing 1. 혼인 상태 열거형 목록

<xsd:simpleType name="MaritalStatusEnumType">
    <xsd:restriction base="xsd:normalizedString">
        <xsd:enumeration value="Divorced"/>
        <xsd:enumeration value="Married"/>
        <xsd:enumeration value="NeverMarried"/>
        <xsd:enumeration value="Separated"/>
        <xsd:enumeration value="SignificantOther"/>
        <xsd:enumeration value="Widowed"/>
        <xsd:enumeration value="Unknown"/>
    </xsd:restriction>
</xsd:simpleType>

<xsd:element name="MaritalStatus" type="MaritalStatusEnumType"/>

회사는 이 값을 그대로 사용하면서 주요 협력업체가 요구하는 값을 추가로 지원하려고 한다. 새 값은 CivilUnion으로, 기존 스키마에 없는 값이다. 하지만 의미상으로 기존 리스트(MaritalStatus)를 그대로 사용하는 쪽이 맞다. 어떻게 할까?




위로


방법 1: 원래 스키마를 수정하여 새 값을 추가한다

원래 스키마를 수정하여 새 값을 추가하는 방법은 당연히 가장 간단한 해결책이다. 스키마를 복사한 후 회사에서 사용하려는 열거 값을 추가한다.

  • 장점: 구현이 쉽다.
  • 단점:
    • 원래 스키마를 복사하여 변경한다. 하지만 시간이 지나면서 원래 스키마가 변한다면? 컨소시엄 등 원래 리스트를 작성한 쪽에서 새 리스트를 내놓을지도 모른다. 그러면 원래 리스트에서 바뀐 내용을 자체 리스트에 모두 추가해야 한다.
    • 손으로 스키마를 편집하다 보면 무심코 편집 오류를 저지르기 쉽다.

원래 스키마를 변경하기 어렵거나 변경할 의사가 없다면 다른 대안이 필요하다.




위로


방법 2: 새 열거형 목록을 생성한 후 원래 열거형 목록과 결합한다

두 번째 해결책은 새 열거형 목록을 생성한 후 원래 열거형 목록과 결합하는 방법이다. Listing 1에서 원래 혼인 상태 리스트를 살펴보았다. Listing 2는 새로 생성한 열거형 목록이다.


Listing 2. 새로 생성한 혼인 상태 리스트

<xsd:simpleType name="MyExtMaritalStatusEnumType">
    <xsd:restriction base="xsd:normalizedString">
        <xsd:enumeration value="CivilUnion"/>
    </xsd:restriction>
</xsd:simpleType>

Listing 3에서 보듯이, <xsd:union> 태그를 사용하여 두 리스트를 결합한다.


Listing 3. 두 리스트 결합하기

<xsd:simpleType name="MaritalStatusType_Union">
     <xsd:union memberTypes="MyExtMaritalStatusEnumType MaritalStatusEnumType"/>
</xsd:simpleType>

<xsd:element name="MaritalStatus" type="MaritalStatusType_Union"/>

이 방법 역시 스키마를 편집하기는 마찬가지다. 즉, MaritalStatus 엘리먼트 유형은 MaritalStatusType이 아니라 MaritalStatusType_Union이 된다. 첫 번째 방법보다 온건하지만, 여전히 수작업을 통한 편집이 필요하다.

  • 장점: 원래 열거형 목록을 건드리지 않는다.
  • 단점:
    • 설계 당시에 모든 값을 알아야 한다. 나중에 값을 바인딩하지 못한다.
    • <xsd:union> 태그를 지원해야 한다. 일부 도구에서는 지원하지 않는다.



위로


방법 3: 패턴을 생성한 후 원래 열겨형 목록 유형과 결합한다

이제 사람의 눈 색깔이라는 인구 통계학적 자료를 살펴보겠다. Listing 4는 사람의 눈 색깔을 정의하는 열거형 목록이다.


Listing 4. 사람 눈 색깔 열거형 목록

<xsd:simpleType name="PersonEyeColorType">
    <xsd:restriction base="xsd:string">
        <xsd:enumeration value="Black"/>
        <xsd:enumeration value="Hazel"/>
        <xsd:enumeration value="Gray"/>
        <xsd:enumeration value="Brown"/>
        <xsd:enumeration value="Violet"/>
        <xsd:enumeration value="Green"/>
        <xsd:enumeration value="Blue"/>
        <xsd:enumeration value="Maroon"/>
        <xsd:enumeration value="Pink"/>
        <xsd:enumeration value="Dichromatic"/>
        <xsd:enumeration value="Unknown"/>
    </xsd:restriction>
</xsd:simpleType>

다음으로 새 값을 포용하는 패턴(정규표현식)을 생성한다. 이 패턴은 단순히 x:로 시작하는 문자열이다. x:는 표준 엘리먼트와 확장 엘리먼트를 구분하는 문자열이다. 구체적인 패턴은 Listing 5를 참조한다.


Listing 5. 확장에 사용할 정규표현식

<xsd:simpleType name="StringPatternType">
    <xsd:restriction base="xsd:string">
        <xsd:pattern value="x:\S.*"/>
    </xsd:restriction>
</xsd:simpleType>

마지막으로 <xsd:union> 태그를 사용하여 리스트와 패턴을 결합한다. Listing 6을 참조한다.


Listing 6. 열거형 목록과 확장 패턴 결합

<xsd:simpleType name="MyExtPersonEyeColorType">
    <xsd:union memberTypes="PersonEyeColorType StringPatternType"/>
</xsd:simpleType>

<xsd:element name="PersonEyeColor" type="MyExtPersonEyeColorType"/>

표준 값과 확장 값은 모두 한 노드에 포함된다. 각각은 분리하기 쉬우며 구문분석기로 검증하기도 쉽다. Listing 7을 참조한다.


Listing 7. 예제 XML 인스턴스

<PersonEyeColor>Black</PersonEyeColor>
<PersonEyeColor>x:Teal</PersonEyeColor>

  • 장점:
    • 모든 자료가 같은 엘리먼트를 사용한다.
    • 구문분석기가 기초 열거형 목록을 검증한다.
    • 표준 값과 확장 값이 명확히 구분된다.
    • 새 값을 나중에 추가해도 된다.
  • 단점:
    • 확장 여부를 판단하려면 엘리먼트 내용을 구문분석해야 한다.
    • 스키마 구문분석기가 정규표현식을 지원해야 한다.
    • <xsd:union> 태그를 지원해야 한다.



위로


방법 4: 확장용으로 분리된 필드를 사용한다

이 방법은 열거형 목록 필드를 변경하지 않는다. 하지만 extension 필드를 사용하여 추가되는 값을 처리한다. Listing 8에서 보듯이, 원래 열거형 목록은 부양 가족 유형(직원 연금 수령인과 피부양자 사이의 관계)이다.


Listing 8. 피부양자 열거형 목록
	
<xsd:simpleType name="DependentRelationshipEnumType">
    <xsd:restriction base="xsd:string">
        <xsd:enumeration value="AdoptedChild"/>
        <xsd:enumeration value="Brother"/>
        <xsd:enumeration value="Child"/>
        <xsd:enumeration value="ExSpouse"/>
        <xsd:enumeration value="Father"/>
        <xsd:enumeration value="Granddaughter"/>
        <xsd:enumeration value="Grandson"/>
        <xsd:enumeration value="Grandfather"/>
        <xsd:enumeration value="Grandmother"/>
        <xsd:enumeration value="LifePartner"/>
        <xsd:enumeration value="Mother"/>
        <xsd:enumeration value="Sister"/>
        <xsd:enumeration value="Spouse"/>
        <xsd:enumeration value="Extension"/>
    </xsd:restriction>
</xsd:simpleType>

새 값을 수용하려면 extension이라는 추가 속성이 필요하다. Listing 9를 참조한다.


Listing 9. 피부양자 extension 속성

<xsd:complexType name="DependentRelationshipType">
    <xsd:simpleContent>
        <xsd:extension base="DependentRelationshipEnumType">
            <xsd:attribute name="extension" type="xsd:string"/>
        </xsd:extension>
    </xsd:simpleContent>
</xsd:complexType>			

<xsd:element name="DependentRelationship" type="DependentRelationshipType"/>

Listing 10extension을 반영한 예제 XML 인스턴스다.


Listing 10. 예제 XML 인스턴스
	
<DependentRelationship>Child</DependentRelationship>
<DependentRelationship extension="MyNewRelationship">Extension</DependentRelationship>

  • 장점:
    • 원래 스키마를 변경할 필요가 없다.
    • 새 값을 나중에 추가해도 된다.
    • extension 메서드는 원래 스키마에 명시적으로 확장 방법을 제공한다.
  • 단점:
    • 설계시 각 열거형 목록에 extension 메서드를 넣어야 한다.
    • 새로 추가하는 값은 속성이 아니라 엘리먼트여야 한다.



위로


방법 5: 문서 기반 방식 -- 문자열과 결합

참고: 방법 5와 방법 6은 '한 번에 검증한다'는 요구사항을 위반한다. 하지만 실제로 많이 사용하는 방법이기에 여기서 설명한다.

다섯 번째 방법은 <xsd:union> 태그를 사용하여 문자열과 결합된 열거형 목록을 사용한다. 따라서 이 방법은 어느 값이 표준 값인지 (대소문자와 철자를 포함하여) 구문분석기에 힌트를 제공하면서도 string 필드에 새 값을 허용한다. 즉, 구문분석기는 열거형 목록 엘리먼트 값을 검증하지 않는다. 대신, 두 번째 단계에서 또는 자료를 받는 응용 프로그램이 엘리먼트 값을 검증한다. 이는 일부 XML 컨소시엄에서 사용하는 전략이다.

Listing 11<xsd:union>을 통해 <xsd:string>과 결합된 열거형 목록은 어느 값이나 가능하므로 구문분석기는 열거형 목록 엘리먼트 값을 검증하지 않는다. 엘리먼트 값은 어디까지나 제안된 표준 값이다.


Listing 11. 문자열과 결합된 요일 열거형 목록

<xsd:simpleType name="DayOfWeekEnumType">
    <xsd:restriction base="xsd:string">
        <xsd:enumeration value="Sunday"/>
        <xsd:enumeration value="Monday"/>
        <xsd:enumeration value="Tuesday"/>
        <xsd:enumeration value="Wednesday"/>
        <xsd:enumeration value="Thursday"/>
        <xsd:enumeration value="Friday"/>
        <xsd:enumeration value="Saturday"/>
    </xsd:restriction>
</xsd:simpleType>
<xsd:element name="DayOfWeek" type="DayOfWeekEnumType"/>

<xsd:simpleType name="ExtendedDayOfWeekType">
	<xsd:union memberTypes="DayOfWeekEnumType xsd:string"/>
</xsd:simpleType>
<xsd:element name="DayOfWeek_solution5" type="ExtendedDayOfWeekType"/>

  • 장점: 나중에도 값을 무한히 추가할 수 있다.
  • 단점:
    • 구문분석기가 열거형 목록 값을 검증하지 않는다. 나중에 따로 검증을 거친다.
    • <xsd:union> 태그를 지원해야 한다.



위로


방법 6: 문서 기반 방법 -- <xsd:annotation> 사용

이 방법은 <xsd:documentation> 태그에 실제 열거형 값을 넣으면서 엘리먼트 값은 비워둔다. Listing 12를 참조한다.


Listing 12. <xsd:documentation> 태그에 열거형 목록값 넣기

<xsd:element name="DayOfWeek" type="xsd:string">
    <xsd:annotation>
        <xsd:documentation>
            <!-- suggested enumerations -->
            <xsd:enumeration value="Sunday"/>
            <xsd:enumeration value="Monday"/>
            <xsd:enumeration value="Tuesday"/>
            <xsd:enumeration value="Wednesday"/>
            <xsd:enumeration value="Thursday"/>
            <xsd:enumeration value="Friday"/>
            <xsd:enumeration value="Saturday"/>
        </xsd:documentation>
    </xsd:annotation>
</xsd:element>

  • 장점:
    • 나중에도 값을 무한하게 추가할 수 있다.
    • 아주 간단한 XML 스키마 기능만 필요하다.
  • 단점: 구문분석기가 열거형 목록 값을 검증하지 않는다.



위로


여기서 고려하지 않은 방법

몇 가지 방법을 고의로 소개하지 않았다. 다음 목록은 이 기사에서 소개하지 않은 방법 두 가지다.

  • <xsd:redefine> 태그 사용하기: 별로 사용하지도 않고 도구에서도 구현하지 않는 기능이다. 가능하면 재정의는 피하는 편이 가장 좋다.
  • substitutionGroup 엘리먼트를 사용하여 모든 값을 포함하는 결합 목록에서 치환하기: 그룹 치환(substitution)과 결합(union)을 사용하는 방법이다. 원래 목록과 새 목록을 결합하여 전체 목록을 만든 후 substitutionGroups<xsi:type> 태그를 사용하여 전역 엘리먼트를 치환한다. 여기서 문제점은 결합된 목록이 치환에 타당하지 않다는 사실이다. 치환을 수행하려면 두 목록이 같은 목록 유형에서 파생해야 한다. 확장(extension)과 제약(restriction)은 둘 다 치환에 적합한 방법이지만, XML 스키마 명세서에 따르면, 결합(union)은 올바른 파생 기법이 아니다(관련 링크는 참고자료에서 제공한다).



위로


결론

XML 스키마 설계자와 구현자는 기존 열거형 목록을 확장할 방법이 필요하다. XML 스키마 명세서에 따르면, 일단 열거형 목록을 생성하면 확장할 방법이 없다. 그래서 현실에서는 우회책을 사용한다. 이 기사에서는 열거형 목록을 설계하고 확장하는 방법을 소개했다. 방법마다 장점과 단점이 있으며, 모든 상황에서 최선인 유일한 방법은 없다. 그렇다면 어떤 방법을 택해야 할까?

다음과 같은 경험적인 요소를 고려한다.

  • 원래 열거형 목록이나 원래 스키마를 변경해도 좋다면, 그리고 설계시 모든 값을 안다면, 방법 1이나 방법 2를 택한다. 방법 1은 원래 스키마를 변경하고, 방법 2는 새 리스트를 생성하여 원래 리스트와 결합한다.
  • 기본 열거형 목록과 확장한 열거형 목록을 모두 포함하는 의미론적으로 똑같은 엘리먼트를 사용하고 싶다면 방법 3을 고려한다. 방법 3은 원래 열거형 목록을 패턴과 결합한다.
  • 원래 목록과 확장 목록에서 필드가 서로 달라도 괜찮다면 방법 4를 고려한다. 방법 4는 필드를 분리한다.
  • 열거형 목록 값을 구문분석기로 검증하지 않겠다면 Genericode나 방법 5방법 6을 고려한다.

위 지침을 따르면 스키마 설계자가 현실에서 부딪히는 문제를 좀 더 효율적으로 해결할 뿐 아니라 구현과 확장이 쉬운 열거형 목록도 어렵지 않게 생성하리라 믿는다.





위로


다운로드 하십시오

설명이름크기다운로드 방식
XML 스키마와 XML 인스턴스 예제ExtendEnumeratedListsCode.zip2KBHTTP
다운로드 방식에 대한 정보


참고자료

교육

제품 및 기술 얻기
  • IBM 평가판 소프트웨어: developerWorks에서 직접 내려받아 다음 프로젝트를 구축하자. DB2®, Lotus®, Rational®, Tivoli®, WebSphere®가 있다.


토론


필자소개

Photo of Paul Kiel

Paul Kiel은 표준 활성화를 전문으로 하는 컨설팅 회사인 xmlHelpline.com의 사장이다. XML 스키마 설계와 우수 개발 기법, 데이터 모델링, XSLT, 데이터 통합이 주력 분야다. Kiel은 현재 HR-XML 컨소시엄을 이끄는 수석 아키텍트이기도 하며, 1997년 이래로 XML 기술을 다뤄왔다. Paul은 원래 도서관 사서 교육을 받았던 사람이라, 때때로 역사적인 문서를 수집하는 취미에 몰두하기도 한다.




기사에 대한 평가


보다 나은 서비스를 제공하기 위함이오니 잠시 짬을 내어 이 양식을 제출하여 주십시오.



 


 


 


이 문서 북마킹 하기

mar.gar.in mar.gar.in naver naver eolin eolin del.icio.us del.icio.us





위로


Adobe, the Adobe logo, PostScript, and the PostScript logo are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States, and/or other countries. IBM, the IBM logo, ibm.com, DB2, developerWorks, Lotus, Rational, Tivoli, WebSphere, and pureXML are trademarks of IBM Corporation in the United States, other countries, or both. Other company, product, or service names may be trademarks or service marks of others. 기타 회사, 제품, 및 서비스명은 다른 상표나 서비스 마크일 수 있습니다.

developerWorks 콘텐트를 다른 사이트에 전재하기:
developerWorks 콘텐트에 대한 저작권은 IBM에 있습니다. IBM의 서면 허가나 원본 저자의 허락이 없이는 전재를 금합니다. 저희 콘텐트를 전재하시려면 IBM developerWorks 담당자 에게 문의하십시오.
    IBM 소개 개인정보 보호정책 문의