클래식 콘솔 API 및 가상 터미널 시퀀스

클래식 Windows 콘솔 API가상 터미널 시퀀스로 바꾸는 것이 좋습니다. 이 문서에서는 둘의 차이점을 간략하게 설명하고 권장 사항의 이유를 알아봅니다.

정의

클래식 Windows 콘솔 API 표면은 이름에 "콘솔"을 사용하여 kernel32.dll에 일련의 C 언어 기능 인터페이스로 정의됩니다.

가상 터미널 시퀀스는 표준 입력 및 표준 출력 스트림에 포함된 명령 언어로 정의됩니다. 가상 터미널 시퀀스는 인쇄할 수 없는 이스케이프 문자를 사용하여 인쇄 가능한 일반 텍스트로 인터리브된 명령에 신호를 보냅니다.

기록

Windows 콘솔은 클라이언트 명령줄 애플리케이션에서 출력 표시 버퍼와 사용자 입력 버퍼를 모두 조작할 수 있는 광범위한 API 표면을 제공합니다. 그러나 다른 비 Windows 플랫폼은 명령줄 환경에 이 특정 API 기반 접근 방식을 적용한 적이 없으며, 표준 입력 및 표준 출력 스트림에 포함된 가상 터미널 시퀀스를 대신 사용하도록 선택합니다. (한동안 Microsoft는 DOS 및 Windows 초기 버전에서 ANSI.SYS라는 드라이버를 통해 이 동작을 지원했습니다.)

반면 가상 터미널 시퀀스(다양한 언어)는 다른 플랫폼에 대한 명령줄 환경 작업을 구동합니다. 이러한 시퀀스의 뿌리는 ECMA 표준 그리고 Digital Equipment Corporation 및 Tektronix 터미널부터 xterm 같은 좀 더 일반적인 최신 소프트웨어 터미널까지 여러 공급업체에서 제공하는 일련의 확장입니다. 가상 터미널 시퀀스 도메인 내에 많은 확장이 있고 일부 시퀀스는 다른 시퀀스보다 광범위하게 지원되지만, 하위 집합이 잘 알려진 명령줄 환경의 명령 언어가 거의 모든 터미널과 명령줄 클라이언트 애플리케이션에서 지원되므로 전 세계가 이를 기반으로 표준화했다고 생각하는 것이 안전합니다.

플랫폼 간 지원

가상 터미널 시퀀스는 모든 플랫폼에서 기본적으로 지원되므로, Windows를 제외한 운영 체제 버전과 변형 간에 터미널 애플리케이션 및 명령줄 유틸리티를 쉽게 이식할 수 있습니다.

반면 Windows 콘솔 API는 Windows에서만 지원됩니다. 한 플랫폼에서 다른 플랫폼으로 명령줄 유틸리티를 이식하려고 할 때 Windows와 가상 터미널 간에 방대한 어댑터 또는 변환 라이브러리를 작성해야 합니다.

원격 액세스

가상 터미널 시퀀스는 원격 액세스에서 큰 장점이 있습니다. 표준 원격 명령줄 연결을 설정하는 데 필요한 작업 외에는 추가 전송 작업 또는 원격 프로시저 호출을 수행할 필요가 없습니다. 파이프, 소켓, 파일, 직렬 포트 또는 다른 디바이스를 통해 아웃바운드와 인바운드 전송 채널(또는 단일 양방향 채널)을 연결하기만 하면 이러한 시퀀스와 통신하는 애플리케이션에 필요한 모든 정보가 원격 호스트에 온전히 전달됩니다.

반면 Windows 콘솔 API는 로컬 머신에서만 액세스할 수 있으며, 이러한 API에 원격으로 연결하려면 간단한 채널 외에도 전체 원격 호출 및 전송 인터페이스 계층을 빌드해야 합니다.

문제의 분리

일부 Windows 콘솔 API는 입력 및 출력 버퍼 또는 대화형 명령줄의 편리한 기능에 대한 낮은 수준의 액세스를 제공합니다. 여기에는 명령줄 클라이언트 애플리케이션 자체 내부가 아닌 콘솔 하위 시스템 및 호스트 환경 내에서 프로그래밍된 별칭 및 명령 기록이 포함될 수 있습니다.

반면 다른 플랫폼은 애플리케이션의 현재 상태 메모리 및 편리한 기능을 명령줄 유틸리티 또는 셸 자체의 책임으로 만듭니다.

콘솔 호스트와 API에서 이러한 책임을 처리하는 Windows 콘솔의 작업 방식 덕분에 이러한 기능을 사용하여 명령줄 애플리케이션을 더 빠르고 쉽게 작성할 수 있으며, 그리기 상태를 기억하거나 편의성 기능을 편집할 필요가 없습니다. 그러나 이렇게 하면 구현 및 가용성의 변동으로 인해 모든 플랫폼, 버전 또는 시나리오에서 이러한 작업을 원격으로 연결하는 것이 거의 불가능합니다. 이와 같은 책임 처리 방법 때문에 이러한 Windows 명령줄 애플리케이션의 최종 대화형 환경은 콘솔 호스트의 구현, 우선 순위 및 릴리스 주기에 완전히 종속됩니다.

예를 들어 구문 강조 표시 및 복합 선택과 같은 고급 줄 편집 기능은 명령줄 애플리케이션이 편집 관련 문제를 스스로 처리하는 경우에만 사용 가능합니다. 콘솔은 클라이언트 애플리케이션처럼 광범위한 방법으로 이러한 시나리오를 완전히 이해할 수 있는 충분한 컨텍스트를 절대로 가질 수 없습니다.

반면 다른 플랫폼은 가상 터미널 시퀀스를 사용하여 readlinencurses 같은 재사용 가능한 클라이언트 쪽 라이브러리를 통해 이러한 작업과 가상 터미널 통신 자체를 처리합니다. 최종 터미널은 양방향 통신 채널을 통해 정보를 표시하고 입력을 받는 역할만 합니다.

잘못된 방향 동사

Windows 콘솔을 사용하면 입력 및 출력 스트림에서 일부 작업을 반대 방향으로 수행할 수 있습니다. 이렇게 하면 Windows 명령줄 애플리케이션에서 자체 버퍼를 관리할 필요가 없습니다. 또한 Windows 명령줄 앱은 사용자 대신 입력을 시뮬레이션/삽입하거나 작성된 내용의 일부 기록을 다시 읽는 등의 고급 작업을 수행할 수 있습니다.

이렇게 하면 단일 머신의 특정 사용자 컨텍스트에서 작동하는 Windows 애플리케이션의 성능이 향상될 뿐 아니라, 특정 시나리오에서 사용할 경우 보안 및 권한 수준 또는 도메인 간에 벡터가 제공됩니다. 이러한 시나리오로는 동일한 머신의 컨텍스트 간에 작동하거나 다른 머신 또는 환경의 컨텍스트에서 작동하는 것이 포함됩니다.

가상 터미널 시퀀스를 사용하는 다른 플랫폼은 이 작업을 허용하지 않습니다. 클래식 Windows 콘솔에서 가상 터미널 시퀀스로 전환할 것을 권장하는 이유는 이 전략과 융합하여 상호 운용성과 보안을 강화하는 것입니다.

직접 창 액세스

Windows 콘솔 API 표면은 호스트 창에 대한 정확한 창 핸들을 제공합니다. 이를 통해 명령줄 유틸리티는 창 핸들에 허용되는 Win32 API의 광범위한 영역에 도달하여 고급 창 작업을 수행할 수 있습니다. 이러한 Win32 API는 창 상태, 프레임, 아이콘 또는 창에 대한 기타 속성을 조작할 수 있습니다.

반면 가상 터미널 시퀀스를 사용하는 다른 플랫폼에는 창에 대해 수행할 수 있는 약간의 명령 세트가 있습니다. 이러한 명령은 창 크기 또는 표시된 제목을 변경하는 등의 작업을 수행할 수 있지만, 스트림의 나머지 부분과 동일한 밴드에서 동일한 컨트롤 하에 수행해야 합니다.

Windows가 발전하면서 창 핸들에 대한 보안 컨트롤과 제한이 증가했습니다. 또한 특정 사용자 인터페이스 요소의 애플리케이션 주소 지정 가능 창 핸들 특성과 존재 양식이 발전했으며, 특히 디바이스 폼 팩터와 플랫폼 지원이 증가했습니다. 이로 인해 플랫폼과 환경이 발전함에 따라 명령줄 애플리케이션에 대한 직접 창 액세스가 취약해집니다.

Unicode

UTF-8은 이식성, 스토리지 크기 및 처리 시간 간에 적절한 균형을 유지하기 때문에 거의 모든 최신 플랫폼에서 유니코드 데이터에 허용되는 인코딩입니다. 그러나 과거에 Windows는 유니코드 데이터의 기본 인코딩으로 UTF-16을 선택했습니다. UTF-8에 대한 지원이 Windows에서 증가하고 있으며 이러한 유니코드 형식을 사용해도 다른 인코딩을 사용할 수 있습니다.

Windows 콘솔 플랫폼은 기존의 모든 코드 페이지와 인코딩을 지원해 왔으며 앞으로도 계속 지원할 것입니다. 모든 Windows 버전에서 최대 호환성을 제공할 수 있도록 UTF-16을 사용하고, 필요한 경우 UTF-8로 알고리즘 변환을 수행하세요. 콘솔 시스템에서 UTF-8 지원을 추가하기 위한 작업이 진행 중입니다.

콘솔의 UTF-16 지원은 추가 구성 없이 모든 콘솔 API의 W 변형을 통해 사용할 수 있으며, 다른 Microsoft 및 Windows 플랫폼 기능과 제품의 wchar_tW 변형과 통신하여 이미 UTF-16에 대해 잘 알고 있는 애플리케이션에서 선택할 가능성이 높습니다.

콘솔의 UTF-8 지원은 SetConsoleOutputCPSetConsoleCP 메서드를 사용하여 코드 페이지를 65001 또는 CP_UTF8로 설정한 후 콘솔 API의 A 변형을 통해 콘솔 핸들에 활용할 수 있습니다. 머신 내 제어판의 지역 섹션에서, 유니코드가 아닌 애플리케이션에 대한 설정에서 "Use Unicode UTF-8 for worldwide language support(전 세계 언어 지원에 유니코드 UTF-8 사용)"을 선택하지 않은 경우에만 코드 페이지를 미리 설정해야 합니다.

참고 항목

현재 UTF-8은 표준 출력 스트림에서 WriteConsoleWriteFile 메서드를 통해 완벽하게 지원됩니다. 입력 스트림에 대한 지원은 입력 모드에 따라 다르며 지속적으로 개선될 것입니다. 특히 입력의 기본 "가공" 모드는 아직 UTF-8을 완벽하게 지원하지 않습니다. 이 작업의 현재 상태는 GitHub의 microsoft/terminal#7777에서 찾을 수 있습니다. 해결 방법은 알고리즘 방식으로 변환 가능한 UTF-16을 사용하여 ReadConsoleW 또는 ReadConsoleInputW를 통해 문제가 해결될 때까지 입력을 읽는 것입니다.

권장 사항

Windows에서 현재 진행 중인 개발과 모든 신규 개발에서 터미널과 상호 작용하는 방식으로 가상 터미널 시퀀스를 사용하는 것이 좋습니다. 그러면 Windows 명령줄 클라이언트 애플리케이션이 다른 모든 플랫폼에서 애플리케이션 프로그래밍 스타일과 융합됩니다.

Windows 콘솔 API 사용의 예외

초기 환경을 설정하려면 여전히 제한된 Windows 콘솔 API 하위 세트가 필요합니다. Windows 플랫폼의 프로세스, 신호, 디바이스 및 인코딩 처리 방법은 여전히 다른 플랫폼과 다릅니다.

향후 계획 및 pseudoconsole

플랫폼에서 Windows 콘솔 API를 제거할 계획은 없습니다.

반면, Windows 콘솔 호스트는 기존 Windows 명령줄 애플리케이션 호출을 가상 터미널 시퀀스로 변환하여 다른 호스팅 환경에 원격으로 또는 여러 플랫폼에 전달하는 pseudoconsole 기술을 제공합니다.

이 변환은 완벽하지 않습니다. 콘솔 호스트 창은 Windows에서 사용자에게 표시했어야 하는 내용의 시뮬레이션된 환경을 유지해야 합니다. 그런 다음, 이 시뮬레이션된 환경의 복제본을 pseudoconsole 호스트에 프로젝션합니다. 모든 Windows 콘솔 API 호출은 기존 명령줄 클라이언트 애플리케이션의 요구 사항을 충족하기 위해 시뮬레이션된 환경 내에서 작동합니다. 그 효과만 최종 호스트로 전파됩니다.

따라서 모든 플랫폼에서 완벽하게 호환되고 모든 새 기능과 시나리오를 Windows와 기타 플랫폼에서 완벽하게 지원하는 명령줄 애플리케이션을 만들려면 가상 터미널 시퀀스로 전환하고 모든 플랫폼에 맞도록 명령줄 애플리케이션의 아키텍처를 조정하는 것이 좋습니다.

명령줄 애플리케이션의 이 Windows 전환에 대한 자세한 내용은 에코시스템 로드맵에서 찾을 수 있습니다.