다음을 통해 공유


스키마를 가져와 클래스 생성

WCF(Windows Communication Foundation)에서 사용할 수 있는 스키마에서 클래스를 생성하려면 XsdDataContractImporter 클래스를 사용합니다. 이 항목에서는 프로세스와 변형에 대해 설명합니다.

가져오기 프로세스

스키마 가져오기 프로세스는 XmlSchemaSet로 시작되고 CodeCompileUnit을 생성합니다.

XmlSchemaSet은 XSD(XML 스키마 정의 언어) 스키마 문서 집합을 나타내는 .NET Framework SOM(스키마 개체 모델)의 일부입니다. XSD 문서 집합에서 XmlSchemaSet 개체를 만들려면 XmlSchema를 사용하여 각 문서를 XmlSerializer 개체로 역직렬화하고 이러한 개체를 새 XmlSchemaSet에 추가합니다.

CodeCompileUnit은 추상적인 방식으로 .NET Framework 코드를 나타내는 .NET Framework CodeDOM(코드 문서 개체 모델)의 일부입니다. CodeCompileUnit에서 실제 코드를 생성하려면 CodeDomProvider 또는 CSharpCodeProvider 클래스 같은 VBCodeProvider 클래스의 하위 클래스를 사용합니다.

스키마를 가져오려면

  1. XsdDataContractImporter 인스턴스를 만듭니다.

  2. (선택 사항) 생성자의 CodeCompileUnit를 전달합니다. 스키마를 가져오는 중 생성된 형식은 빈 CodeCompileUnit로 시작하지 않고 이 CodeCompileUnit 인스턴스에 추가됩니다.

  3. (선택 사항) CanImport 메서드 중 하나를 호출합니다. 메서드는 지정된 스키마가 올바른 데이터 계약 스키마이고 가져올 수 있는지 여부를 결정합니다. CanImport 메서드는 Import(다음 단계)와 동일한 오버로드를 갖습니다.

  4. 오버로드된 Import 메서드 중 하나(예: Import(XmlSchemaSet) 메서드)를 호출합니다.

    가장 간단한 오버로드는 XmlSchemaSet를 사용하고 익명 형식을 포함하여 해당 스키마 집합에 있는 모든 형식을 가져옵니다. 기타 오버로드를 사용하면 XSD 형식이나 가져올 형식 목록을 XmlQualifiedName 또는 XmlQualifiedName 개체 컬렉션 형태로 지정할 수 있습니다. 이 경우 지정된 형식만 가져옵니다. 오버로드는 XmlSchemaElement에서 특정 요소를 가져오는 XmlSchemaSet 및 연결된 형식(익명 형식인지 여부에 관계없이)을 사용합니다. 이 오버로드는 이 요소에 대해 생성된 형식의 데이터 계약 이름을 나타내는 XmlQualifiedName을 반환합니다.

    Import 메서드를 여러 번 호출하면 동일한 CodeCompileUnit에 여러 항목이 추가됩니다. 형식이 이미 있으면 CodeCompileUnit 에 생성되지 않습니다. Import 개체를 여러 개 사용하는 대신 동일한 XsdDataContractImporter에서 XsdDataContractImporter를 여러 번 호출합니다. 중복 형식이 생성되지 않도록 하려면 이 방법을 사용하는 것이 좋습니다.

    참고

    가져오기 중 오류가 발생하면 CodeCompileUnit는 예기치 않은 상태가 됩니다. 실패한 가져오기에서 생성된 CodeCompileUnit를 사용하면 보안상 취약해질 수 있습니다.

  5. CodeCompileUnit 속성을 통해 CodeCompileUnit 에 액세스합니다.

가져오기 옵션: 생성된 형식 사용자 지정

OptionsXsdDataContractImporter 속성을 ImportOptions 클래스의 인스턴스로 설정하여 가져오기 프로세스의 다양한 측면을 제어할 수 있습니다. 여러 가지 옵션은 생성되는 형식에 직접 영향을 줍니다.

액세스 수준 제어(GenerateInternal 또는 /internal 스위치)

이는 ServiceModel Metadata 유틸리티 도구(Svcutil.exe)/internal 스위치에 해당합니다.

일반적으로 public 형식은 private 필드 및 일치하는 공용 데이터 멤버 속성을 사용하여 스키마에서 생성됩니다. 대신 내부 형식을 생성하려면 GenerateInternal 속성을 true로 설정합니다.

다음 예제에서는 GenerateInternal 속성이 true.로 설정된 경우 내부 클래스로 변환되는 스키마를 보여 줍니다.

[DataContract]
internal partial class Vehicle : IExtensibleDataObject
{
    private int yearField;
    private string colorField;

    [DataMember]
    internal int year
    {
        get { return this.yearField; }
        set { this.yearField = value; }
    }
    [DataMember]
    internal string color
    {
        get { return this.colorField; }
        set { this.colorField = value; }
    }

    private ExtensionDataObject extensionDataField;
    public ExtensionDataObject ExtensionData
    {
        get { return this.extensionDataField; }
        set { this.extensionDataField = value; }
    }
}
Class Vehicle
    Implements IExtensibleDataObject
    Private yearField As Integer
    Private colorField As String

    <DataMember()> _
    Friend Property year() As Integer
        Get
            Return Me.yearField
        End Get
        Set
            Me.yearField = value
        End Set
    End Property

    <DataMember()> _
    Friend Property color() As String
        Get
            Return Me.colorField
        End Get
        Set
            Me.colorField = value
        End Set
    End Property
    Private extensionDataField As ExtensionDataObject

    Public Property ExtensionData() As ExtensionDataObject _
        Implements IExtensibleDataObject.ExtensionData
        Get
            Return Me.extensionDataField
        End Get
        Set(ByVal value As ExtensionDataObject)
            Me.extensionDataField = value
        End Set
    End Property
End Class

네임스페이스 제어(Namespaces 또는 /namespace 스위치)

이는 Svcutil.exe 도구의 /namespace 스위치에 해당합니다.

일반적으로 스키마에서 생성된 형식은 .NET Framework 네임스페이스로 생성되고 데이터 계약 스키마 참조에 설명된 매핑에 따라 각 XSD 네임스페이스는 특정 .NET Framework 네임스페이스에 해당합니다. Namespaces에 대한 Dictionary<TKey,TValue> 속성으로 이 매핑을 사용자 지정할 수 있습니다. 지정된 XSD 네임스페이스가 사전에 있으면 일치하는 .NET Framework 네임스페이스도 사전에서 가져옵니다.

예를 들어 다음 스키마를 생각해 볼 수 있습니다.

<xs:schema targetNamespace="http://schemas.contoso.com/carSchema">
  <xs:complexType name="Vehicle">
    <!-- details omitted... -->
  </xs:complexType>
</xs:schema>

다음 예제에서는 Namespaces 속성을 사용하여 http://schemas.contoso.com/carSchema 네임스페이스를 “Contoso.Cars”에 매핑합니다.

XsdDataContractImporter importer = new XsdDataContractImporter();
importer.Options.Namespaces.Add(new KeyValuePair<string, string>("http://schemas.contoso.com/carSchema", "Contoso.Cars"));
Dim importer As New XsdDataContractImporter
importer.Options.Namespaces.Add(New KeyValuePair(Of String, String)("http://schemas.contoso.com/carSchema", "Contoso.Cars"))

SerializableAttribute 추가(GenerateSerializable 또는 /serializable 스위치)

이는 Svcutil.exe 도구의 /serializable 스위치에 해당합니다.

경우에 따라 스키마에서 생성된 형식을 .NET Framework 런타임 직렬화 엔진에서 사용할 수 있는 기능이 중요합니다. 이 기능은 .NET Framework 원격의 형식을 사용할 때 유용합니다. 이 기능을 사용하려면 일반적인 SerializableAttribute 특성 외에도 DataContractAttribute 특성을 생성된 형식에 적용해야 합니다. GenerateSerializable 가져오기 옵션이 true로 설정되어 있으면 이 특성이 자동으로 생성됩니다.

다음 예제에서는 Vehicle 가져오기 옵션을 GenerateSerializable로 설정하여 생성된 true 클래스를 보여 줍니다.

[DataContract]
[Serializable]
public partial class Vehicle : IExtensibleDataObject
{
    // Code not shown.
    public ExtensionDataObject ExtensionData
    {
        get
        {
            throw new Exception("The method or operation is not implemented.");
        }
        set
        {
            throw new Exception("The method or operation is not implemented.");
        }
    }
}
<DataContract(), Serializable()> _
Partial Class Vehicle
    Implements IExtensibleDataObject
    Private extensionDataField As ExtensionDataObject

    ' Code not shown.

    Public Property ExtensionData() As ExtensionDataObject _
        Implements IExtensibleDataObject.ExtensionData
        Get
            Return Me.extensionDataField
        End Get
        Set(ByVal value As ExtensionDataObject)
            Me.extensionDataField = value
        End Set
    End Property

End Class

데이터 바인딩 지원 추가(EnableDataBinding 또는 /enableDataBinding 스위치)

이는 Svcutil.exe 도구의 /enableDataBinding 스위치에 해당합니다.

경우에 따라 스키마에서 생성된 형식을 그래픽 사용자 인터페이스 구성 요소에 바인딩하여 이러한 형식의 인스턴스를 업데이트할 경우 자동으로 UI가 업데이트되도록 할 수도 있습니다. XsdDataContractImporter는 속성을 변경할 경우 이벤트가 트리거되는 방식으로 INotifyPropertyChanged 인터페이스를 구현하는 형식을 생성할 수 있습니다. 이 인터페이스를 지원하는 클라이언트 UI 프로그래밍 환경(예: WPF(Windows Presentation Foundation))에서 사용할 형식을 생성하는 경우 이 기능을 사용하려면 EnableDataBinding 속성을 true로 설정합니다.

다음 예제에서는 VehicleEnableDataBinding로 설정하여 생성된 true 클래스를 보여 줍니다.

[DataContract]
public partial class Vehicle : IExtensibleDataObject, INotifyPropertyChanged
{
    private int yearField;
    private string colorField;

    [DataMember]
    public int year
    {
        get { return this.yearField; }
        set
        {
            if (this.yearField.Equals(value) != true)
            {
                this.yearField = value;
                this.RaisePropertyChanged("year");
            }
        }
    }
    [DataMember]
    public string color
    {
        get { return this.colorField; }
        set
        {
            if (this.colorField.Equals(value) != true)
            {
                this.colorField = value;
                this.RaisePropertyChanged("color");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler propertyChanged =
this.PropertyChanged;
        if (propertyChanged != null)
        {
            propertyChanged(this,
new PropertyChangedEventArgs(propertyName));
        }
    }

    private ExtensionDataObject extensionDataField;
    public ExtensionDataObject ExtensionData
    {
        get { return this.extensionDataField; }
        set { this.extensionDataField = value; }
    }
}
Partial Class Vehicle
    Implements IExtensibleDataObject, INotifyPropertyChanged
    Private yearField As Integer
    Private colorField As String

    <DataMember()> _
    Public Property year() As Integer
        Get
            Return Me.yearField
        End Get
        Set
            If Me.yearField.Equals(value) <> True Then
                Me.yearField = value
                Me.RaisePropertyChanged("year")
            End If
        End Set
    End Property

    <DataMember()> _
    Public Property color() As String
        Get
            Return Me.colorField
        End Get
        Set
            If Me.colorField.Equals(value) <> True Then
                Me.colorField = value
                Me.RaisePropertyChanged("color")
            End If
        End Set
    End Property

    Public Event PropertyChanged As PropertyChangedEventHandler _
      Implements INotifyPropertyChanged.PropertyChanged

    Private Sub RaisePropertyChanged(ByVal propertyName As String)
        RaiseEvent PropertyChanged(Me, _
         New PropertyChangedEventArgs(propertyName))
    End Sub

    Private extensionDataField As ExtensionDataObject

    Public Property ExtensionData() As ExtensionDataObject _
        Implements IExtensibleDataObject.ExtensionData
        Get
            Return Me.extensionDataField
        End Get
        Set(ByVal value As ExtensionDataObject)
            Me.extensionDataField = value
        End Set
    End Property

End Class

가져오기 옵션: 컬렉션 형식 선택

XML의 두 가지 특수 패턴은 항목 컬렉션, 즉 항목 목록 및 한 항목과 다른 항목 간의 연결을 나타냅니다. 다음은 문자열 목록의 예입니다.

<People>
  <person>Alice</person>
  <person>Bob</person>
  <person>Charlie</person>
</People>

다음은 문자열과 정수(city namepopulation) 간의 연결 예입니다.

<Cities>
  <city>
    <name>Auburn</name>
    <population>40000</population>
  </city>
  <city>
    <name>Bellevue</name>
    <population>80000</population>
  </city>
  <city>
    <name>Cedar Creek</name>
    <population>10000</population>
  </city>
</Cities>

참고

모든 연결을 목록으로 간주할 수도 있습니다. 예를 들어 앞의 연결을 두 개의 필드(문자열 필드 및 정수 필드)가 있는 복잡한 city 개체 목록으로 간주할 수 있습니다. 두 패턴은 모두 XSD 스키마에서 하나로 표현됩니다. 목록과 연결을 구분할 수 없으므로 WCF에 관련된 특별한 주석이 스키마에 없으면 해당 패턴은 항상 목록으로 처리됩니다. 주석은 지정된 패턴이 연결을 나타냄을 가리킵니다. 자세한 내용은 데이터 계약 스키마 참조를 참조하세요.

일반적으로 목록은 스키마가 컬렉션의 표준 명명 패턴을 따르는지 여부에 따라 제네릭 목록에서 파생된 컬렉션 데이터 계약이나 .NET Framework 배열로 가져옵니다. 이것은 데이터 계약의 컬렉션 형식에서 자세히 설명되어 있습니다. 연결은 일반적으로 Dictionary<TKey,TValue> 또는 사전 개체에서 파생된 컬렉션 데이터 계약으로 가져옵니다. 예를 들어 다음 스키마를 생각해 볼 수 있습니다.

<xs:complexType name="Vehicle">
  <xs:sequence>
    <xs:element name="year" type="xs:int"/>
    <xs:element name="color" type="xs:string"/>
    <xs:element name="passengers" type="people"/>
  </xs:sequence>
</xs:complexType>
<xs:complexType name="people">
  <xs:sequence>
    <xs:element name="person" type="xs:string" maxOccurs="unbounded" />
  </xs:sequence>
</xs:complexType>

이 스키마는 다음과 같이 가져옵니다(읽기 쉽도록 속성 대신 필드가 표시됨).

[DataContract]
public partial class Vehicle : IExtensibleDataObject
{
    [DataMember] public int yearField;
    [DataMember] public string colorField;
    [DataMember] public people passengers;

    // Other code not shown.

    public ExtensionDataObject ExtensionData
    {
        get
        {
            throw new Exception("The method or operation is not implemented.");
        }
        set
        {
            throw new Exception("The method or operation is not implemented.");
        }
    }
}
[CollectionDataContract(ItemName = "person")]
public class people : List<string> { }
Public Partial Class Vehicle
    Implements IExtensibleDataObject

    <DataMember()> _
    Public yearField As Integer
    <DataMember()> _
    Public colorField As String
    <DataMember()> _
    Public passengers As people

    ' Other code not shown.

    Public Property ExtensionData() As ExtensionDataObject _
    Implements IExtensibleDataObject.ExtensionData
        Get
            Throw New Exception("The method or operation is not implemented.")
        End Get
        Set
            Throw New Exception("The method or operation is not implemented.")
        End Set
    End Property
End Class

<CollectionDataContract(ItemName:="person")> _
Public Class people
    Inherits List(Of String)
End Class

이러한 스키마 패턴에 대해 생성된 컬렉션 형식을 사용자 지정할 수 있습니다. 예를 들어 형식을 목록 상자에 바인딩하고 컬렉션 콘텐츠를 변경할 때 자동으로 업데이트되도록 BindingList<T> 클래스 대신 List<T>에서 파생된 컬렉션을 생성할 수 있습니다. 이렇게 하려면 ReferencedCollectionTypes 클래스의 ImportOptions 속성을 사용할 컬렉션 형식(이후부터는 참조된 형식) 목록으로 설정합니다. 컬렉션을 가져올 때는 이 참조된 컬렉션 형식 목록이 검색되고, 가장 일치하는 컬렉션이 있으면 해당 컬렉션이 사용됩니다. 목록은 지원되는 모든 컬렉션 형식에 대해 일치되지만 연결은 제네릭 또는 비제네릭 IDictionary 인터페이스를 구현하는 형식에 대해서만 일치됩니다.

예를 들어 ReferencedCollectionTypes 속성을 BindingList<T>로 설정하면 앞의 예에서 people 형식은 다음과 같이 생성됩니다.

[CollectionDataContract(ItemName = "person")]
public class people : BindingList<string> { }
<CollectionDataContract(ItemName:="person")> _
Public Class people
    Inherits BindingList(Of String)

폐쇄형 제네릭이 가장 일치하는 항목으로 간주됩니다. 예를 들어 BindingList(Of Integer)ArrayList 형식이 참조된 형식의 컬렉션으로 전달되는 경우 스키마에 있는 모든 정수 목록을 BindingList(Of Integer)로 가져옵니다. 예를 들어 다른 모든 목록 List(Of String)ArrayList로 가져옵니다.

제네릭 IDictionary 인터페이스를 구현하는 형식이 참조된 형식 컬렉션에 추가되는 경우 형식 매개 변수를 완전히 열거나 완전히 닫아야 합니다.

복제는 허용되지 않습니다. 예를 들어 List(Of Integer)Collection(Of Integer)을 모두 참조된 형식에 추가할 수는 없습니다. 이렇게 하면 스키마에 정수 목록이 있을 때 사용할 항목을 결정할 수 없습니다. 중복 문제를 노출하는 형식이 스키마에 있는 경우에만 중복이 감지됩니다. 예를 들어 가져온 스키마에 정수 목록이 없는 경우 List(Of Integer)Collection(Of Integer)을 참조된 형식 컬렉션에 모두 포함할 수 있지만 둘 다 영향을 미치지 않습니다.

참조된 컬렉션 형식 메커니즘은 기본 형식의 컬렉션뿐만 아니라 다른 컬렉션의 컬렉션을 비롯한 복합 형식의 컬렉션에서도 효과적으로 작동합니다.

ReferencedCollectionTypes 속성은 SvcUtil.exe 도구의 /collectionType 스위치에 해당합니다. 여러 컬렉션 형식을 참조하려면 /collectionType 스위치를 여러 번 지정해야 합니다. 형식이 MsCorLib.dll에 없으면 /reference 스위치를 사용하여 해당 어셈블리도 참조해야 합니다.

가져오기 옵션: 기존 형식 참조

경우에 따라 스키마의 형식은 기존 .NET Framework 형식과 일치하며 이러한 형식은 처음부터 생성할 필요가 없습니다. (이 섹션은 컬렉션 형식이 아닌 형식에만 적용됩니다. 컬렉션 형식은 이전 섹션을 참조하세요.)

예를 들어 개인을 나타낼 때 항상 사용할 회사 수준의 표준 "Person" 데이터 계약 형식이 있을 수 있습니다. 일부 서비스에서 이 형식을 사용하고 서비스 메타데이터에 해당 스키마가 나타날 때마다 각 서비스에 대해 새 형식을 생성하는 대신 이 스키마를 가져올 때 기존 Person 형식을 다시 사용할 수 있습니다.

이렇게 하려면 다시 사용할 .NET Framework 형식 목록을 ReferencedTypes 속성이 ImportOptions 클래스에서 반환하는 컬렉션으로 전달합니다. 이러한 형식에 스키마 형식의 이름 및 네임스페이스와 일치하는 데이터 계약 이름 및 네임스페이스가 있으면 구조 비교가 수행됩니다. 형식에 일치하는 이름과 일치하는 구조가 모두 있는 경우 새 형식을 생성하는 대신 기존 .NET Framework 형식이 다시 사용됩니다. 이름만 일치하고 구조가 일치하지 않으면 예외가 throw됩니다. 형식을 참조할 때(예: 새 선택적 데이터 멤버를 추가할 때) 버전 관리는 허용되지 않습니다. 구조는 정확하게 일치해야 합니다.

해당 이름과 네임스페이스를 가진 스키마 형식을 가져오지 않는 한 동일한 데이터 계약 이름과 네임스페이스를 가진 여러 형식을 참조된 형식 컬렉션에 추가할 수 있습니다. 이렇게 하면 실제로 스키마에서 발생하지 않는 형식의 중복에 대해 염려하지 않고 어셈블리의 모든 형식을 쉽게 컬렉션에 추가할 수 있습니다.

ReferencedTypes 속성은 Svcutil.exe 도구의 특정 작업 모드에서 제공되는 /reference 스위치에 해당합니다.

참고

Svcutil.exe 또는 Visual Studio의 서비스 참조 추가 도구를 사용하는 경우 MsCorLib.dll의 모든 형식이 자동으로 참조됩니다.

가져오기 옵션: DataContract가 아닌 스키마를 IXmlSerializable 형식으로 가져오기

XsdDataContractImporter는 스키마의 제한된 하위 집합을 지원합니다. 지원되지 않는 스키마 구문이 있으면(예: XML 특성) 예외와 함께 가져오기 시도가 실패합니다. 그러나 ImportXmlType 속성을 true로 설정하면 지원되는 스키마 범위가 확장됩니다. trueXsdDataContractImporter로 설정된 경우 IXmlSerializable 인터페이스를 구현하는 형식을 생성합니다. 이 경우 이러한 형식의 XML 표현에 직접 액세스할 수 있습니다.

디자인 고려 사항
  • 약한 형식의 XML 표현을 직접 사용하기 어려울 수도 있습니다. XmlSerializer 같은 대체 serialization 엔진을 사용하여 강력한 형식의 데이터 계약과 호환되지 않는 스키마 작업을 수행해 보세요. 자세한 내용은 XmlSerializer 클래스 사용을 참조하세요.

  • XsdDataContractImporter 속성이 ImportXmlType로 설정되어 있어도 일부 스키마 구문은 true로 가져올 수 없습니다. 이 경우에도 XmlSerializer를 사용해 보세요.

  • ImportXmlTypetrue 또는 false일 때 모두 지원되는 정확한 스키마 구문은 데이터 계약 스키마 참조에 설명되어 있습니다.

  • 생성된 IXmlSerializable 형식의 스키마는 가져오고 내보낼 때 충실도를 유지하지 않습니다. 즉, 생성된 형식에서 스키마를 내보내고 클래스로 가져오면 원래 스키마가 반환되지 않습니다.

ImportXmlType 옵션을 앞에서 설명한 ReferencedTypes 옵션과 결합할 수 있습니다. IXmlSerializable 구현으로 생성해야 하는 형식의 경우 ReferencedTypes 기능을 사용할 때 구조적 검사를 건너뜁니다.

ImportXmlType 옵션은 Svcutil.exe 도구의 /importXmlTypes 스위치에 해당합니다.

생성된 IXmlSerializable 형식 작업

생성된 IXmlSerializable 형식에는 XmlNode 개체 배열을 반환하는 "nodesField"라는 private 필드가 있습니다. 이러한 형식의 인스턴스를 역직렬화하는 경우 XML 문서 개체 모델을 사용하여 이 필드를 통해 직접 XML 데이터에 액세스할 수 있습니다. 이 형식의 인스턴스를 serialize하는 경우 이 필드를 원하는 XML 데이터로 설정하면 serialize됩니다.

이 작업은 IXmlSerializable 구현을 통해 수행됩니다. 생성된 IXmlSerializable 형식에서 ReadXml 구현은 ReadNodes 클래스의 XmlSerializableServices 메서드를 호출합니다. 메서드는 XmlReader를 통해 제공된 XML을 XmlNode 개체 배열로 변환하는 도우미 메서드입니다. WriteXml 구현은 반대 작업을 수행하고 XmlNode 개체 배열을 XmlWriter 호출 시퀀스로 변환합니다. 이 작업은 WriteNodes 메서드를 사용하여 수행됩니다.

생성된 IXmlSerializable 클래스에서 스키마 내보내기 프로세스를 실행할 수 있습니다. 앞에서 설명했듯이 원래 스키마가 반환되지는 않습니다. 대신 XSD 형식의 와일드카드인 “anyType” 표준 XSD 형식을 얻게 됩니다.

이 작업은 XmlSchemaProviderAttribute 특성을 생성된 IXmlSerializable 클래스에 적용하고 AddDefaultSchema 메서드를 호출하여 “anyType” 형식을 생성하는 메서드를 지정하여 수행됩니다.

참고

XmlSerializableServices 형식은 이 특정 기능을 지원하기 위한 용도로만 제공됩니다. 다른 용도로는 사용하지 않는 것이 좋습니다.

가져오기 옵션: 고급 옵션

다음은 고급 가져오기 옵션입니다.

참고 항목