Skip to main content
이 항목에서는 Game Chat 2의 C++ API를 사용하여 게임에 음성 및 텍스트 통신을 추가하는 방법에 대한 간단한 안내를 제공합니다.

사전 요구 사항

Game Chat 2는 프로젝트가 GDK용으로 설정되어 있어야 합니다. 설정 방법에 대한 자세한 내용은 Microsoft Game Development Kit 시작하기를 참조하세요. Game Chat 2를 컴파일하려면 기본 GameChat2.h 헤더를 포함해야 합니다. 제대로 링크하려면 프로젝트에 하나 이상의 컴파일 단위에 GameChat2Impl.h도 포함해야 합니다(이러한 스텁 함수 구현은 작고 컴파일러가 “인라인”으로 생성하기 쉬우므로 공통 미리 컴파일된 헤더를 권장합니다). Game Chat 2 인터페이스는 프로젝트가 C++/CX와 전통적인 C++ 중 어느 것으로 컴파일할지 선택하도록 요구하지 않습니다. 둘 다 사용할 수 있습니다. 또한 구현은 치명적이지 않은 오류 보고 수단으로 예외를 던지지 않습니다. 원한다면 예외 없는 프로젝트에서 쉽게 사용할 수 있습니다. 그러나 구현은 치명적인 오류 보고 수단으로 예외를 던집니다. (자세한 내용은 이 항목 뒷부분의 실패 모델 섹션을 참조하세요.)

초기화

싱글턴 초기화의 수명에 적용되는 매개변수로 Game Chat 2 싱글턴 인스턴스를 초기화하여 라이브러리와의 상호 작용을 시작합니다. 다음과 같이 chat_manager::initialize를 호출하여 싱글턴 인스턴스를 초기화합니다.
RegisterAppStateChangeNotification을 통해 일시 중단 및 재개 이벤트에 대해 등록해야 합니다. 일시 중단 시 chat_manager::cleanup()으로 Game Chat 2를 정리해야 합니다. 재개 시 Game Chat 2를 다시 초기화해야 합니다. 일시 중단/재개 주기에 걸쳐 사용하려고 하면 크래시가 발생할 수 있습니다.

사용자 구성

Microsoft Game Development Kit(GDK) 타이틀에 사용자 추가

Game Chat 2 인스턴스에 사용자를 추가하기 전에 사용자가 GDK 타이틀에 추가되었는지 확인하세요. 이는 XUserAddAsync API를 사용하여 수행됩니다. 이 API 사용에 대한 자세한 내용은 사용자 ID 및 XUser를 참조하세요. Game Chat 2에 추가하려는 사용자에 대한 XUserHandle을 얻은 후에는 XUserGetId API를 사용하여 사용자의 XBOX 사용자 ID(XUID)를 가져와야 합니다. 사용자가 온라인 상태여야 하며 이 단계에 대한 사용자의 동의가 필요합니다. XUserGetId는 XUID를 uint64_t로 제공합니다. Game Chat 2에서 사용하려면 XUID를 std::wstring으로 변환해야 합니다. 다음은 XUserHandle을 얻은 후 Game Chat 2에 사용자를 추가하는 방법을 보여주는 코드 예제입니다.
XUserResolveIssueWithUiAsync를 호출하면 시스템 대화 상자가 표시됨을 유의하세요.

Game Chat 2에 사용자 추가

인스턴스가 초기화된 후 chat_manager::add_local_user를 사용하여 Game Chat 2 인스턴스에 로컬 사용자를 추가해야 합니다. 이 예제에서 사용자 A는 로컬 사용자를 나타냅니다.
다음으로, 원격 사용자와 사용자가 있는 원격 “엔드포인트”를 나타내는 식별자를 추가합니다. 엔드포인트는 원격 장치에서 실행 중인 앱의 인스턴스입니다. 이 예에서 사용자 B는 엔드포인트 X에 있습니다. 사용자 C 및 D는 엔드포인트 Y에 있습니다. 엔드포인트 X에는 임의로 식별자 “1”이 할당됩니다. 엔드포인트 Y에는 임의로 식별자 “2”가 할당됩니다. 다음 호출을 사용하여 Game Chat 2에 원격 사용자를 알립니다.
다음으로, 각 원격 사용자와 로컬 사용자 간의 통신 관계를 구성합니다. 이 예에서 사용자 A와 사용자 B가 같은 팀에 있다고 가정합니다. 양방향 통신이 허용됩니다. c_communicationRelationshipSendAndReceiveAll은 양방향 통신을 나타내기 위해 GameChat2.h에 정의된 상수입니다. chat_user_local::set_communication_relationship을 사용하여 사용자 A와 사용자 B의 관계를 설정합니다.
사용자 C와 D가 “관중”이며 사용자 A의 말을 들을 수 있지만 말할 수는 없어야 한다고 가정합니다. c_communicationRelationshipSendAll은 이 단방향 통신을 나타내기 위해 GameChat2.h에 정의된 상수입니다. 다음과 같이 관계를 설정합니다.
4명의 로컬 사용자 모두의 관계 설정 예제는 이 항목 뒷부분의 시나리오 섹션을 참조하세요. 싱글턴 인스턴스에 추가되었지만 로컬 사용자와 통신하도록 구성되지 않은 원격 사용자가 어느 시점에서든 있는 경우 - 괜찮습니다. 이는 사용자가 팀을 결정 중이거나 임의로 발언 채널을 변경할 수 있는 시나리오에서 예상할 수 있습니다. Game Chat 2는 인스턴스에 추가된 사용자에 대한 정보(예: 개인정보 관계 및 평판)만 캐시하므로 특정 시점에 로컬 사용자와 말할 수 없더라도 가능한 모든 사용자를 Game Chat 2에 알리는 것이 유용합니다. 마지막으로 사용자 D가 게임을 떠났고 로컬 Game Chat 2 인스턴스에서 제거해야 한다고 가정합니다. 이는 다음과 같이 chat_manager::remove_user를 사용하여 수행할 수 있습니다.
chat_manager::remove_user()를 호출하면 사용자 개체가 무효화될 수 있습니다. 실시간 오디오 조작을 사용하는 경우 자세한 내용은 채팅 사용자 수명을 참조하세요. 그렇지 않으면 chat_manager::remove_user()가 호출되면 사용자 개체가 즉시 무효화됩니다. 사용자를 제거할 수 있는 시점에 대한 미묘한 제한 사항은 이 항목 뒷부분의 상태 변경 처리 섹션에 자세히 설명되어 있습니다.

데이터 프레임 처리

Game Chat 2에는 자체 전송 계층이 없습니다. 앱에서 제공해야 합니다. 이 플러그인은 chat_manager::start_processing_data_frames()chat_manager::finish_processing_data_frames() 메서드 쌍에 대한 앱의 정기적이고 빈번한 호출로 관리됩니다. 이 메서드는 Game Chat 2가 앱에 발신 데이터를 제공하는 방식입니다. 이러한 메서드는 빠르게 작동하도록 설계되었습니다. 전용 네트워킹 스레드에서 자주 폴링될 수 있습니다. 이는 네트워크 타이밍의 예측 불가능성이나 다중 스레드 콜백 복잡성을 걱정하지 않고 대기 중인 모든 데이터를 검색할 수 있는 편리한 장소를 제공합니다. chat_manager::start_processing_data_frames()가 호출되면 모든 대기 중인 데이터가 game_chat_data_frame 구조체 포인터 배열로 보고됩니다. 앱은 배열을 반복하고, 대상 엔드포인트를 검사하고, 앱의 네트워킹 계층을 사용하여 적절한 원격 앱 인스턴스에 데이터를 전달해야 합니다. 배열이 모든 game_chat_data_frame 구조체로 완료된 후, 리소스를 해제하기 위해 chat_manager:finish_processing_data_frames()를 호출하여 배열을 Game Chat 2로 다시 전달해야 합니다. 다음 예제에 표시되어 있습니다.
데이터 프레임이 자주 처리될수록 사용자에게 나타나는 오디오 지연 시간이 낮아집니다. 오디오는 40ms 데이터 프레임으로 결합됩니다. 이것이 권장되는 폴링 기간입니다.

상태 변경 처리

Game Chat 2는 chat_manager::start_processing_state_changes()chat_manager::finish_processing_state_changes() 메서드 쌍에 대한 앱의 정기적이고 빈번한 호출을 통해 수신된 텍스트 메시지와 같은 업데이트를 앱에 제공합니다. 이 메서드는 빠르게 작동하므로 UI 렌더링 루프의 모든 그래픽 프레임에서 호출할 수 있습니다. 이는 네트워크 타이밍의 예측 불가능성이나 다중 스레드 콜백 복잡성을 걱정하지 않고 대기 중인 모든 변경 사항을 검색할 수 있는 편리한 장소를 제공합니다. chat_manager::start_processing_state_changes()가 호출되면 대기 중인 모든 업데이트가 game_chat_state_change 구조체 포인터 배열로 보고됩니다. 앱은 배열을 반복하고, 기본 구조체에서 더 구체적인 유형을 검사하고, 기본 구조체를 해당하는 더 자세한 유형으로 캐스트한 다음, 해당 업데이트를 적절하게 처리해야 합니다. 배열이 현재 사용 가능한 모든 game_chat_state_change 개체로 완료된 후, 리소스를 해제하기 위해 chat_manager::finish_processing_state_changes()를 호출하여 배열을 Game Chat 2로 다시 전달해야 합니다. 다음 예제에 표시되어 있습니다.
chat_manager::remove_user()가 사용자 개체와 관련된 메모리를 즉시 무효화하고, 상태 변경에 사용자 개체에 대한 포인터가 포함될 수 있으므로 상태 변경을 처리하는 동안에는 chat_manager::remove_user()를 호출해서는 안 됩니다.

텍스트 채팅

텍스트 채팅을 보내려면 chat_user::chat_user_local::send_chat_text()를 사용합니다. 다음 예제에 표시되어 있습니다.
Game Chat 2는 이 메시지를 포함하는 데이터 프레임을 생성합니다. 데이터 프레임의 대상 엔드포인트는 로컬 사용자로부터 텍스트를 수신하도록 구성된 사용자와 관련된 엔드포인트입니다. 데이터가 원격 엔드포인트에서 처리되면 메시지가 game_chat_text_chat_received_state_change를 통해 노출됩니다. 음성 채팅과 마찬가지로 텍스트 채팅에도 권한 및 개인정보 제한이 적용됩니다. 한 쌍의 사용자가 텍스트 채팅을 허용하도록 구성되었지만 권한 또는 개인정보 제한으로 인해 해당 통신이 허용되지 않는 경우 텍스트 메시지가 삭제됩니다.

접근성

접근성에는 텍스트 채팅 입력 및 표시 지원이 필요합니다. 물리적 키보드 사용이 널리 보급되지 않았던 플랫폼이나 게임 장르에서도 사용자가 텍스트 음성 변환 보조 기술을 사용하도록 시스템을 구성할 수 있으므로 텍스트 입력이 필요합니다. 마찬가지로 사용자가 시스템을 사용하여 음성 텍스트 변환을 구성할 수 있으므로 텍스트 표시가 필요합니다. 이러한 기본 설정은 각각 chat_user::chat_user_local::text_to_speech_conversion_preference_enabled()chat_user::chat_user_local::speech_to_text_conversion_preference_enabled() 메서드를 호출하여 로컬 사용자에서 감지할 수 있습니다. 사용자 기본 설정에 따라 조건부로 텍스트를 활성화하는 것이 좋습니다.

텍스트 음성 변환

사용자가 텍스트 음성 변환을 활성화한 경우 chat_user::chat_user_local::text_to_speech_conversion_preference_enabled()true를 반환합니다. 이 상태가 감지되면 앱은 텍스트 입력 방법을 제공해야 합니다. 실제 또는 가상 키보드로 텍스트 입력을 받은 후 문자열을 chat_user::chat_user_local::synthesize_text_to_speech() 메서드에 전달합니다. Game Chat 2는 문자열과 사용자의 접근성 음성 기본 설정을 기반으로 오디오 데이터를 감지하고 합성합니다. 다음 예제에 표시되어 있습니다.
이 작업의 일부로 합성된 오디오는 이 로컬 사용자로부터 오디오를 수신하도록 구성된 모든 사용자에게 전송됩니다. 텍스트 음성 변환이 활성화되지 않은 사용자에서 chat_user::chat_user_local::synthesize_text_to_speech()가 호출되면 Game Chat 2는 아무 작업도 수행하지 않습니다.

음성 텍스트 변환

사용자가 음성 텍스트 변환을 활성화한 경우 chat_user::chat_user_local::speech_to_text_conversion_preference_enabled()true를 반환합니다. 이 상태가 감지되면 앱은 전사된 채팅 메시지와 관련된 UI를 제공할 준비가 되어 있어야 합니다. Game Chat 2는 각 원격 사용자의 오디오를 자동으로 전사하고 game_chat_transcribed_chat_received_state_change 구조체를 통해 노출합니다.

음성 텍스트 변환 성능 고려 사항

음성 텍스트 변환이 활성화되면 각 원격 장치의 Game Chat 2 인스턴스는 음성 서비스 엔드포인트와 WebSocket 연결을 시작합니다. 각 원격 Game Chat 2 클라이언트는 이 WebSocket을 통해 음성 서비스 엔드포인트에 오디오를 업로드합니다. 음성 서비스 엔드포인트는 때때로 원격 장치에 전사 메시지를 반환합니다. 그런 다음 원격 장치는 전사 메시지(즉, 텍스트 메시지)를 로컬 장치로 보냅니다. 전사된 메시지는 Game Chat 2가 앱에 제공하여 렌더링합니다. 따라서 음성 텍스트 변환의 주요 성능 비용은 네트워크 사용량입니다. 대부분의 네트워크 트래픽은 인코딩된 오디오의 업로드입니다. WebSocket은 “일반” 음성 채팅 경로에서 Game Chat 2에 의해 이미 인코딩된 오디오를 업로드합니다. 앱은 chat_manager::set_audio_encoding_bitrate를 통해 비트레이트를 제어할 수 있습니다.

UI

특히 스코어보드와 같은 게이머태그 목록에서 사용자에게 UI가 표시되는 곳이면 어디에서나 사용자에 대한 피드백으로 음소거/발언 아이콘도 표시하는 것이 좋습니다. 이는 chat_user::chat_indicator()를 호출하여 해당 사용자의 채팅에 대한 현재 즉각적인 상태를 나타내는 game_chat_user_chat_indicator 열거형을 검색함으로써 수행됩니다. 다음 예제는 chatUserA 변수가 가리키는 chat_user 개체에 대한 표시기 값을 검색하여 iconToShow 변수에 할당할 특정 아이콘 상수 값을 결정하는 방법을 보여줍니다.
chat_user::chat_indicator()에서 보고된 값은 예를 들어 플레이어가 말하기 시작하고 중지할 때와 같이 자주 변경될 것으로 예상됩니다. 결과적으로 앱이 UI 프레임마다 폴링하는 것을 지원하도록 설계되었습니다.

음소거

chat_user::chat_user_local::set_microphone_muted() 메서드를 사용하여 로컬 사용자 마이크의 음소거 상태를 전환할 수 있습니다. 마이크가 음소거되면 해당 마이크의 오디오가 캡처되지 않습니다. 사용자가 Kinect와 같은 공유 장치를 사용 중인 경우 음소거 상태는 모든 사용자에게 적용됩니다. chat_user::chat_user_local::microphone_muted() 메서드를 사용하여 로컬 사용자 마이크의 음소거 상태를 검색할 수 있습니다. 이 메서드는 chat_user::chat_user_local::set_microphone_muted() 호출을 통해 소프트웨어에서 로컬 사용자의 마이크가 음소거되었는지 여부만 반영합니다. 이 메서드는 예를 들어 사용자 헤드셋의 버튼을 통해 하드웨어로 제어되는 음소거는 반영하지 않습니다. Game Chat 2를 통해 사용자 오디오 장치의 하드웨어 음소거 상태를 검색하는 방법은 없습니다. chat_user::chat_user_local::set_remote_user_muted() 메서드를 사용하여 특정 로컬 사용자와 관련된 원격 사용자의 음소거 상태를 전환할 수 있습니다. 원격 사용자가 음소거되면 로컬 사용자는 원격 사용자로부터 어떤 오디오도 듣지 않으며 어떤 텍스트 메시지도 받지 않습니다.

나쁜 평판 자동 음소거

일반적으로 원격 사용자는 음소거되지 않은 상태로 시작됩니다. Game Chat 2는 다음의 경우 사용자를 음소거 상태로 시작합니다:
  1. 원격 사용자가 로컬 사용자의 친구가 아닙니다.
  2. 원격 사용자에게 나쁜 평판 플래그가 있습니다.
이 작업으로 인해 사용자가 음소거되면 chat_user::chat_indicator()game_chat_user_chat_indicator::reputation_restricted를 반환합니다. 이 상태는 원격 사용자를 대상 사용자로 포함하는 chat_user::chat_user_local::set_remote_user_muted()에 대한 첫 번째 호출로 재정의됩니다.

권한 및 개인정보 보호

게임에 의해 구성된 통신 관계 외에도 Game Chat 2는 권한 및 개인정보 제한을 시행합니다. Game Chat 2는 사용자가 처음 추가될 때 권한 및 개인정보 제한 조회를 수행합니다. 해당 작업이 완료될 때까지 사용자의 chat_user::chat_indicator()는 항상 game_chat_user_chat_indicator::silent를 반환합니다. 사용자와의 통신이 권한 또는 개인정보 제한에 영향을 받는 경우 사용자의 chat_user::chat_indicator()game_chat_user_chat_indicator::platform_restricted를 반환합니다. 플랫폼 통신 제한은 음성 및 텍스트 채팅 모두에 적용됩니다. 텍스트 채팅이 플랫폼 제한으로 차단되었지만 음성 채팅은 그렇지 않은 경우, 또는 그 반대의 경우는 결코 없습니다. chat_user::chat_user_local::get_effective_communication_relationship()을 사용하여 완료되지 않은 권한 및 개인정보 작업으로 인해 사용자가 통신할 수 없는 경우를 구별하는 데 도움을 얻을 수 있습니다. 이는 game_chat_communication_relationship_flags 형태로 Game Chat 2에 의해 시행되는 통신 관계를 반환하며, 관계가 game_chat_communication_relationship_adjuster 열거형 형태로 구성된 관계와 다를 수 있는 이유입니다. 예를 들어, 조회 작업이 아직 진행 중인 경우 game_chat_communication_relationship_adjustergame_chat_communication_relationship_adjuster::initializing이 됩니다. 이 메서드는 UI에 영향을 미치는 데 사용해서는 안 됩니다. (자세한 내용은 이 항목의 앞부분에 있는 UI 섹션을 참조하세요.) Game Chat 2에서 권한 문제가 발생하면 communication_relationship_adjuster_changed 상태 변경으로 보고됩니다. 복구할 수 없는 이유로 Game Chat 2가 사용자의 권한을 검색하지 못하면 game_chat_communication_relationship_adjuster::privilege_check_failure 조정자로 보고됩니다. 사용자가 해결할 수 있는 이유로 Game Chat 2가 사용자의 권한을 검색하지 못하면 game_chat_communication_relationship_adjuster::resolve_user_issue 조정자로 보고됩니다. UI로 해결할 수 있는 권한이 사용자에게 없는 경우 game_chat_communication_relationship_adjuster::privilege 조정자로 보고됩니다. 이러한 경우 통신이 제한됩니다. 다음은 사용자에게 다음과 같은 일반적인 문제 중 하나가 있는지 확인하는 방법의 예입니다.
  1. Game Chat 2가 권한을 확인하려면 사용자가 XBOX 서비스에 동의해야 합니다.
  2. 사용자 계정이 권한을 거부하도록 구성되어 있습니다(예: 자녀 계정이므로 채팅을 사용할 수 없음).
game_chat_communication_relationship_adjuster::privilege 조정자로 보고된 문제의 경우 XUserPrivilegeOptions::NoneXUserPrivilege::Communications와 함께 XUserResolvePrivilegeWithUiAsync를 호출하여 문제 해결을 시도할 수 있습니다. game_chat_communication_relationship_adjuster::resolve_user_issue 조정자로 보고된 문제의 경우 URL에 nullptr을 사용하여 XUserResolveIssueWithUiAsync를 호출하여 문제 해결을 시도할 수 있습니다. 권한 문제가 있음을 나타내는 UI를 표시하는 것이 좋습니다. 사용자가 버튼 누르기 또는 메뉴 옵션을 통해 문제 해결을 시도할지 결정할 수 있도록 허용하세요. 사용자가 문제를 해결할 수 없거나 원하지 않을 수 있습니다. 사용자가 문제를 해결하면 다음에 사용자가 Game Chat 2에 추가될 때 적용됩니다.
chat_manager::remove_user()는 상태 변경을 처리하는 동안(즉, chat_manager::start_processing_state_changes()가 호출된 후 해당하는 chat_manager::finish_processing_state_changes() 호출 이전) 호출되어서는 안 됩니다. 상태 변경이 처리되는 동안 chat_manager::remove_user()를 호출하면 제거된 사용자와 관련된 메모리가 무효화될 수 있습니다. game_chat_communication_relationship_adjuster::privilege 조정자가 표시되고 사용자 권한을 해결하려는 경우 상태 변경 처리 후까지 기다렸다가 시도해야 합니다.
XUserResolvePrivilegeWithUiAsync를 호출하는 데 필요한 XUID에서 XUserHandle을 가져오려면 XUserFindUserById API를 사용하여 새 XUserHandle을 가져올 수 있습니다. 또는 XUserAddAsync로 획득한 것을 보유하고 어떤 XUID가 이에 매핑되는지 추적할 수 있습니다. 다음은 이러한 문제를 해결하는 방법의 예입니다.

정리

앱이 더 이상 Game Chat 2를 통한 통신이 필요하지 않으면 chat_manager::cleanup()을 호출해야 합니다. 이렇게 하면 Game Chat 2가 통신 관리에 할당된 리소스를 회수할 수 있습니다.

실패 모델

Game Chat 2 구현은 치명적이지 않은 오류 보고 수단으로 예외를 던지지 않습니다. 원한다면 예외 없는 프로젝트에서 쉽게 사용할 수 있습니다. 그러나 Game Chat 2는 치명적인 오류를 알리기 위해 예외를 던집니다. 이러한 오류는 인스턴스를 초기화하기 전에 Game Chat 인스턴스에 사용자를 추가하거나 Game Chat 2 인스턴스에서 제거된 후 사용자 개체에 액세스하는 등과 같은 API 오용의 결과입니다. 이러한 오류는 개발 초기에 잡힐 것으로 예상되며 Game Chat 2와 상호 작용하는 데 사용되는 패턴을 수정하여 수정할 수 있습니다. 이러한 오류가 발생하면 예외가 발생하기 전에 오류의 원인에 대한 힌트가 디버거에 출력됩니다.

인기 있는 시나리오를 구성하는 방법

Push-to-talk

Push-to-talk는 chat_user::chat_user_local::set_microphone_muted()로 구현해야 합니다. 말하기를 허용하려면 set_microphone_muted(false)를 호출하고 제한하려면 set_microphone_muted(true)를 호출합니다. 이 메서드는 Game Chat 2로부터 가장 낮은 지연 시간의 응답을 제공합니다.

사용자 A와 사용자 B가 블루 팀에 있고 사용자 C와 사용자 D가 레드 팀에 있다고 가정합니다. 각 사용자는 앱의 고유한 인스턴스에 있습니다. 사용자 A의 장치에서:
사용자 B의 장치에서:
사용자 C의 장치에서:
사용자 D의 장치에서:

브로드캐스트

사용자 A가 명령을 내리는 리더라고 가정합니다. 사용자 B, C 및 D는 듣기만 할 수 있습니다. 각 플레이어는 고유한 장치에 있습니다. 사용자 A의 장치에서:
사용자 B의 장치에서:
사용자 C의 장치에서:
사용자 D의 장치에서:

참조 API 문서

참고 항목

Game Chat 2 소개 실시간 오디오 조작 API 콘텐츠(GameChat2) Microsoft Game Development Kit
마지막 수정일 2026년 8월 25일