문서를 영문으로 보려면 영문 확인란을 선택하세요. 마우스 포인터를 텍스트 위로 이동시켜 팝업 창에서 영문 텍스트를 표시할 수도 있습니다.
번역
영문

.NET Framework의 형식 서식 지정

 

게시 날짜: 2016년 11월

형식 지정은 대개 결과 문자열을 사용자에게 표시하거나 deserialize하여 원본 데이터 형식으로 복원하기 위해 클래스, 구조체 또는 열거형 값의 인스턴스를 해당 문자열 표현으로 변환하는 프로세스입니다. 이 변환 프로세스에는 다음과 같은 여러 가지 문제점이 나타날 수 있습니다.

  • 내부적으로 값을 저장하는 방식에 사용자가 원하는 표시 방식이 반영되지 않을 수 있습니다. 예를 들어, 전화 번호가 사용자에게 친숙하지 않은 8009999999 형태로 저장될 수 있습니다. 이 전화 번호는 800-999-9999로 표시되어야 합니다. 이러한 방식으로 숫자의 형식을 지정하는 예제는 사용자 지정 형식 문자열 단원을 참조하세요.

  • 개체를 문자열 표현으로 변환하는 과정이 명확하지 않을 수 있습니다. 예를 들어, Temperature 또는 Person 개체의 문자열 표현이 어떻게 표시될지 명확하지 않습니다. 다양한 방식으로 Temperature 개체의 형식을 지정하는 예제는 표준 형식 문자열 단원을 참조하세요.

  • 값에 문화권별 형식 지정이 필요할 수 있습니다. 예를 들어, 숫자를 사용하여 통화 값을 나타내는 응용 프로그램에서는 숫자 문자열에 현재 문화권의 통화 기호, 그룹 구분 기호(대부분의 경우 1000 단위 구분 기호임) 및 소수점 기호가 포함되어야 합니다. 예제는 형식 공급자 및 IFormatProvider 인터페이스를 사용하여 문화권 구분 형식 지정 단원을 참조하세요.

  • 응용 프로그램에서 같은 값을 여러 가지 방법으로 표시해야 하는 경우도 있을 수 있습니다. 예를 들어, 응용 프로그램에서 해당 이름의 문자열 표현을 표시하거나 해당 내부 값을 표시하여 열거형 멤버를 나타낼 수 있습니다. 다양한 방식으로 DayOfWeek 열거형 멤버의 형식을 지정하는 예제는 표준 형식 문자열 단원을 참조하세요.

System_CAPS_note참고

형식 지정은 형식의 값을 문자열 표현으로 변환합니다. 구문 분석은 형식 지정과 반대 과정으로 진행됩니다. 구문 분석 작업은 해당 문자열 표현에서 데이터 형식의 인스턴스를 만듭니다. 문자열을 다른 데이터 형식으로 변환하는 방법에 대한 자세한 내용은 .NET Framework에서 문자열 구문 분석을 참조하세요.

.NET Framework에서는 개발자가 이러한 요구 사항을 해결할 수 있는 다양한 형식 지정 지원 기능을 제공합니다.

이 개요는 다음과 같은 단원으로 구성됩니다.

형식 지정의 기본 메커니즘은 이 항목의 뒷부분에 나오는 ToString 메서드를 사용한 기본 형식 지정 단원에서 설명하는 Object.ToString 메서드의 기본 구현입니다. 그러나 .NET Framework에서는 기본 형식 지정 지원을 수정하고 확장할 수 있는 여러 가지 방법을 제공합니다. 이러한 요구 사항은 다음과 같습니다.

  • Object.ToString 메서드를 재정의하여 개체의 값에 대한 사용자 지정 문자열 표현을 정의합니다. 자세한 내용은 이 항목의 뒷부분에 나오는 ToString 메서드 재정의 단원을 참조하세요.

  • 개체의 값에 대한 문자열 표현에서 여러 형식을 사용할 수 있도록 형식 지정자를 정의합니다. 예를 들어, 다음 문의 "X" 형식 지정자는 정수를 16진수 값의 문자열 표현으로 변환합니다.

    int integerValue = 60312;
    Console.WriteLine(integerValue.ToString("X"));   // Displays EB98.
    

    형식 지정자에 대한 자세한 내용은 ToString 메서드 및 형식 문자열 단원을 참조하세요.

  • 형식 공급자를 사용하여 특정 문화권의 형식 지정 규칙을 사용합니다. 예를 들어, 다음 문은 en-US 문화권의 형식 지정 규칙을 사용하여 통화 값을 표시합니다.

    double cost = 1632.54; 
    Console.WriteLine(cost.ToString("C", 
                      new System.Globalization.CultureInfo("en-US")));   
    // The example displays the following output:
    //       $1,632.54
    

    형식 공급자를 사용하여 형식을 지정하는 방법에 대한 자세한 내용은 형식 공급자 및 IFormatProvider 인터페이스 단원을 참조하세요.

  • IFormattable 인터페이스를 구현하여 Convert 클래스를 사용하여 문자열 변환과 복합 형식 지정을 지원합니다. 자세한 내용은 IFormattable 인터페이스 단원을 참조하세요.

  • 복합 형식 지정을 사용하여 값의 문자열 표현을 더 큰 문자열에 포함합니다. 자세한 내용은 복합 형식 지정 단원을 참조하세요.

  • ICustomFormatterIFormatProvider를 구현하여 완벽한 사용자 지정 형식 지정 솔루션을 제공합니다. 자세한 내용은 ICustomFormatter를 사용한 사용자 지정 형식 지정 단원을 참조하세요.

다음 단원에서는 개체를 문자열 표현으로 변환하는 데 대해 이러한 메서드를 검토합니다.

맨 위로 이동

System.Object에서 파생되는 모든 형식은 기본적으로 형식의 이름을 반환하는 매개 변수가 없는 ToString 메서드를 상속합니다. 다음 예제에서는 기본 ToString 메서드를 보여 줍니다. 이 예제에서는 구현이 없는 Automobile이라는 클래스를 정의합니다. 클래스가 인스턴스화되고 ToString 메서드가 호출되면 해당 형식 이름이 표시됩니다. 예제에서는 ToString 메서드를 명시적으로 호출하지 않습니다. Console.WriteLine(Object) 메서드는 인수로 전달되는 개체의 ToString 메서드를 암시적으로 호출합니다.

using System;

public class Automobile
{
   // No implementation. All members are inherited from Object.
}

public class Example
{
   public static void Main()
   {
      Automobile firstAuto = new Automobile();
      Console.WriteLine(firstAuto);
   }
}
// The example displays the following output:
//       Automobile
System_CAPS_warning경고

Windows 8.1부터 Windows 런타임에는 기본 형식 지원을 제공하며 단일 메서드(IStringable.ToString)를 사용하는 IStringable 인터페이스가 포함됩니다. 그러나 관리되는 형식은 IStringable인터페이스를 구현하지 않는 것이 좋습니다. 자세한 내용은 Windows 런타임 참조 페이지의 "IStringableObject.ToString 인터페이스" 단원을 참조하세요.

인터페이스를 제외한 모든 형식이 Object에서 파생되기 때문에 이 함수는 사용자 지정 클래스 또는 구조체에 자동으로 제공됩니다. 그러나 기본 ToString 메서드에서 제공하는 기능은 제한되어 있기 때문에 형식을 정의하더라도 해당 형식의 인스턴스에 대한 정보를 제공할 수 없습니다. 이 개체에 대한 정보를 제공하는 개체의 문자열 표현을 제공하려면 ToString 메서드를 재정의해야 합니다.

System_CAPS_note참고

구조체는 ValueType에서 상속되며, 이 형식은 다시 Object에서 파생됩니다. ValueTypeObject.ToString을 재정의해도 해당 구현은 동일합니다.

맨 위로 이동

형식 이름을 표시할 수 있는 경우가 종종 제한되어 형식의 사용자가 서로 다른 인스턴스를 구분할 수 없는 경우가 있습니다. 그러나 ToString 메서드를 재정의하여 개체 값을 더 유용하게 표현할 수 있습니다. 다음 예제에서는 Temperature 개체를 정의하고 ToString 메서드를 재정의하여 온도를 섭씨 단위로 표시합니다.

using System;

public class Temperature
{
   private decimal temp;

   public Temperature(decimal temperature)
   {
      this.temp = temperature;   
   }

   public override string ToString()
   {
      return this.temp.ToString("N1") + "°C";
   }
}

public class Example
{
   public static void Main()
   {
      Temperature currentTemperature = new Temperature(23.6m);
      Console.WriteLine("The current temperature is " +
                        currentTemperature.ToString());
   }
}
// The example displays the following output:
//       The current temperature is 23.6°C.

.NET Framework에서 각 기본 값 형식의 ToString 메서드는 개체의 이름 대신 개체의 값을 표시하도록 재정의되어 있습니다. 다음 표에는 각 기본 형식의 재정의가 나와 있습니다. 재정의된 메서드의 대부분은 ToString 메서드의 다른 오버로드를 호출하고 이를 해당 형식에 대한 일반적인 형식을 정의하는 "G" 형식 지정자와 현재 문화권을 나타내는 IFormatProvider 개체에 전달합니다.

형식

ToString 재정의

Boolean

Boolean.TrueString 또는 Boolean.FalseString을 반환합니다.

Byte

Byte.ToString("G", NumberFormatInfo.CurrentInfo)을 호출하여 현재 문화권에 대한 Byte 값의 형식을 지정합니다.

Char

문자를 문자열로 반환합니다.

DateTime

DateTime.ToString("G", DatetimeFormatInfo.CurrentInfo)을 호출하여 현재 문화권에 대한 날짜 및 시간 값의 형식을 지정합니다.

Decimal

Decimal.ToString("G", NumberFormatInfo.CurrentInfo)을 호출하여 현재 문화권에 대한 Decimal 값의 형식을 지정합니다.

Double

Double.ToString("G", NumberFormatInfo.CurrentInfo)을 호출하여 현재 문화권에 대한 Double 값의 형식을 지정합니다.

Int16

Int16.ToString("G", NumberFormatInfo.CurrentInfo)을 호출하여 현재 문화권에 대한 Int16 값의 형식을 지정합니다.

Int32

Int32.ToString("G", NumberFormatInfo.CurrentInfo)을 호출하여 현재 문화권에 대한 Int32 값의 형식을 지정합니다.

Int64

Int64.ToString("G", NumberFormatInfo.CurrentInfo)을 호출하여 현재 문화권에 대한 Int64 값의 형식을 지정합니다.

SByte

SByte.ToString("G", NumberFormatInfo.CurrentInfo)을 호출하여 현재 문화권에 대한 SByte 값의 형식을 지정합니다.

Single

Single.ToString("G", NumberFormatInfo.CurrentInfo)을 호출하여 현재 문화권에 대한 Single 값의 형식을 지정합니다.

UInt16

UInt16.ToString("G", NumberFormatInfo.CurrentInfo)을 호출하여 현재 문화권에 대한 UInt16 값의 형식을 지정합니다.

UInt32

UInt32.ToString("G", NumberFormatInfo.CurrentInfo)을 호출하여 현재 문화권에 대한 UInt32 값의 형식을 지정합니다.

UInt64

UInt64.ToString("G", NumberFormatInfo.CurrentInfo)을 호출하여 현재 문화권에 대한 UInt64 값의 형식을 지정합니다.

맨 위로 이동

개체에 문자열 표현이 하나만 있는 경우에는 기본 ToString 메서드를 사용하거나 ToString을 재정의합니다. 하지만 개체의 값에 여러 표현이 있는 경우가 자주 있습니다. 예를 들어 온도는 화씨, 섭씨 또는 캘빈으로 표시할 수 있습니다. 마찬가지로 정수 값 10도 10, 10.0, 1.0e01, $10.00 등과 같은 여러 가지 방식으로 표현될 수 있습니다.

단일 값에 여러 문자열 표현을 허용하기 위해 .NET Framework에서는 형식 문자열을 사용합니다. 형식 문자열은 하나 이상의 미리 정의된 형식 지정자가 들어 있는 문자열이며, 이러한 형식 지정자는 ToString 메서드가 해당 출력의 형식을 지정하는 방식을 정의한 단일 문자 또는 문자 그룹입니다. 형식 문자열은 개체의 ToString 메서드에 매개 변수로 전달되어 개체의 값에 대한 문자열 표현의 표시 방법을 결정합니다.

.NET Framework의 모든 숫자 형식, 날짜/시간 형식 및 열거형 형식은 미리 정의된 형식 지정자 집합을 지원합니다. 형식 문자열을 사용하여 응용 프로그램 정의 데이터 형식의 여러 문자열 표현도 정의할 수 있습니다.

표준 형식 문자열에는 개체의 문자열 표현을 정의하는 영문자인 단일 형식 지정자와 함께 결과 문자열을 표시하는 데 사용할 자릿수에 영향을 주는 선택적 전체 자릿수 지정자가 포함됩니다. 전체 자릿수 지정자가 생략되었거나 지원되지 않으면 표준 형식 지정자는 표준 형식 문자열과 같습니다.

.NET Framework에서는 모든 숫자 형식, 날짜/시간 형식 및 열거형 형식에 대한 표준 형식 지정자 집합을 정의합니다. 예를 들어, 이러한 각 범주는 해당 형식 값에 대한 일반적인 문자열 표현을 정의하는 "G" 표준 형식 지정자를 지원합니다.

열거형 형식의 표준 형식 문자열은 값의 문자열 표현을 직접 제어합니다. 열거형 값의 ToString 메서드에 전달된 형식 문자열은 값이 문자열 이름("G" 및 "F" 형식 지정자), 내부 정수 값("D" 형식 지정자) 또는 16진수 값("X" 형식 지정자)을 사용하여 표시되는지 여부를 결정합니다. 다음 예제에서는 표준 형식 문자열을 사용하여 DayOfWeek 열거형 값의 형식을 지정하는 방법을 보여 줍니다.

DayOfWeek thisDay = DayOfWeek.Monday;
string[] formatStrings = {"G", "F", "D", "X"};

foreach (string formatString in formatStrings)
   Console.WriteLine(thisDay.ToString(formatString));
// The example displays the following output:
//       Monday
//       Monday
//       1
//       00000001

열거형 형식 문자열에 대한 자세한 내용은 열거형 형식 문자열을 참조하세요.

일반적으로 숫자 형식의 표준 형식 문자열은 정확한 모양이 하나 이상의 속성 값에 의해 제어되는 결과 문자열을 정의합니다. 예를 들어, "C" 형식 지정자는 숫자의 형식을 통화 값으로 지정합니다. "C" 형식 지정자를 유일한 매개 변수로 사용하여 ToString 메서드를 호출하면 현재 문화권의 NumberFormatInfo 개체에 있는 다음 속성 값이 숫자 값의 문자열 표현을 정의하는 데 사용됩니다.

  • 현재 문화권의 통화 기호를 지정하는 CurrencySymbol 속성

  • 다음과 같은 사항을 결정하는 정수를 반환하는 CurrencyNegativePattern 또는 CurrencyPositivePattern 속성

    • 통화 기호의 위치

    • 음수 값이 선행 음수 기호, 후행 음수 기호 또는 괄호로 표시되는지 여부

    • 숫자 값과 통화 기호 사이에 공백이 표시되는지 여부

  • 결과 문자열의 소수 자릿수를 정의하는 CurrencyDecimalDigits 속성

  • 결과 문자열의 소수 구분 기호를 정의하는 CurrencyDecimalSeparator 속성

  • 그룹 구분 기호를 정의하는 CurrencyGroupSeparator 속성

  • 정수 부분의 각 그룹 자릿수를 정의하는 CurrencyGroupSizes 속성

  • 음수 값을 나타내는 데 괄호가 사용되지 않는 경우 결과 문자열에 사용되는 음수 기호를 결정하는 NegativeSign 속성

이외에도 숫자 형식 문자열에는 전체 자릿수 지정자가 포함될 수도 있습니다. 이 지정자의 의미는 해당 지정자가 사용되는 형식 문자열에 따라 달라지지만 일반적으로 결과 문자열에 표시될 전체 자릿수나 소수 자릿수를 나타냅니다. 예를 들어, 다음 예제에서는 "X4" 표준 숫자 문자열과 전체 자릿수 지정자를 사용하여 네 자리의 16진수로 구성된 문자열 값을 만듭니다.

byte[] byteValues = { 12, 163, 255 };
foreach (byte byteValue in byteValues)
   Console.WriteLine(byteValue.ToString("X4"));
// The example displays the following output:
//       000C
//       00A3
//       00FF

표준 숫자 서식 지정 문자열에 대한 자세한 내용은 표준 숫자 형식 문자열을 참조하세요.

날짜 및 시간 값의 표준 형식 문자열은 특정 DateTimeFormatInfo 속성에 저장된 사용자 지정 형식 문자열의 별칭입니다. 예를 들어, "D" 형식 지정자를 사용하여 날짜 및 시간 값의 ToString 메서드를 호출하면 현재 문화권의 DateTimeFormatInfo.LongDatePattern 속성에 저장된 사용자 지정 형식 문자열을 사용하여 날짜 및 시간이 표시됩니다. 사용자 지정 형식 문자열에 대한 자세한 내용은 다음 단원을 참조하세요. 다음 예제에서는 이러한 관계를 보여 줍니다.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      DateTime date1 = new DateTime(2009, 6, 30);
      Console.WriteLine("D Format Specifier:     {0:D}", date1);
      string longPattern = CultureInfo.CurrentCulture.DateTimeFormat.LongDatePattern;
      Console.WriteLine("'{0}' custom format string:     {1}", 
                        longPattern, date1.ToString(longPattern));
   }
}
// The example displays the following output when run on a system whose
// current culture is en-US:
//    D Format Specifier:     Tuesday, June 30, 2009
//    'dddd, MMMM dd, yyyy' custom format string:     Tuesday, June 30, 2009

표준 날짜 및 시간 형식 문자열에 대한 자세한 내용은 표준 날짜 및 시간 형식 문자열을 참조하세요.

표준 형식 문자열을 사용하여 개체의 ToString(String) 메서드에 의해 생성되는 응용 프로그램 정의 개체의 문자열 표현도 정의할 수 있습니다. 개체가 지원하는 특정 표준 형식 지정자를 정의하고 이러한 지정자가 대/소문자를 구분하는지 여부를 결정할 수 있습니다. ToString(String) 메서드의 구현에서는 다음을 지원해야 합니다.

  • 개체의 사용자 지정 또는 일반 형식을 나타내는 "G" 형식 지정자. 개체의 ToString 메서드에 대한 매개 변수가 없는 오버로드는 해당 ToString(String) 오버로드를 호출하고 이를 "G" 표준 형식 문자열에 전달해야 합니다.

  • null 참조(Visual Basic의 경우 Nothing)와 동일한 형식 지정자에 대한 지원. null 참조와 동일한 형식 지정자는 "G" 형식 지정자와 같은 것으로 간주됩니다.

예를 들어 Temperature 클래스는 섭씨 온도를 내부적으로 저장하고 형식 지정자를 사용하여 Temperature 개체의 값을 섭씨, 화씨 및 캘빈으로 표시할 수 있습니다. 다음 예제에서 이에 대해 설명합니다.

using System;

public class Temperature
{
   private decimal m_Temp;

   public Temperature(decimal temperature)
   {
      this.m_Temp = temperature;
   }

   public decimal Celsius
   {
      get { return this.m_Temp; }
   }

   public decimal Kelvin
   {
      get { return this.m_Temp + 273.15m; }   
   }

   public decimal Fahrenheit
   {
      get { return Math.Round(((decimal) (this.m_Temp * 9 / 5 + 32)), 2); }
   }

   public override string ToString()
   {
      return this.ToString("C");
   }

   public string ToString(string format)
   {  
      // Handle null or empty string.
      if (String.IsNullOrEmpty(format)) format = "C";
      // Remove spaces and convert to uppercase.
      format = format.Trim().ToUpperInvariant();      

      // Convert temperature to Fahrenheit and return string.
      switch (format)
      {
         // Convert temperature to Fahrenheit and return string.
         case "F":
            return this.Fahrenheit.ToString("N2") + " °F";
         // Convert temperature to Kelvin and return string.
         case "K":
            return this.Kelvin.ToString("N2") + " K";
         // return temperature in Celsius.
         case "G":
         case "C":
            return this.Celsius.ToString("N2") + " °C";
         default:
            throw new FormatException(String.Format("The '{0}' format string is not supported.", format));
      }      
   }
}

public class Example
{
   public static void Main()
   {
      Temperature temp1 = new Temperature(0m);
      Console.WriteLine(temp1.ToString());
      Console.WriteLine(temp1.ToString("G"));
      Console.WriteLine(temp1.ToString("C"));
      Console.WriteLine(temp1.ToString("F"));
      Console.WriteLine(temp1.ToString("K"));

      Temperature temp2 = new Temperature(-40m);
      Console.WriteLine(temp2.ToString());
      Console.WriteLine(temp2.ToString("G"));
      Console.WriteLine(temp2.ToString("C"));
      Console.WriteLine(temp2.ToString("F"));
      Console.WriteLine(temp2.ToString("K"));

      Temperature temp3 = new Temperature(16m);
      Console.WriteLine(temp3.ToString());
      Console.WriteLine(temp3.ToString("G"));
      Console.WriteLine(temp3.ToString("C"));
      Console.WriteLine(temp3.ToString("F"));
      Console.WriteLine(temp3.ToString("K"));

      Console.WriteLine(String.Format("The temperature is now {0:F}.", temp3));
   }
}
// The example displays the following output:
//       0.00 °C
//       0.00 °C
//       0.00 °C
//       32.00 °F
//       273.15 K
//       -40.00 °C
//       -40.00 °C
//       -40.00 °C
//       -40.00 °F
//       233.15 K
//       16.00 °C
//       16.00 °C
//       16.00 °C
//       60.80 °F
//       289.15 K
//       The temperature is now 16.00 °C.

맨 위로 이동

표준 형식 문자열 외에도 .NET Framework에서는 숫자 값과 날짜 및 시간 값에 대한 사용자 지정 형식 문자열을 정의합니다. 사용자 지정 형식 문자열은 값의 문자열 표현을 정의하는 하나 이상의 사용자 지정 형식 지정자로 구성됩니다. 예를 들어, en-US 문화권의 경우 사용자 지정 날짜 및 시간 형식 문자열 "yyyy/mm/dd hh:mm:ss t zzz"는 날짜를 "2008/11/15 07:45:00.0000 P -08:00" 형태의 문자열 표현으로 변환합니다. 마찬가지로 사용자 지정 형식 문자열 "0000"은 정수 값 12를 "0012"로 변환합니다. 사용자 지정 서식 문자열의 전체 목록은 사용자 지정 날짜 및 시간 형식 문자열사용자 지정 숫자 형식 문자열을 참조하세요.

형식 문자열이 단일 사용자 지정 형식 지정자로 구성된 경우에는 표준 형식 지정자와 혼동되지 않도록 형식 지정자 앞에 백분율 기호(%)가 와야 합니다. 다음 예제에서는 "M" 사용자 지정 형식 지정자를 사용하여 특정 날짜의 월에 해당하는 한 자리 또는 두 자리 숫자를 표시합니다.

DateTime date1 = new DateTime(2009, 9, 8);
Console.WriteLine(date1.ToString("%M"));       // Displays 9

많은 표준 형식 문자열은 DateTimeFormatInfo 개체의 속성에 정의된 사용자 지정 형식 문자열의 별칭입니다. 또한 사용자 지정 형식 문자열을 사용하면 상당히 융통성 있게 숫자 값 또는 날짜 및 시간 값에 대한 응용 프로그램 정의 형식 지정 기능을 제공할 수 있습니다. 여러 사용자 지정 형식 지정자를 하나의 사용자 지정 형식 문자열로 결합하여 숫자 값과 날짜 및 시간 값에 대한 사용자 지정 결과 문자열을 정의할 수 있습니다. 다음 예제에서는 월 이름, 일, 연도 및 괄호로 묶은 요일을 차례로 표시하는 사용자 지정 형식 문자열을 정의합니다.

string customFormat = "MMMM dd, yyyy (dddd)";
DateTime date1 = new DateTime(2009, 8, 28);
Console.WriteLine(date1.ToString(customFormat));   
// The example displays the following output if run on a system
// whose language is English:
//       August 28, 2009 (Friday)      

다음 예제에서는 Int64 값을 7자리 표준 미국 전화 번호로 지역 번호와 함께 표시하는 사용자 지정 서식 문자열을 정의합니다.

using System;

public class Example
{
   public static void Main()
   {
      long number = 8009999999;
      string fmt = "000-000-0000";
      Console.WriteLine(number.ToString(fmt));
   }
}
// The example displays the following output:
//        800-999-9999

일반적으로 표준 형식 문자열로 응용 프로그램 정의 형식의 형식 지정 요구를 대부분 처리할 수 있지만 사용자 지정 형식 지정자를 정의하여 형식의 형식을 지정할 수도 있습니다.

맨 위로 이동

모든 숫자 형식(즉, Byte, Decimal, Double, Int16, Int32, Int64, SByte, Single, UInt16, UInt32, UInt64, BigInteger 형식)

DateTime, DateTimeOffset, TimeSpan, Guid와 모든 열거형 형식은 형식 문자열을 사용한 서식 지정을 지원합니다. 각 형식에서 지원되는 형식 문자열에 대한 자세한 내용은 다음 항목을 참조하세요.

제목

정의

표준 숫자 형식 문자열

숫자 값의 일반적으로 사용되는 문자열 표현을 만드는 표준 형식 문자열에 대해 설명합니다.

사용자 지정 숫자 형식 문자열

숫자 값의 응용 프로그램별 형식을 만드는 사용자 지정 형식 문자열에 대해 설명합니다.

표준 날짜 및 시간 형식 문자열

DateTime 값의 일반적으로 사용되는 문자열 표현을 만드는 표준 형식 문자열에 대해 설명합니다.

사용자 지정 날짜 및 시간 형식 문자열

DateTime 값의 응용 프로그램별 형식을 만드는 사용자 지정 형식 문자열에 대해 설명합니다.

표준 TimeSpan 서식 문자열

시간 간격의 일반적으로 사용되는 문자열 표현을 만드는 표준 형식 문자열에 대해 설명합니다.

사용자 지정 TimeSpan 서식 문자열

시간 간격의 응용 프로그램별 형식을 만드는 사용자 지정 형식 문자열에 대해 설명합니다.

열거형 형식 문자열

열거형 값의 문자열 표현을 만드는 데 사용되는 표준 형식 문자열에 대해 설명합니다.

Guid.ToString(String)

Guid 값에 대한 표준 형식 문자열에 대해 설명합니다.

형식 지정자를 사용하여 개체의 형식 지정을 사용자 지정할 수 있기는 하지만 의미 있는 개체의 문자열 표현을 만들려면 추가 형식 지정 정보가 필요한 경우가 종종 있습니다. 예를 들어, C" 표준 형식 문자열이나 "$ #,#.00" 같은 사용자 지정 형식 문자열을 사용하여 숫자의 형식을 통화 값으로 지정하려면 최소한 올바른 통화 기호, 그룹 구분 기호 및 소수 구분 기호에 대한 정보를 형식 지정된 문자열에 포함할 수 있어야 합니다. .NET Framework에서는 이러한 추가 형식 지정 정보를 IFormatProvider 인터페이스를 통해 사용할 수 있습니다. 이러한 인터페이스는 숫자 형식과 날짜 및 시간 형식의 ToString 메서드에 대한 하나 이상이 오버로드에 매개 변수로 제공됩니다. IFormatProvider 구현은 문화권별 형식을 지원하기 위해 .NET Framework에서 사용됩니다. 다음 예제에서는 서로 다른 문화권을 나타내는 세 IFormatProvider 개체를 사용하여 형식을 지정할 때 개체의 문자열 표현이 어떻게 바뀌는지 보여 줍니다.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      decimal value = 1603.42m;
      Console.WriteLine(value.ToString("C3", new CultureInfo("en-US")));
      Console.WriteLine(value.ToString("C3", new CultureInfo("fr-FR")));
      Console.WriteLine(value.ToString("C3", new CultureInfo("de-DE")));
   }
}
// The example displays the following output:
//       $1,603.420
//       1 603,420 €
//       1.603,420 €

IFormatProvider 인터페이스에는 GetFormat(Type) 메서드가 하나 있으며, 이 메서드에는 형식 지정 정보를 제공하는 개체의 형식을 지정하는 매개 변수가 하나 있습니다. 이 메서드는 해당 형식의 개체를 제공할 수 있는 경우 해당 형식의 개체를 반환합니다. 그러지 않으면 null 참조(Visual Basic의 경우 Nothing)를 반환합니다.

IFormatProvider.GetFormat은 콜백 메서드입니다. ToString 매개 변수가 포함된 IFormatProvider 메서드 오버로드를 호출하면 해당 GetFormat 개체의 IFormatProvider 메서드가 호출됩니다. GetFormat 메서드는 formatType 매개 변수에 지정된 대로 필요한 형식 지정 정보를 제공하는 개체를 ToString 메서드에 반환합니다.

IFormatProvider 형식의 매개 변수를 포함하는 형식 지정 또는 문자열 변환 메서드가 많이 있기는 하지만 대부분의 경우 메서드가 호출될 때 매개 변수의 값이 무시됩니다. 다음 표에서는 매개 변수를 사용하는 형식 지정 메서드와 이러한 메서드가 Type 메서드로 전달하는 IFormatProvider.GetFormat 개체의 형식을 보여 줍니다.

메서드

formatType 매개 변수의 형식

숫자 형식의 ToString 메서드

System.Globalization.NumberFormatInfo

날짜 및 시간 형식의 ToString 메서드

System.Globalization.DateTimeFormatInfo

String.Format

System.ICustomFormatter

StringBuilder.AppendFormat

System.ICustomFormatter

System_CAPS_note참고

숫자 형식과 날짜 및 시간 형식의 ToString 메서드는 오버로드되며, 일부 오버로드에만 IFormatProvider 매개 변수가 포함됩니다. 메서드에 IFormatProvider 형식의 매개 변수가 없으면 CultureInfo.CurrentCulture 속성에 의해 반환되는 개체가 대신 전달됩니다. 예를 들어, 기본 Int32.ToString() 메서드를 호출하면 결과적으로 Int32.ToString("G", System.Globalization.CultureInfo.CurrentCulture) 같은 메서드가 호출됩니다.

.NET Framework에는 IFormatProvider를 구현하는 세 가지 클래스가 있습니다.

사용자 고유의 형식 공급자를 구현하여 이러한 클래스 중 하나를 대체할 수도 있습니다. 그러나 GetFormat 메서드에 형식 지정 정보를 제공해야 하는 경우에는 구현된 형식 공급자의 ToString 메서드에서 위의 표에 나와 있는 형식의 개체를 반환해야 합니다.

맨 위로 이동

기본적으로 숫자 값의 형식은 문화권을 구분합니다. 형식 지정 메서드를 호출할 때 문화권을 지정하지 않으면 현재 스레드 문화권의 형식 규칙이 사용됩니다. 이는 현재 스레드 문화권을 4번 변경한 후 Decimal.ToString(String) 메서드를 호출하는 다음 예제에 나와 있습니다. 각각의 경우 결과 문자열은 현재 문화권의 형식 규칙을 반영합니다. 이는 ToStringToString(String) 메서드가 각 숫자 형식의 ToString(String, IFormatProvider) 메서드에 대한 호출을 래핑하기 때문입니다.

using System;
using System.Globalization;
using System.Threading;

public class Example
{
   public static void Main()
   {
      string[] cultureNames = { "en-US", "fr-FR", "es-MX", "de-DE" };
      Decimal value = 1043.17m;

      foreach (var cultureName in cultureNames) {
         // Change the current thread culture.
         Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName);
         Console.WriteLine("The current culture is {0}", 
                           Thread.CurrentThread.CurrentCulture.Name);
         Console.WriteLine(value.ToString("C2"));
         Console.WriteLine();
      }   
   }
}
// The example displays the following output:
//       The current culture is en-US
//       $1,043.17
//       
//       The current culture is fr-FR
//       1 043,17 €
//       
//       The current culture is es-MX
//       $1,043.17
//       
//       The current culture is de-DE
//       1.043,17 €

ToString 매개 변수를 포함하는 provider 오버로드를 호출하고 여기에 다음 중 하나를 전달하여 특정 문화권에 대한 숫자 값의 형식을 지정할 수도 있습니다.

다음 예제에서는 부동 소수점 수의 형식을 지정하기 위해 영어(미국) 및 영어(영국) 문화권과 프랑스어 및 러시아어 중립 문화권을 나타내는 NumberFormatInfo 개체를 사용합니다.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {                                                                                                    
      Double value = 1043.62957;
      string[] cultureNames = { "en-US", "en-GB", "ru", "fr" };

      foreach (var name in cultureNames) {
         NumberFormatInfo nfi = CultureInfo.CreateSpecificCulture(name).NumberFormat;
         Console.WriteLine("{0,-6} {1}", name + ":", value.ToString("N3", nfi));
      }   
   }
}
// The example displays the following output:
//       en-US: 1,043.630
//       en-GB: 1,043.630
//       ru:    1 043,630
//       fr:    1 043,630

기본적으로 날짜 및 시간 값의 형식은 문화권을 구분합니다. 형식 지정 메서드를 호출할 때 문화권을 지정하지 않으면 현재 스레드 문화권의 형식 규칙이 사용됩니다. 이는 현재 스레드 문화권을 4번 변경한 후 DateTime.ToString(String) 메서드를 호출하는 다음 예제에 나와 있습니다. 각각의 경우 결과 문자열은 현재 문화권의 형식 규칙을 반영합니다. 이는 DateTime.ToString(), DateTime.ToString(String), DateTimeOffset.ToString()DateTimeOffset.ToString(String) 메서드가 DateTime.ToString(String, IFormatProvider)DateTimeOffset.ToString(String, IFormatProvider) 메서드에 대한 호출을 래핑하기 때문입니다.

using System;
using System.Globalization;
using System.Threading;

public class Example
{
   public static void Main()
   {
      string[] cultureNames = { "en-US", "fr-FR", "es-MX", "de-DE" };
      DateTime dateToFormat = new DateTime(2012, 5, 28, 11, 30, 0);

      foreach (var cultureName in cultureNames) {
         // Change the current thread culture.
         Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName);
         Console.WriteLine("The current culture is {0}", 
                           Thread.CurrentThread.CurrentCulture.Name);
         Console.WriteLine(dateToFormat.ToString("F"));
         Console.WriteLine();
      }   
   }
}
// The example displays the following output:
//       The current culture is en-US
//       Monday, May 28, 2012 11:30:00 AM
//       
//       The current culture is fr-FR
//       lundi 28 mai 2012 11:30:00
//       
//       The current culture is es-MX
//       lunes, 28 de mayo de 2012 11:30:00 a.m.
//       
//       The current culture is de-DE
//       Montag, 28. Mai 2012 11:30:00

DateTime.ToString 매개 변수를 포함하는 DateTimeOffset.ToString 또는 provider 오버로드를 호출하고 여기에 다음 중 하나를 전달하여 특정 문화권에 대한 날짜 및 시간 값의 형식을 지정할 수도 있습니다.

다음 예제에서는 날짜의 형식을 지정하기 위해 영어(미국) 및 영어(영국) 문화권과 프랑스어 및 러시아어 중립 문화권을 나타내는 DateTimeFormatInfo 개체를 사용합니다.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {                                                                                                    
      DateTime dat1 = new DateTime(2012, 5, 28, 11, 30, 0);
      string[] cultureNames = { "en-US", "en-GB", "ru", "fr" };

      foreach (var name in cultureNames) {
         DateTimeFormatInfo dtfi = CultureInfo.CreateSpecificCulture(name).DateTimeFormat;
         Console.WriteLine("{0}: {1}", name, dat1.ToString(dtfi));
      }   
   }
}
// The example displays the following output:
//       en-US: 5/28/2012 11:30:00 AM
//       en-GB: 28/05/2012 11:30:00
//       ru: 28.05.2012 11:30:00
//       fr: 28/05/2012 11:30:00

일반적으로 형식 문자열과 ToString 매개 변수로 IFormatProvider 메서드를 오버로드하는 형식은 IFormattable 인터페이스도 구현합니다. 이 인터페이스에는 형식 문자열과 형식 공급자가 매개 변수로 포함되어 있는 IFormattable.ToString(String, IFormatProvider)이라는 단일 멤버가 있습니다.

응용 프로그램 정의 클래스에 대해 IFormattable 인터페이스를 구현하면 다음과 같은 두 가지 이점이 있습니다.

다음 예제에서는 Temperature 인터페이스를 구현하는 IFormattable 클래스를 정의합니다. 이 클래스는 온도를 섭씨로 표시하는 "C" 또는 "G" 형식 지정자, 온도를 화씨로 표시하는 "F" 형식 지정자 또는 온도를 켈빈으로 표시하는 "K" 형식 지정자를 지원합니다.

using System;
using System.Globalization;

public class Temperature : IFormattable
{
   private decimal m_Temp;

   public Temperature(decimal temperature)
   {
      this.m_Temp = temperature;
   }

   public decimal Celsius
   {
      get { return this.m_Temp; }
   }

   public decimal Kelvin
   {
      get { return this.m_Temp + 273.15m; }   
   }

   public decimal Fahrenheit
   {
      get { return Math.Round((decimal) this.m_Temp * 9 / 5 + 32, 2); }
   }

   public override string ToString()
   {
      return this.ToString("G", null);
   }

   public string ToString(string format)
   {
      return this.ToString(format, null);
   }

   public string ToString(string format, IFormatProvider provider)  
   {
      // Handle null or empty arguments.
      if (String.IsNullOrEmpty(format)) format = "G";
      // Remove any white space and convert to uppercase.
      format = format.Trim().ToUpperInvariant();

      if (provider == null) provider = NumberFormatInfo.CurrentInfo;

      switch (format)
      {
         // Convert temperature to Fahrenheit and return string.
         case "F":
            return this.Fahrenheit.ToString("N2", provider) + "°F";
         // Convert temperature to Kelvin and return string.
         case "K":
            return this.Kelvin.ToString("N2", provider) + "K";
         // Return temperature in Celsius.
         case "C":
         case "G":
            return this.Celsius.ToString("N2", provider) + "°C";
         default:
            throw new FormatException(String.Format("The '{0}' format string is not supported.", format));
      }      
   }
}

다음 예제에서는 Temperature 개체를 인스턴스화합니다. 그런 다음 ToString 메서드를 호출하고 여러 복합 형식 문자열을 사용하여 Temperature 개체의 다양한 문자열 표현을 얻습니다. 이 메서드를 호출할 때마다 자동으로 IFormattable 클래스의 Temperature 구현도 호출됩니다.

public class Example
{
   public static void Main()
   {
      Temperature temp1 = new Temperature(22m);
      Console.WriteLine(Convert.ToString(temp1, new CultureInfo("ja-JP")));
      Console.WriteLine("Temperature: {0:K}", temp1);
      Console.WriteLine("Temperature: {0:F}", temp1);
      Console.WriteLine(String.Format(new CultureInfo("fr-FR"), "Temperature: {0:F}", temp1));
   }
}
// The example displays the following output:
//       22.00°C
//       Temperature: 295.15°K
//       Temperature: 71.60°F
//       Temperature: 71,60°F

맨 위로 이동

String.FormatStringBuilder.AppendFormat 같은 일부 메서드는 복합 형식 지정을 지원합니다. 복합 형식 문자열은 0개 이상의 개체에 대한 문자열 표현이 통합된 단일 문자열을 반환하는 일종의 템플릿입니다. 복합 형식 문자열에서는 각 개체가 인덱싱된 형식 항목으로 표현됩니다. 형식 항목의 인덱스는 메서드의 매개 변수 목록에 표시되는 개체의 위치에 해당합니다. 인덱스는 0에서 시작합니다. 예를 들어 다음과 같은 String.Format 메서드 호출에서 첫 번째 형식 항목인 {0:D}thatDate의 문자열 표현으로 바뀌고, 두 번째 형식 항목인 {1}item1의 문자열 표현으로 바뀌고, 세 번째 형식 항목인 {2:C2}item1.Value의 문자열 표현으로 바뀝니다.

result = String.Format("On {0:d}, the inventory of {1} was worth {2:C2}.", 
                       thatDate, item1, item1.Value);
Console.WriteLine(result);                            
// The example displays output like the following if run on a system
// whose current culture is en-US:
//       On 5/1/2009, the inventory of WidgetA was worth $107.44.

형식 항목을 해당 개체의 문자열 표현으로 바꾸는 것 외에도 형식 항목을 통해 다음을 제어할 수 있습니다.

  • 개체가 IFormattable 인터페이스를 구현하고 형식 문자열을 지원하는 경우 개체가 문자열로 표현되는 특정 방식. 이렇게 하려면 형식 항목의 인덱스 뒤에 :(콜론) 및 유효한 형식 문자열을 추가합니다. 이전 예제에서는 날짜 값의 형식을 "d"(짧은 날짜 패턴) 형식 문자열(예: {0:d})로 지정하고 숫자 값의 형식을 "C2" 형식 문자열(예: {2:C2})로 지정하여 소수 2자리의 통화 값으로 숫자를 나타냈습니다.

  • 개체의 문자열 표현을 포함하는 필드의 너비 및 해당 필드의 문자열 표현 맞춤. 이렇게 하려면 형식 항목의 인덱스 뒤에 ,(쉼표) 및 필드 너비를 추가합니다. 필드 너비가 양수 값이면 문자열이 필드에 오른쪽 맞춤되고, 필드 너비가 음수 값이면 왼쪽 맞춤됩니다. 다음 예제에서는 날짜 값을 20자 필드에 왼쪽 맞춤하고, 소수 1자리의 10진수 값을 11자 필드에 오른쪽 맞춤합니다.

    DateTime startDate = new DateTime(2015, 8, 28, 6, 0, 0);
    decimal[] temps = { 73.452m, 68.98m, 72.6m, 69.24563m,
                       74.1m, 72.156m, 72.228m };
    Console.WriteLine("{0,-20} {1,11}\n", "Date", "Temperature");
    for (int ctr = 0; ctr < temps.Length; ctr++)
       Console.WriteLine("{0,-20:g} {1,11:N1}", startDate.AddDays(ctr), temps[ctr]);
    
    // The example displays the following output:
    //       Date                 Temperature
    //
    //       8/28/2015 6:00 AM           73.5
    //       8/29/2015 6:00 AM           69.0
    //       8/30/2015 6:00 AM           72.6
    //       8/31/2015 6:00 AM           69.2
    //       9/1/2015 6:00 AM            74.1
    //       9/2/2015 6:00 AM            72.2
    //       9/3/2015 6:00 AM            72.2
    

    맞춤 문자열 구성 요소와 형식 문자열 구성 요소가 둘 다 있는 경우 맞춤 문자열 구성 요소가 우선합니다(예: {0,-20:g}).

복합 서식 지정에 대한 자세한 내용은 복합 형식 지정을 참조하세요.

맨 위로 이동

두 복합 형식 지정 메서드(String.Format(IFormatProvider, String, Object[])StringBuilder.AppendFormat(IFormatProvider, String, Object[]))에 사용자 지정 형식을 지원하는 형식 공급자 매개 변수가 포함되어 있습니다. 이러한 형식 지정 메서드 중 하나를 호출하면 Type 인터페이스를 나타내는 ICustomFormatter 개체가 형식 공급자의 GetFormat 메서드에 전달됩니다. 그러면 GetFormat 메서드가 사용자 지정 형식 지정을 제공하는 ICustomFormatter 구현을 반환합니다.

ICustomFormatter 인터페이스에는 복합 형식 지정 메서드에 의해 자동으로 복합 형식 문자열의 각 형식 항목에 대해 한 번씩 호출되는 Format(String, Object, IFormatProvider)라는 메서드가 하나 있습니다. Format(String, Object, IFormatProvider) 메서드에는 세 개의 매개 변수 즉, 형식 항목의 formatString 인수를 나타내는 형식 문자열, 형식을 지정할 개체 및 형식 지정 서비스를 제공하는 IFormatProvider 개체가 포함되어 있습니다. 일반적으로 ICustomFormatter를 구현하는 클래스는 IFormatProvider도 구현하여 이 마지막 매개 변수가 사용자 지정 형식 지정 클래스를 참조하도록 합니다. 이 메서드는 형식을 지정할 개체의 사용자 지정 형식 문자열 표현을 반환합니다. 이 메서드가 개체의 형식을 지정할 수 없는 경우에는 null 참조(Visual Basic의 경우 Nothing)가 반환되어야 합니다.

다음 예제에서는 정수 값을 뒤에 공백이 오는 두 자리 16진수 값 시퀀스로 표시하는 ICustomFormatter라는 ByteByByteFormatter 구현을 제공합니다.

public class ByteByByteFormatter : IFormatProvider, ICustomFormatter
{
   public object GetFormat(Type formatType)
   { 
      if (formatType == typeof(ICustomFormatter))
         return this;
      else
         return null;
   }

   public string Format(string format, object arg, 
                          IFormatProvider formatProvider)
   {   
      if (! formatProvider.Equals(this)) return null;

      // Handle only hexadecimal format string.
      if (! format.StartsWith("X")) return null;

      byte[] bytes;
      string output = null;

      // Handle only integral types.
      if (arg is Byte) 
         bytes = BitConverter.GetBytes((Byte) arg);
      else if (arg is Int16)
         bytes = BitConverter.GetBytes((Int16) arg);
      else if (arg is Int32)
         bytes = BitConverter.GetBytes((Int32) arg);
      else if (arg is Int64)   
         bytes = BitConverter.GetBytes((Int64) arg);
      else if (arg is SByte)
         bytes = BitConverter.GetBytes((SByte) arg);
      else if (arg is UInt16)
         bytes = BitConverter.GetBytes((UInt16) arg);
      else if (arg is UInt32)
         bytes = BitConverter.GetBytes((UInt32) arg);
      else if (arg is UInt64)
         bytes = BitConverter.GetBytes((UInt64) arg);
      else
         return null;

      for (int ctr = bytes.Length - 1; ctr >= 0; ctr--)
         output += String.Format("{0:X2} ", bytes[ctr]);   

      return output.Trim();
   }
}

다음 예제에서는 ByteByByteFormatter 클래스를 사용하여 정수 값의 형식을 지정합니다. ICustomFormatter.Format 메서드는 두 번째 String.Format(IFormatProvider, String, Object[]) 메서드 호출에서 두 번 이상 호출되고 NumberFormatInfo 메서드가 "N0" 형식 문자열을 인식하지 못하고 null 참조(Visual Basic의 경우 ByteByByteFormatter.Format)를 반환하기 때문에 세 번째 메서드 호출에서는 기본 Nothing 공급자가 사용됩니다.

public class Example
{
   public static void Main()
   {
      long value = 3210662321; 
      byte value1 = 214;
      byte value2 = 19;

      Console.WriteLine(String.Format(new ByteByByteFormatter(), "{0:X}", value));
      Console.WriteLine(String.Format(new ByteByByteFormatter(), "{0:X} And {1:X} = {2:X} ({2:000})", 
                                      value1, value2, value1 & value2));                                
      Console.WriteLine(String.Format(new ByteByByteFormatter(), "{0,10:N0}", value));
   }
}
// The example displays the following output:
//       00 00 00 00 BF 5E D1 B1
//       00 D6 And 00 13 = 00 12 (018)
//       3,210,662,321

맨 위로 이동

제목

정의

표준 숫자 형식 문자열

숫자 값의 일반적으로 사용되는 문자열 표현을 만드는 표준 형식 문자열에 대해 설명합니다.

사용자 지정 숫자 형식 문자열

숫자 값의 응용 프로그램별 형식을 만드는 사용자 지정 형식 문자열에 대해 설명합니다.

표준 날짜 및 시간 형식 문자열

DateTime 값의 일반적으로 사용되는 문자열 표현을 만드는 표준 형식 문자열에 대해 설명합니다.

사용자 지정 날짜 및 시간 형식 문자열

DateTime 값의 응용 프로그램별 형식을 만드는 사용자 지정 형식 문자열에 대해 설명합니다.

표준 TimeSpan 서식 문자열

시간 간격의 일반적으로 사용되는 문자열 표현을 만드는 표준 형식 문자열에 대해 설명합니다.

사용자 지정 TimeSpan 서식 문자열

시간 간격의 응용 프로그램별 형식을 만드는 사용자 지정 형식 문자열에 대해 설명합니다.

열거형 형식 문자열

열거형 값의 문자열 표현을 만드는 데 사용되는 표준 형식 문자열에 대해 설명합니다.

복합 형식 지정

문자열에 형식이 지정된 하나 이상의 값을 포함시키는 방법에 대해 설명합니다. 그런 후 해당 문자열을 콘솔에 표시하거나 스트림에 쓸 수 있습니다.

서식 지정 작업 수행

특정 형식 지정 작업을 수행하기 위한 단계별 지침을 제공하는 항목을 나열합니다.

.NET Framework에서 문자열 구문 분석

개체를 해당 개체의 문자열 표현으로 표시되는 값으로 초기화하는 방법에 대해 설명합니다. 구문 분석은 형식 지정의 역순으로 진행됩니다.

맨 위로 이동

표시: