Roblox는 TextChatService를 통해 플레이어 간의 실시간 세션에서 텍스트 기반 메시징을 제공합니다. 이 클래스는 전체 채팅 시스템 관리, 채팅 메시지 필터링, 모더레이션 및 사용자 권한 관리를 책임지는 싱글톤 클래스입니다. 이 서비스는 기본 기능을 제공하며 사용자 정의 요구사항을 기반으로 메시지를 전달하고, 특정 사용자에게 특별 권한이나 모더레이션을 추가하고, 특정 작업을 실행하는 사용자 정의 명령을 생성하는 등 채팅을 확장하고 사용자 정의할 수 있는 메소드와 이벤트 집합도 제공합니다.
UI 구성
TextChatService는 게임의 필요에 맞게 사용자 정의할 수 있는 기본 UI를 제공합니다. 관련 UI 요소를 숨기려면 이 구성 요소들을 비활성화하십시오. 원한다면 이러한 UI 요소를 사용자 정의 인터페이스로 교체할 수도 있습니다:
채널, 메시지 및 명령
TextChannel — 텍스트 채널은 사용자가 보낸 메시지를 클라이언트에서 서버로 전달하며, 서버는 이를 기반으로 다른 사용자에게 메시지를 표시합니다. 텍스트 채널은 기능을 수행하기 위해 TextChatService에 부모로 설정되어야 합니다.
TextSource — TextChannel 내의 사용자입니다. 텍스트 소스는 AddUserAsync()가 호출될 때 TextChannel에 바로 부모로 설정됩니다. 텍스트 소스는 채널 내 사용자의 메시지 전송 능력과 같은 세부 권한을 포함합니다. 단일 사용자가 여러 텍스트 채널에 있는 경우, 여러 텍스트 소스와 연결됩니다.
TextChatMessage — 텍스트 채널의 메시지입니다. 채팅 메시지는 메시지 발신자, 원래 메시지, 필터링된 메시지, 생성 타임스탬프와 같은 기본 정보를 포함합니다.
TextChatCommand — 사용자가 PrimaryAlias 또는 SecondaryAlias 속성과 일치하는 메시지를 보내 특정 작업이나 행동을 호출할 수 있게 해줍니다. 채팅 명령은 기능을 수행하기 위해 TextChatService에 부모로 설정되어야 합니다.
채팅 흐름도
텍스트 채팅은 클라이언트‑서버 모델을 사용하며, 전송 클라이언트, 서버, 및 수신 클라이언트로 구성됩니다.

플레이어가 로컬 장치에서 메시지를 보내기 시작하면 TextChannel:SendAsync() 메소드가 트리거됩니다. 이 메소드는 메시지를 처리하고 해당 메시지가 채팅 명령인지 일반 채팅 메시지인지 판단합니다.
메시지가 채팅 명령인 경우, 정의된 작업을 수행하기 위해 TextChatCommand.Triggered 이벤트를 발생시킵니다. 그 이후 단계는 필요하지 않습니다.
메시지가 일반 채팅 메시지인 경우, 발신 클라이언트에서 발신자를 표시하기 위해 TextChatService.SendingMessage 이벤트가 발생합니다. 동시에 TextChannel:SendAsync()는 메시지를 서버로 전달합니다.
서버는 TextChannel.ShouldDeliverCallback을 발생시켜 사용자 권한 및 Roblox 커뮤니티 필터링 요구 사항을 바탕으로 메시지를 다른 플레이어에게 전달할지 결정합니다.
만약 TextChannel.ShouldDeliverCallback이 메시지가 다른 플레이어에게 전달될 자격이 있다고 판단하면, 서버는 필터를 적용하고 TextChannel.OnIncomingMessage를 두 번 발생시킵니다:
첫 번째는 발신 클라이언트에서 발생하며, TextChatService.MessageReceived 이벤트를 통해 서버가 메시지를 처리하고 있다는 신호입니다. 이 이벤트는 발신 클라이언트에서 로컬 메시지를 서버의 처리된 메시지로 교체합니다. 원래 메시지가 필터링을 필요로 하지 않았다면 메시지는 동일합니다.
두 번째는 수신 클라이언트에서 발생하며, TextChatService.MessageReceived 이벤트가 트리거되어 다른 플레이어에게 메시지를 표시합니다.
텍스트 채팅 후크 및 콜백
TextChatService API는 채팅 메시지의 외관과 배달을 명확하게 분리하는 것을 장려합니다. 텍스트 채팅 시스템의 여러 인스턴스는 중앙 집중식, 명확한 위치에서 포맷을 설정할 수 있는 후크와 콜백을 제공합니다.

메시지 조건부 전달
TextChannel.ShouldDeliverCallback 콜백은 서버에서만 정의되어야 합니다. 메시지가 전송될 때, 텍스트 채널의 각 TextSource 자식에 대해 이 콜백이 발생하여 메시지를 전달해야 하는지를 결정합니다. 이 콜백은 추가 게임 플레이 맥락에 따라 커스텀 메시지 전달 로직을 구현하는 데 사용될 수 있습니다:
- 사용자들이 가까운 거리의 사람에게만 메시지를 보낼 수 있는 근접 기반 채팅.
- 특정 속성을 가진 사용자가 다른 사용자에게 메시지를 보내는 것을 방지.
메시지 표시 사용자 정의
기본 TextChatService UI는 리치 텍스트를 사용하여 메시지 표시 방식을 포맷하고 사용자 정의합니다. 다음 콜백을 사용하여 메시지가 사용자에게 표시되기 전에 포맷할 수 있습니다. 예를 들어 사용자 이름에 색상을 추가하거나 채팅 태그를 사용하는 것입니다.
다음 콜백은 모든 TextChatMessage가 표시되기 전 호출되어 TextChannel, TextSource, 또는 TextChatMessage 내용에 따라 채팅 창 외관을 사용자 정의할 수 있습니다. 클라이언트가 메시지를 보내면, 이 콜백은 메시지가 서버로 전송될 때 한 번 호출되며, 그 때 TextChatMessage.Status 값은 Enum.TextChatMessageStatus.Sending이 됩니다. 메시지가 서버에서 수신되고 다른 사용자에게 전달되고 있을 때, 발신 클라이언트는 수정된 Enum.TextChatMessageStatus 값을 가진 메ッ세지를 다시 받게 됩니다.
- TextChatService.OnIncomingMessage — 이 콜백은 클라이언트에서만 정의되어야 합니다. 메시지를 수신하면 발생하며, 서버에서 수신되었거나 로컬 클라이언트가 방금 메시지를 보낸 경우입니다. 이 콜백은 모든 TextChannel 인스턴스에서 수신된 모든 TextChatMessage에 대해 호출되며, 사용자가 메시지를 표시하기 전에 가장 먼저 메시지를 처리합니다.
- TextChannel.OnIncomingMessage — 이 콜백은 클라이언트에서만 정의되어야 합니다. 서버에서 메시지를 수신하면 발생합니다. 이 콜백은 TextChannel에서 수신된 모든 TextChatMessage에 대해 호출됩니다. 기본 TextChannel 인스턴스는 TextChatService.CreateDefaultTextChannels에서 생성되며 이 콜백이 정의되어 있으며 덮어 쓸 수 있습니다.
- TextChatService.OnBubbleAdded — 이 콜백은 클라이언트에서만 정의되어야 합니다. 채팅 창 UI의 메시지 외관과 독립적으로 채팅 버블의 외관을 사용자 정의하는 데 사용됩니다.
- TextChatService.OnChatWindowAdded — 이 콜백은 클라이언트에서만 정의되어야 합니다. 채팅 버블의 메시지 외관과 독립적으로 채팅 창 UI의 메시지 외관을 사용자 정의하는 데 사용됩니다.
레거시 채팅에서 마이그레이션
이 섹션은 TextChatService를 사용하여 일반 채팅 기능 및 행동을 구현하기 위한 대체 방법을 제공함으로써 레거시 채팅 시스템에서 마이그레이션하는 데 도움을 줍니다.
탐색기 창에서 TextChatService를 선택합니다.
속성 창에서 ChatVersion 드롭다운을 찾아 TextChatService를 선택합니다.

기본 기능
두 시스템 모두 동일한 기본 채팅 기능을 공유하지만, 일반적으로 TextChatService 구현은 더 지속 가능하고 반복하기 쉽습니다.
| 기능 | 레거시 채팅 | TextChatService | 차이점 |
|---|---|---|---|
| 채팅 메시지 전송 | Players:Chat() | TextChannel:SendAsync() | SendAsync() 메소드는 리치 텍스트 포맷팅 및 메시지 우선 순위와 같은 보다 고급 채팅 기능을 지원합니다. 또한 부적절한 메시지가 전송되는 것을 방지하기 위한 내장 필터링도 포함되어 있습니다. |
| 메시지 콜백 구현 | Chat:InvokeChatCallback() Chat:RegisterChatCallback() | TextChatService.SendingMessage TextChatService.OnIncomingMessage | 레거시 채팅 시스템은 메시지를 전달하기 위해 채팅 시스템 이벤트에 함수를 바인딩합니다. TextChatService의 두 메소드는 더 나은 유연성과 사용자 정의를 제공합니다. |
| 사용자 정의 채팅 명령 추가 | ChatService/ChatCommand 모듈 | TextChatCommand | TextChatService는 레거시 채팅 모듈을 사용하는 대신 텍스트 명령을 위한 전용 클래스를 가지고 있습니다. |
| 시스템 메시지 표시 | StarterGui:SetCore()을 사용하여 ChatMakeSystemMessage | TextChannel:DisplaySystemMessage() | TextChannel.OnIncomingMessage 콜백은 메시지 외관을 사용자 정의하기 위해 TextChatMessageProperties 인스턴스를 반환할 수 있습니다. |
| 채팅 비활성화 | 경험 설정에서 Studio와 ChatWindow/ChatSettings 모듈로 채팅 창 숨기기 | ChatWindowConfiguration.Enabled |
메시지 필터링
TextChatService는 각 플레이어의 계정 정보를 기반으로 채팅 메시지를 자동으로 필터링하므로 모든 종류의 채팅 메시지에 대해 수동으로 텍스트 필터링을 구현할 필요가 없습니다.
| 기능 | 레거시 채팅 | TextChatService |
|---|---|---|
| 개별 플레이어의 채팅 메시지 필터링 | Chat:FilterStringAsync() | 자동화됨 |
| 방송 메시지 필터링 | Chat:FilterStringForBroadcast() | 자동화됨 |
윈도우 및 버블 채팅
TextChatService의 채팅 창 및 버블 채팅 동작과 사용자 정의 옵션은 레거시 채팅 시스템과 동일합니다. 레거시 채팅 시스템은 채팅 모듈 또는 Players 컨테이너를 사용한 사용자 정의만 허용되기 때문에, 이 서비스는 모든 채팅 창 및 버블 채팅 속성을 관리하는 전용 클래스(ChatWindowConfiguration 및 BubbleChatConfiguration)를 제공합니다. 또한, 스크립팅하지 않고도 Studio 설정을 사용하여 블록 채팅 외관과 동작 속성을 쉽게 조정하고 미리보기할 수 있습니다.
스피커 "추가 데이터" 마이그레이션
레거시 Lua 채팅 시스템은 개발자가 Speaker 클래스에서 SetExtraData를 사용할 수 있도록 하였습니다. 이 데이터는 형식화된 이름 색상, 채팅 색상 또는 특정 발신자에 대한 이름 태그를 지정하는 데 사용되었습니다.
레거시 채팅 시스템 SetExtraData
-- 레거시 채팅 시스템에서 스피커에 추가 데이터를 설정하는 예제
ChatService.SpeakerAdded:Connect(function(playerName)
local speaker = ChatService:GetSpeaker(playerName)
speaker:SetExtraData("NameColor", Color3.fromRGB(255, 255, 55))
speaker:SetExtraData("ChatColor", Color3.fromRGB(212, 175, 55))
speaker:SetExtraData("Tags", {{TagText = "YourTagName", TagColor = Color3.fromRGB(0, 255, 0)}, {TagText = "OtherTagName", TagColor = Color3.fromRGB(255, 0, 0)}})
end)
TextChatService는 SetExtraData에 대한 직접적인 대응이 없습니다. 대신 메시지의 TextSource를 기반으로 리치 텍스트를 사용하여 메시지의 외관을 사용자 정의하기 위해 콜백과 같은 OnWindowAdded를 사용하십시오.
레거시 Lua 채팅의 "추가 데이터"를 모방하는 예는 Player 객체의 속성에 액세스하는 것입니다:
TextChatService SetAttributes
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
player:SetAttribute("NameColor", Color3.fromRGB(255, 255, 55))
player:SetAttribute("ChatColor", Color3.fromRGB(212, 175, 55))
player:SetAttribute("isYourTag", true)
player:SetAttribute("isOtherTag", true)
end)
그런 다음 플레이어에 설정된 속성에 따라 채팅 창의 외관을 사용자 정의하기 위해 OnChatWindowAdded 콜백을 사용할 수 있습니다:
TextChatService OnChatWindowAdded
local TextChatService = game:GetService("TextChatService")
local Players = game:GetService("Players")
TextChatService.OnChatWindowAdded = function(textChatMessage)
local textSource = textChatMessage.TextSource
if textSource then
local player = Players:GetPlayerByUserId(textSource.UserId)
if player then
local overrideProperties = TextChatService.ChatWindowConfiguration:DeriveNewMessageProperties()
overrideProperties.PrefixText = textChatMessage.PrefixText
overrideProperties.Text = textChatMessage.Text
local nameColor = player:GetAttribute("NameColor")
if nameColor and typeof(nameColor) == "Color3" then
overrideProperties.PrefixTextProperties.TextColor3 = nameColor
end
local chatColor = player:GetAttribute("ChatColor")
if chatColor and typeof(chatColor) == "Color3" then
overrideProperties.TextColor3 = chatColor
end
local isYourTag = player:GetAttribute("isYourTag")
if isYourTag == true then
overrideProperties.PrefixText = `<font color='rgb(0, 255, 0)'>[YourTag]</font> {overrideProperties.PrefixText}`
end
local isOtherTag = player:GetAttribute("isOtherTag")
if isOtherTag == true then
overrideProperties.PrefixText = `<font color='rgb(255, 0, 0)'>[OtherTag]</font> {overrideProperties.PrefixText}`
end
return overrideProperties
end
end
return nil
end