Share via


소스 코드 개요(CNG 예제)

업데이트: 2008년 7월

이 개요에서는 CNG(Cryptography Next Generation) 보안 통신 예제에 있는 다양한 코드 요소 간의 상호 작용에 대해 자세히 설명합니다.

예제의 다음과 같은 측면에 대해 설명합니다.

  • 응용 프로그램

  • 파일

  • 클래스

  • 보안 버전

  • 세션 개요

  • 암호화 키(버전 2-5)

  • 공개 채널을 통해 교환되는 디지털 서명(버전 3)

  • 개인 채널을 통해 교환되는 디지털 서명(버전 4)

  • 세션 종료(버전 5)

  • 참고 사항

  • CNG 예제의 제한 사항

응용 프로그램

이 예제는 Alice, Bob 및 Mallory라는 서로 구분되는 세 가지 콘솔 응용 프로그램으로 구성되어 있습니다. 각 응용 프로그램은 별도의 Visual Studio 프로젝트로 빌드되며 주 파일과 세 개의 공유 파일로 구성됩니다. 다음 표에서는 각 응용 프로그램과 해당 파일을 보여 줍니다.

응용 프로그램(프로젝트) 이름

파일

Alice

  • Alice.cs(주 파일)

  • Utilities.cs

  • ChannelManager.cs

  • Communicator.cs

Bob

  • Bob.cs(주 파일)

  • Utilities.cs

  • ChannelManager.cs

  • Communicator.cs

Mallory

  • Mallory.cs(주 파일)

  • Utilities.cs

  • ChannelManager.cs

  • Communicator.cs

파일

다음 단원의 표에서는 각 응용 프로그램에서 사용하는 클래스와 메서드를 소스 코드에 나타나는 순서에 따라 요약하여 보여 줍니다.

Alice.cs, Bob.cs 및 Mallory.cs

클래스, 메서드 또는

전역 변수 이름

용도

CNG_SecureCommunicationExample

프로젝트 수준 partial 클래스입니다.

MyColor

OtherColor

fDisplaySendMessage

전역 변수입니다.

Main

각 응용 프로그램의 프로그램 진입점입니다. 이 메서드는 다음 작업을 처리합니다.

  • Alice에서 호출한 경우 Bob.exe 및 Mallory.exe를 자동으로 로드합니다.

  • 처리 루프를 만듭니다.

  • InitConsole 메서드를 호출하여 콘솔 크기, 위치 및 제목을 설정합니다.

  • Run 메서드를 호출합니다.

Run

InitializeOptions 메서드를 호출하고 선택된 보안 시나리오를 만드는 메서드입니다.

Utilities.cs

클래스, 메서드 또는

전역 변수 이름

용도

CNG_SecureCommunicationExample

프로젝트 수준 partial 클래스입니다.

Version

fVerbose

fMallory

전역 변수입니다.

Autoloader

Alice에서 Bob.exe 및 Mallory.exe 응용 프로그램을 로드하기 위해 호출하는 메서드입니다.

InitConsole

사용자 인터페이스 메뉴 및 응용 프로그램 수준 메시지를 처리하는 메서드입니다.

SplashScreen

콘솔 창 제목을 제공하는 메서드입니다.

ReadALine

콘솔에서 사용자가 입력한 줄을 읽는 유틸리티 메서드입니다.

ReadAChar

질문을 표시하고 사용자가 예 또는 아니요로 대답하게 하는 유틸리티 메서드입니다.

InitializeOptions

여러 옵션을 표시하고 사용자가 선택하게 하는 메서드입니다. 또한 이 메서드는 Version, fVerbose 및 fMallory 전역 플래그를 설정합니다.

Display(string s)

두 Display 메서드 중 첫 번째입니다. 이 메서드는 문자열과 MyColor 변수를 두 번째 Display 메서드에 전달합니다.

Display(string DisplayString, int color)

두 Display 메서드 중 두 번째입니다. 이 메서드는 Console.WriteLine 문을 래핑하고 출력 줄에 색을 지정할 수 있게 합니다.

이러한 클래스, 메서드 및 변수에 대한 자세한 내용은 유틸리티 클래스의 코드 분석(CNG 예제)을 참조하십시오.

ChannelManager.cs

클래스, 메서드 또는

전역 변수 이름

용도

CNG_SecureCommunicationExample

프로젝트 수준 partial 클래스입니다.

AppControl

내부 응용 프로그램을 제어하고 세 콘솔 응용 프로그램을 동기화하는 메서드입니다.

Alice에서는 이 메서드를 사용하여 프로그램 옵션(Version 및 fVerbose 플래그)을 Bob과 Mallory에 전송합니다.

AppControl은 메시징 메서드가 아닙니다. 해당 내용은 암호화되거나 서명되지 않으며 Communicator 클래스는 호출되지 않습니다.

SendChannelName

ReceiveChannelName

PublicChannel 명명된 파이프에서 AliceAndBobChannel 및 AliceAndBobChannel1 명명된 파이프로 전환하는 데 사용되는 메서드입니다. 이러한 메서드를 통해 CNG 예제 개요에서 설명하는 보안 문제를 의도적으로 발생시킬 수 있습니다.

ChannelManager

응용 프로그램의 프로세스 간 통신 프레임워크를 제공하는 클래스입니다.

이러한 클래스 및 메서드에 대한 자세한 내용은 ChannelManager 클래스의 코드 분석(CNG 예제)을 참조하십시오.

Communicator.cs

클래스, 메서드 또는

전역 변수 이름

용도

CNG_SecureCommunicationExample

프로젝트 수준 partial 클래스입니다.

Communicator

모든 암호화 기능을 캡슐화하는 클래스입니다. 이 클래스는 Alice, Bob 및 Mallory 간의 모든 메시지를 처리합니다. ChannelManagerAppControl 메서드에서 전송하는 메시지는 처리하지 않습니다.

m_DSKey

m_ECDH_Cng

m_ECDH_local_publicKey_XML

m_ECDH_remote_publicKey

ChMgr

클래스 변수입니다.

Communicator

Communicator 개체를 생성하는 메서드입니다.

Dispose

전용으로 보유된 리소스를 해제하는 메서드입니다.

StoreDSKey

디지털 서명 키를 저장하는 메서드입니다.

Send_or_Receive_PublicCryptoKey

키 교환을 지원하는 메서드입니다.

iv

ciphertext

signature

일반 텍스트 메시지를 암호화하는 데 사용되는 전용 클래스 변수입니다. 이러한 변수는 ReceiveMessage() 메서드 근처에 선언되어 있습니다.

ReceiveMessage

보안 버전에 따라 일반 텍스트 또는 암호화된 메시지를 받는 메서드입니다.

SendMessage

일반 텍스트를 받아들이고 보안 버전에 따라 일반 텍스트 또는 암호화된 형식으로 전송하는 메서드입니다.

이러한 클래스, 메서드 및 변수에 대한 자세한 내용은 Communicator 클래스의 코드 분석(CNG 예제)을 참조하십시오.

클래스

각 프로젝트에는 세 개의 클래스가 들어 있습니다.

  • public partial class CNG_SecureCommunicationExample

    이 클래스는 Alice, Bob 및 Mallory 응용 프로그램에 포함된 네 개의 프로젝트 파일 모두에 걸쳐 있습니다. 컴파일 후 CNG_SecureCommunicationExample 클래스에는 프로젝트 파일 네 개의 클래스, 변수 및 메서드가 모두 들어 있습니다. partial 클래스에 대한 자세한 내용은 Partial 클래스 및 메서드(C# 프로그래밍 가이드)를 참조하십시오.

  • internal sealed class ChannelManager

    이 클래스는 명명된 파이프를 지원합니다. 각 프로젝트는 프로그램 실행 도중 서로 다른 시점에 몇 개의 ChannelManager 인스턴스를 만듭니다. 이 클래스에 대한 자세한 내용은 ChannelManager 클래스의 코드 분석(CNG 예제)을 참조하십시오.

  • internal sealed class Communicator

    이 클래스는 암호화 및 암호 해독을 지원합니다. 각 프로젝트는 프로그램 실행 도중 서로 다른 시점에 몇 개의 Communicator 인스턴스를 만듭니다. 이 클래스에 대한 자세한 내용은 Communicator 클래스의 코드 분석(CNG 예제)을 참조하십시오.

보안 버전

소스 코드는 CNG 예제 개요에서 설명하는 보안 시나리오를 지원합니다. IM(인스턴트 메시징) 도구의 다섯 가지 보안 수준을 나타내는 다음과 같은 다섯 가지 버전이 구현됩니다.

  • 버전 1: 일반 텍스트 메시지와 명명된 파이프 사용

  • 버전 2: 암호화된 메시지 사용

  • 버전 3: 암호화된 메시지와 디지털 서명 사용

  • 버전 4: 암호화된 메시지와 개인 디지털 서명 사용

  • 버전 5: 보안 오류가 발생할 경우 응용 프로그램 종료

참고:

이 항목의 나머지 부분에서는 이러한 버전을 번호에 따라 호칭합니다. 또한 "Alice", "Bob" 및 "Mallory"라는 이름은 문맥에 따라 예제 시나리오에 관련된 세 명의 사람을 나타낼 수도 있고 세 개의 Visual Studio 응용 프로그램을 나타낼 수도 있습니다.

세션 개요

Alice, Bob 및 Mallory에는 각각 Main 메서드와 Run 메서드가 있습니다.

Main 메서드는 응용 프로그램을 동기화하고 다음 기능을 수행합니다.

  • 시작 화면을 표시합니다.

  • 사용자가 세션 옵션을 선택하게 합니다(Alice에만 해당).

  • 세션 옵션을 Bob과 Mallory에 전송합니다(Alice에만 해당).

  • Alice에서 보내는 세션 옵션을 받습니다(Bob 및 Mallory에만 해당).

  • Run 메서드를 호출하여 요청된 보안 세션을 수행합니다.

Run 메서드에서 보안 시나리오를 실행합니다.

  • 각 세션은 이전 단원에 나열된 버전 중 하나를 보여 줍니다.

  • Alice, Bob 및 Mallory가 Run 메서드에 진입하면 세션이 시작되고 Main 메서드로 돌아오면 세션이 끝납니다.

  • Alice, Bob 및 Mallory는 세션 도중 항상 같은 버전을 실행합니다.

  • Alice는 세션 도중 발생하는 모든 트랜잭션을 시작합니다. Mallory는 Alice에 응답하고 Bob과 트랜잭션을 시작합니다. Bob은 응답만 수행합니다.

Alice와 Bob의 소스 코드는 매우 비슷합니다. 주요 차이점은 Alice는 각 세션을 시작하고 파이프 서버 역할을 하는 반면 Bob은 파이프 클라이언트 역할을 한다는 것입니다. Mallory는 별도의 두 파이프(Alice와의 파이프 및 Bob과의 파이프)를 관리하므로 코드가 더 복잡합니다.

Main 메서드

Alice는 Main 메서드가 시작될 때 InitializeOptions 메서드를 호출하고 사용자에게서 세션 옵션(Version, fVerbose, fMallory)을 입력받습니다. 그런 다음 AppControl 메서드를 사용하여 옵션을 Bob 및 Mallory에 전송합니다. Bob 및 Mallory는 자신의 AppControl 메서드를 사용하여 옵션을 받습니다. 사용자가 응용 프로그램을 종료하기 위해 "x"를 입력하면 Alice의 AppControl 메서드에서 Bob 및 Mallory에 세션 옵션 대신 "exit"라는 문자열을 전송합니다.

세 응용 프로그램은 세션 옵션을 받은 후 Run 메서드를 호출합니다.

Run 메서드

Alice, Bob 및 Mallory는 다음 단계를 수행하여 요청된 세션을 수행합니다.

  1. Alice는 PublicChannel이라는 채널을 사용하는 SendChannelName 메서드를 호출합니다. 그런 다음 Bob에 새 채널 이름(AliceAndBobChannel)을 전송합니다.

  2. fMallory 플래그가 true로 설정되어 있으면 Mallory는 PublicChannel을 수신 대기하고 Alice가 보내는 새 채널 이름(AliceAndBobChannel)을 가로챕니다. 그런 다음 Bob에 다른 채널 이름(AliceAndBobChannel1)을 전송합니다.

  3. Alice와 Bob은 자신의 이름을 사용하여 Communicator 개체를 만듭니다. 이러한 개체는 C# using 명령문 내에서 만들어지고 Run 메서드의 끝 부분에서 삭제됩니다.

    Alice는 파이프 서버로 초기화됩니다.

    using (Communicator Alice = new Communicator("server", NewChannelName))
    

    Bob은 파이프 클라이언트로 초기화됩니다.

    using (Communicator Bob = new Communicator("client", NewChannelName))
    

    Mallory는 두 Communicator 개체인 MalloryAlice 및 MalloryBob을 만듭니다. Mallory는 Alice에 대해 파이프 클라이언트로 초기화됩니다.

    using (Communicator MalloryAlice = new Communicator("client", AliceChannelName))
    

    Mallory는 Bob에 대해 파이프 서버로 초기화됩니다.

    using (Communicator MalloryBob = new Communicator("server", BobChannelName"))
    
  4. Communicator 클래스 생성자는 채널 이름을 받아 ChMgr이라는 장기 public ChannelManager 개체를 만듭니다.

    ChMgr = new ChannelManager(mode, ChannelName);
    
  5. ChannelManager 생성자는 채널 이름을 받아 명명된 해당 파이프를 만듭니다.

    참고:

    이 시점에서 Alice와 Mallory는 AliceAndBobChannel이라는 파이프를 통해 통신하고 있으며 Mallory와 Bob은 AliceAndBobChannel1이라는 파이프를 통해 통신하고 있습니다.

    AliceAndBobChannel 및 AliceAndBobChannel1은 장기 채널이므로 보안 시나리오가 끝날 때까지(Run 메서드가 끝날 때까지) 열려 있습니다.

  6. 보안 버전을 제어하는 fVersion 플래그 및 Mallory의 개입 여부를 제어하는 fMallory 플래그의 값에 따라 다음 동작이 결정됩니다.

    버전 3의 경우 Alice는 PublicChannel을 통해 Bob에 디지털 서명 키를 전송합니다. 이 디지털 서명 키를 사용하여 키와 메시지에 서명합니다. fMallory가 true이면 Mallory가 디지털 서명 키를 가로채서 Alice와 Bob에 전송하는 키와 메시지에 서명하는 데 사용합니다.

    버전 4 및 5의 경우 Alice는 Bob에 두 개의 디지털 서명 키를 전송합니다. 디지털 서명 키 1은 Alice가 버전 3에서 보내는 키와 같으며, 디지털 서명 키 2는 Mallory가 알 수 없는 비밀 디지털 서명 키입니다.

  7. 버전 2-5의 경우 Alice와 Bob은 공개 암호화 키를 교환합니다. fMallory가 true이면 Mallory가 공개 키를 가로채서 자신의 키로 바꿉니다.

  8. Alice와 Bob이 메시지를 교환합니다. fMallory가 true이면 Mallory가 Alice와 Bob의 메시지를 가로채서 변경하고 다시 전송합니다.

  9. Alice와 Bob의 통신이 끝나면 사용자가 직접 메시지를 입력하여 전송할 수 있습니다. 이를 통해 메시지가 암호화되는 방식 및 Mallory가 메시지를 변경하는 방법을 확인할 수 있습니다. 입력을 마친 후 Enter 키를 눌러 제어를 다시 Alice로 전달합니다.

  10. Alice가 세션을 종료합니다. Alice, Bob 및 Mallory의 Run 메서드가 해당 Main 메서드로 제어를 반환하고 예제가 다시 시작됩니다.

암호화 키(버전 2-5)

버전 2-5에서는 AES(Advanced Encryption Standard) 알고리즘을 사용하여 메시지를 암호화합니다. 암호화 키 교환은 Alice, Bob 및 Mallory의 Run 메서드에서 다음 코드 명령문 뒤에 구현되어 있습니다.

if (2 <= Version)

암호화 키는 Communicator 클래스 생성자에서 만든 장기 public ChannelManager 개체(ChMgr)에 의해 전송됩니다.

다음 두 코드 명령문은 암호화 키를 Alice가 보내고 Bob이 받는 방법을 보여 줍니다.

Alice.Send_or_Receive_PublicCryptoKey("send", MyColor);
Bob.Send_or_Receive_PublicCryptoKey("receive", OtherColor);

두 번째 매개 변수는 수신하는 응용 프로그램에서 암호화 키의 내용을 표시할 때 사용할 색을 정의합니다.

AES 구현은 수학적으로는 약점이 없는 것으로 간주되지만 중간자 개입 공격에 대해서는 보호되지 않습니다. AES에서 강력한 암호화를 제공하는 데도 Mallory가 Alice와 Bob의 메시지를 해독할 수 있다는 것은 모순처럼 생각될 수 있지만, 이는 Alice와 Bob이 공유하는 비밀 계약을 Mallory가 가지고 있기 때문에 가능합니다. Mallory는 키를 가로채고 대체하는 방법으로 강력한 AES 암호화를 무력화합니다.

인증 없이 암호화 키를 사용하면 보안과 관련된 착각이 발생할 수 있습니다. Alice와 Bob은 버전 2를 사용할 때 메시지가 안전하게 전송되는 것으로 생각할 수 있지만, 사실은 첫 번째 메시지를 보내기도 전에 이미 보안이 손상된 것입니다.

Alice와 Bob의 회사에서는 공격이 비롯된 위치가 회사 내부인지 아니면 외부인지 알 수 없습니다. 따라서 공격의 출처를 확인하기 위해 IM 도구 버전 3을 설계했습니다.

공개 채널을 통한 디지털 서명 교환(버전 3)

버전 3에서는 디지털 서명으로 키와 메시지에 서명하여 버전 2의 보안 결함을 수정하려고 합니다. 디지털 서명 키 교환은 Alice, Bob 및 Mallory의 Run 메서드에서 다음 코드 명령문 뒤에 구현되어 있습니다.

if (3 <= Version)

디지털 서명 키는 암호화 키와 같은 장기 공개 채널을 통해 전송됩니다. 디지털 서명 키를 전송하는 코드는 다음과 같습니다.

Alice.ChMgr.SendMessage(dsKeyBlob);
참고:

디지털 서명 키를 전송하는 ChannelManager 인스턴스(ChMgr)는 Alice Communicator 개체의 멤버입니다.

Alice와 Bob은 디지털 서명 키를 Communicator 개체의 private 멤버로 저장합니다.

Alice.StoreDSKey(DSKey);
Bob.StoreDSKey(DSKey);

그러나 Mallory는 PublicChannel에서 디지털 서명을 손쉽게 복사하여 저장할 수 있습니다.

Mallory.StoreDSKey(DSKey);

Alice와 Bob이 서로의 서명된 메시지를 받을 때는 디지털 서명이 메시지와 완벽하게 일치합니다. 이는 Mallory가 Alice와 Bob이 사용하는 디지털 서명 키를 그대로 사용하여 메시지에 서명했기 때문입니다.

버전 3에서는 회사 네트워크를 통해 공개 채널로 암호화 키와 디지털 서명을 모두 교환합니다. 따라서 Alice와 Bob이 근무하는 회사에서는 회사 내부 인물이 해커일 것으로 의심합니다. 이 아이디어를 테스트하기 위해 버전 4를 만들었습니다.

개인 채널을 통한 디지털 서명 교환(버전 4)

버전 4에서는 두 개의 디지털 서명 키(버전 3에서 사용된 키 및 개인 채널을 통해 전송되는 두 번째 비밀 키)를 사용합니다. 첫 번째 키는 이제 해커를 잡기 위한 가짜 디지털 키로 사용됩니다. Alice와 Bob은 두 번째 키를 사용하여 암호화 키와 메시지에 디지털 서명합니다.

Alice와 Bob에게만 IM 소프트웨어 버전 4가 주어지고 Mallory는 버전 3을 계속 사용합니다. 따라서 Mallory는 자신이 사용하는 디지털 서명이 잘못되었다는 사실을 알 수 없습니다. 따라서 Alice와 Bob의 IM 도구는 수신되는 모든 키와 메시지에 대해 보안 경고를 표시합니다.

버전 4에서는 누군가가 암호화 키와 메시지를 모두 가로챘다는 사실도 보여 줍니다. 이를 통해 중간자 개입 공격이 발생하고 있으며 암호화 키가 전송되기도 전에 공격이 시작되었다는 점을 알 수 있습니다. 따라서 회사의 PublicChannel에 액세스할 수 있는 회사 직원이 Bob보다 먼저 로그온한 것입니다. 비밀 디지털 서명 키를 통해 Mallory의 해킹이 발각되었습니다.

비밀 디지털 서명 키 전송은 Alice와 Bob의 Run 메서드에서 다음 코드 명령문 뒤에 구현되어 있습니다.

if (4 <= Version)

다음 코드 명령문에서는 Alice와 Bob의 private ChannelManager 인스턴스를 만듭니다.

ChannelManager ChMgr2 = new ChannelManager("server", "PrivateChannel")
ChannelManager ChMgr2 = new ChannelManager("client", "PrivateChannel")

Alice와 Bob이 사용하는 개인 채널(ChMgr2)은 Communicator 개체의 멤버가 아닙니다. 다음 두 코드 명령문을 비교하면 이를 확인할 수 있습니다.

Alice.ChMgr.SendMessage(dsKeyBlob); // Public channel - fake key
ChMgr2.SendMessage(dsKeyBlob);      // Private channel - real key

첫 번째 명령문에서는 Run 메서드가 시작될 때 만들어진 장기 ChannelManager 인스턴스(ChMgr)를 사용합니다. 이 인스턴스는 세션이 끝날 때까지 Alice, Bob 및 Mallory의 Communicator 개체에 public 멤버로 보유됩니다. 세션 개요 단원의 3단계를 참조하십시오. 두 번째 명령문에서는 키를 주고받을 동안만 유지되는 임시 개체를 사용합니다. 이 개체는 사용 후 즉시 삭제됩니다.

Alice가 비밀 디지털 서명 키를 전송하면 Bob은 다음 명령문을 사용하여 키를 받습니다.

DSKey = ChMgr2.ReadMessage();

Alice와 Bob은 키를 Communicator 개체의 private 멤버로 저장합니다.

Alice.StoreDSKey(DSKey);
Bob.StoreDSKey(DSKey);

또한 이 명령문은 가짜 디지털 서명 키를 덮어씁니다.

버전 4에서 Alice와 Bob은 가짜 디지털 서명 키 대신 비밀 디지털 서명 키를 사용하여 키와 메시지에 서명합니다. 또한 버전 4에서는 메시지의 디지털 서명이 메시지와 일치하지 않을 때마다 암호화 키에 서명하고 보안 경고를 표시합니다.

세션 종료(버전 5)

버전 5는 버전 4와 동일하지만 오류가 처음 발생할 때 세션을 종료한다는 점이 다릅니다. Alice가 첫 번째 오류를 경험하는 시점은 Bob의 공개 암호화 키를 받아 잘못된 디지털 서명을 발견할 때입니다. Bob이 첫 번째 오류를 경험하는 시점도 Alice의 공개 암호화 키를 받아 잘못된 디지털 서명을 발견할 때입니다.

참고 사항

  • 개체 삭제: C# using 명령문은 강화된 보안을 제공합니다. 이 명령문을 사용하여 모든 ChannelManager 및 Communicator 개체를 묶습니다. 이러한 개체가 범위를 벗어나면 해당 Dispose 메서드가 즉시 호출되고 내부 보유 리소스가 모두 해제됩니다.

  • 인코딩 메서드: 암호화된 데이터를 전송할 때는 항상 ASCII가 아닌 UTF8 또는 Unicode로 인코딩해야 합니다.

CNG 예제의 제한 사항

CNG 보안 통신 예제의 목적은 관리되는 CNG 기능을 보여 주는 것입니다. 따라서 다음을 비롯한 특정 기능이 생략되었습니다.

  • 모든 메서드의 매개 변수 유효성 검사

  • 광범위한 try/catch 블록 사용

  • 강력한 파이프 연결 해제 검색

  • 화면 출력을 파일로 로깅

  • 암호화 알고리즘을 동적으로 구성

  • 디지털 서명 알고리즘을 동적으로 구성

  • 디지털 서명 키를 Bob에게 전송하는 다른 방법. 명명된 파이프인 PrivateChannel은 단순한 솔루션이지만 더 복잡한 다른 방법도 있습니다.

  • 키 유지, 저장 및 검색

  • 운영 체제에서 생성한 디지털 서명 키 사용

  • PKI(공개 키 인프라)에서 제공하는 키 사용

이러한 기능을 사용하면 코드가 복잡해지며 이 예제의 범위를 벗어나게 됩니다.

참고 항목

개념

CNG(Cryptography Next Generation) 보안 통신 예제

단계별 키 및 메시지 교환(CNG 예제)

예상 출력(CNG 예제)

변경 기록

날짜

변경 내용

이유

2008년 7월

항목이 추가되었습니다.

향상된 기능 관련 정보