Classic/VPC 환경에서 이용 가능합니다.
메시지
Ncloud Chat에서 제공하는 메시지 기능은 사용자 간의 효과적인 커뮤니케이션을 지원하는 다양한 서비스를 포함합니다. 이 플랫폼은 개인 대화뿐만 아니라 그룹 대화에도 적합하며, 메시지를 보내고 받는 과정을 간편하고 신속하게 만들어 줍니다. 다음은 Ncloud Chat의 주요 메시지 기능과 그 특징입니다.
1. 즉시 메시징
- 실시간 소통: 사용자들은 실시간으로 메시지를 보내고 받을 수 있으며, 이는 커뮤니케이션의 지연을 최소화합니다.
- 다중 장치 지원: 사용자는 스마트폰, 태블릿, PC 등 다양한 장치에서 메시지를 주고받을 수 있습니다.
2. 그룹 채팅
- 다수의 참여자: 사용자는 여러 명이 참여하는 그룹 채팅을 생성하여 정보를 공유하고 팀 내 소통을 용이하게 할 수 있습니다.
- 채널 관리: 관리자는 그룹 채팅을 통해 멤버를 추가하거나 제거하고, 그룹의 설정을 조정할 수 있습니다.
3. 파일 공유
- 다양한 파일 형식 지원: 텍스트, 이미지, 비디오, 문서 등 다양한 형식의 파일을 채팅을 통해 손쉽게 공유할 수 있습니다.
- 안전한 파일 보관: Ncloud Chat은 고객님 소유의 Object Storage 내에 파일을 저장관리하기 때문에 정보의 외부 유출을 방지합니다.
4. 메시지 검색
- 키워드 검색: 채팅 내에서 특정 키워드를 사용하여 과거의 대화 내용을 검색할 수 있습니다.
- 고급 필터 옵션: 날짜, 참여자, 파일 유형 등 다양한 필터를 적용하여 원하는 메시지를 빠르게 찾을 수 있습니다.
5. 알림 및 알림 조정
- 푸시 알림: 새 메시지나 중요한 업데이트가 있을 때 사용자에게 알림을 보내어 정보의 누락을 방지합니다.
- 알림 설정: 사용자는 알림의 종류와 빈도를 조정할 수 있어, 원하는 방식으로 정보를 받아볼 수 있습니다.
6. 보안과 개인 정보 보호
- 데이터 암호화: 모든 메시지는 전송과 저장 과정에서 암호화되어 외부로부터의 데이터 유출을 방지합니다.
- 개인 정보 보호: 사용자의 개인 정보와 대화 내용은 엄격하게 보호되며, 사용자의 동의 없이 제3자에게 공개되지 않습니다.
Ncloud Chat의 메시지 기능은 사용자의 커뮤니케이션을 원활하고 효율적으로 만들어 주며, 업무와 일상 생활에서 중요한 역할을 합니다. 이러한 기능들은 사용자가 더욱 쉽게 소통할 수 있도록 돕고, 팀워크를 강화하는 데 크게 기여합니다.
메시지 전달
채널을 생성하고 가입했다면 아래와 같이 호출하여 새로운 메시지를 전달합니다.
Javascript/Typescript
const message = 'Hello !!!';
await nc.sendMessage([CHANNEL_ID], {
type: "text",
message: message
});
// 특정 사용자 언급을 위한 맨션 사용시
await nc.sendMessage(CHANNEL_ID, {
type: "text",
mentions: [USER_ID, USER_ID]
message: message
});
// 멘션을 보내는 또 다른 방법으로는 메시지내에 '@[ID]' 와 같이 입력할 경우 자동으로 멘션에 저장된다.
// 메시지에 답글을 보내는 경우
await nc.sendMessage(CHANNEL_ID, {
type: "text",
parent_message_id: MESSAGE_ID
message: message
});
// 신규 메시지에서 아래과 같이 parent_message 로 부모 메시지의 내용을 보강하여 전달합니다.
{
"id": "message_id",
"text": "Message",
"parent_message_id": "first_message_id",
"parent_message": {
"id": "message_id",
"text": "message_name",
"sender" : {
"id" : "Sender",
"name" : "Sender Nickname",
"profile" : "profile url",
}
}
}
Android(Kotlin)
NChat.sendMessage([CHANNEL_ID], messageText) { message, e ->
if (e != null) {
// 오류
} else {
// 성공
}
}
iOS(Swift)
NChat.sendMessage(channelId: [CHANNEL_ID], message: messageText) { result in
switch(result)
{
case .success(let message) :
// 성공
break;
case .failure(let error) :
// 실패
break;
}
}
iOS(Objective-C)
[NChatBridge.shared sendMessageWithChannelId:[CHANNEL_ID] message:[MESSAGE] type:@"TEXT" parentMessageId:@"" translate:NO :^(NSDictionary * _Nullable result, NSError * _Nullable error) {
if (error) {
// 오류 처리
} else {
// 성공 처리
}
}];
Unity
const message = 'Hello !!!';
await nc.sendMessage(
channelId: CHANNEL_ID,
type:"text",
content: message
);
// 메시지에 답글을 보내는 경우
await nc.sendMessage(
channelId: CHANNEL_ID,
type:"text",
content: message,
parentMessageId: [MESSAGE_ID]
);
// 메시지에 자동 번역을 해야하는 경우
await nc.sendMessage(
channelId: CHANNEL_ID,
type:"text",
content: message,
translate: true
);
// 신규 메시지에서 아래과 같이 parent_message 로 부모 메시지의 내용을 보강하여 전달합니다.
{
"id": "message_id",
"text": "Message",
"parent_message_id": "first_message_id",
"parent_message": {
"id": "message_id",
"text": "message_name",
"sender" : {
"id" : "Sender",
"name" : "Sender Nickname",
"profile" : "profile url"
}
}
}
message는 JSON 형태로 발송/수신하시면 다양한 사용자 정의 값을 사용할 수 있습니다.
Javascript/Typescript
const message = {
{ "text", "Text" },
{ "state", 1 },
{ "desc" , "Desc" }
};
// 메시지를 스트링으로 변환합니다.
const jsonString = JSON.stringify(message);
// 받은 메시지를 Array 로 변환합니다.
const messageArray = JSON.parse(jsonString);
Unity
Hashtable messageArray = new Hashtable
{
{ "channel_id", "channelId" },
{ "state", 1 },
{ "desc" , "Desc" }
};
// 메시지를 일반 텍스트로 변환 합니다.
const jsonString = JsonConvert.SerializeObject(messageArray);
// 받은 메시지를 Array 로 변환합니다.
Hashtable hashtable = JsonConvert.DeserializeObject<Hashtable>(jsonString);
| ID | Type | Description |
|---|---|---|
| CHANNEL_ID | string | 채널 아이디 |
| type | string | 보내는 메시지 종류(text, image) |
| MESSAGE | string | 전송 메시지 텍스트, JSON String을 활용하면 다양하게 사용 가능 |
| MENTIONS | array | 멘션할 사용자 ID |
- Express Message 사용하기: 오직 고속으로 메시지를 발송하기 위한 함수입니다. 시간 지연이 걸릴 수 있는 부분을 모두 스킵하여 기존 대비 10배 빠르게 메시지 전송이 가능합니다. 일반 sendMessage와 차이점은 아래와 같습니다.
| Function | Description | 필터링 | 차단 | 번역 |
|---|---|---|---|---|
| sendMessage | 일반 메시지 발송 | O | O | O |
| sendExpressMessage | 빠른 메시지 발송 | X | X | X |
게임 내에서 실시간 PvP를 제작하거나 고속의 Broadcasting이 필요한 모든 서비스에 이용이 가능합니다.
파일 업로드
- 특정 채널로 파일을 전송할 수 있습니다.
- 대시보드 > 설정 > 보안 > 허용된 파일 타입만 업로드할 수 있습니다.
Javascript/Typescript
await nc.sendFile([CHANNEL_ID], file);
Android (Kotlin)
import android.app.Activity
import android.content.Intent
import android.net.Uri
...
private val PICK_FILE_REQUEST_CODE = 1009
fun fileUpload() {
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "*/*"
startActivityForResult(intent, PICK_FILE_REQUEST_CODE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == PICK_FILE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
val fileUri: Uri? = data?.data
fileUri?.let {
// 선택된 파일 URI를 사용하여 파일 업로드
NChat.sendFile(this, [CHANNEL_ID], it) { response,e ->
if (e != null) {
// 오류
} else {
// 성공
}
}
}
}
}
iOS (Swift)
파일 업로드 기능 사용을 위해서 아래 예시와 같이 DocumentPicker 를 추가합니다.
import SwiftUI
import UniformTypeIdentifiers
struct DocumentPicker: UIViewControllerRepresentable {
class Coordinator: NSObject, UIDocumentPickerDelegate {
var parent: DocumentPicker
init(parent: DocumentPicker) {
self.parent = parent
}
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
guard let selectedFileURL = urls.first, selectedFileURL.startAccessingSecurityScopedResource() else { return }
parent.selectedFileURL = selectedFileURL
parent.isPresented = false
}
}
@Binding var selectedFileURL: URL?
@Binding var isPresented: Bool
func makeCoordinator() -> Coordinator {
return Coordinator(parent: self)
}
func makeUIViewController(context: Context) -> UIDocumentPickerViewController {
let picker = UIDocumentPickerViewController(forOpeningContentTypes: [UTType.item])
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: Context) {
}
}
View 내 파일 업로드 기능을 아래 예시와 같이 구현합니다.
@State private var selectedFileURL: URL?
@State private var isDocumentPickerPresented = false
if let selectedFileURL = selectedFileURL {
Text("선택된 파일: \(selectedFileURL.lastPathComponent)")
Button(action: {
NChat.sendFile(channelId: channelId, fileUrl: selectedFileURL) { result in
switch(result) {
case .success(let result):
// 성공
case .failure(let error):
// 실패
}
}
}) {
Text("파일 업로드")
}
} else {
Text("파일을 선택하세요")
}
// 파일 업로드 완료 후 호출해 주십시오.
selectedFileURL?.stopAccessingSecurityScopedResource()
var body: some View {
VStack {
Button(action: {
isDocumentPickerPresented = true
}) {
Text("파일 선택")
}
.sheet(isPresented: $isDocumentPickerPresented) {
DocumentPicker(selectedFileURL: $selectedFileURL, isPresented: $isDocumentPickerPresented)
}
- 파일 외에 이미지 업로드를 구현하고자 한다면 UIImagePickerController 를 사용해 주십시오.
- 이미지 업로드를 위해 Targets > Info > Custom iOS Target Properties 내 Privacy - Photo Library Usage Description 정의해 주십시오.
iOS(Objective-C)
파일 업로드 기능 사용을 위해서 UIImagePickerController 혹은 UIDocumentPickerViewController 구현 이후 fileUrl를 통해 파일을 업로드 합니다.
NSURL *fileUrl = [NSURL URLWithString:[FILEURL]];
if (fileUrl) {
[NChatBridge.shared sendFileWithChannelId:channelId fileUrl:fileUrl :^(NSDictionary * _Nullable result, NSError * _Nullable error) {
if (error) {
[self inAppLog:[NSString stringWithFormat:@"Send File Error: %@", error.localizedDescription]];
} else {
[self inAppLog:[NSString stringWithFormat:@"Send File succeeded with result: %@", result]];
}
[self.tableView reloadData];
}];
}
Unity
await nc.sendFile([CHANNEL_ID],file);
| ID | Type | Description |
|---|---|---|
| CHANNEL_ID | string | 채널 아이디 |
| file | string | 파일 정보 |
- 오브젝트 스토리지가 활성화되어 있어야 합니다.
- Object Storage 상품과 연동한 후에 사용할 수 있습니다.
- 업로드 시 대시보드 프로젝트 설정 > 보안설정에 업로드 타입과 업로드 크기 등을 설정해 주십시오.
- 지원 파일 타입: 이미지, 비디오, 문서, 압축 등의 일반적인 타입을 모두 지원하며, 추가로 지원이 필요한 확장자는 문의하기를 통해 문의 주시면 보안 검토 후 추가해 드리고 있습니다.
- 파일 링크 활용시 Endpoint 주소는 https://apps.ncloudchat.naverncp.com 입니다.
예) https://apps.ncloudchat.naverncp.com/archive/[archiveId]
메시지 정보
- Message Data Class
| ID | Type | Description |
|---|---|---|
| id | string | 메시지 전송 아이디 (unique) |
| message_id | string | 메시지 아이디 |
| sort_id | string | 메시지 정렬을 위한 식별자 |
| message_type | string | 메시지 종류 |
| sender.id | string | 보낸 사용자 ID |
| sender.name | string | 보낸 사용자 이름 |
| sender.profile | string | 보낸 사용자 프로필 이미지 |
| attachment_filenames | string | 첨부 파일 |
| parent_message_id | string | 답글 메시지 아이디 |
| parent_message | Message | 답글 메시지 |
| isExpress | boolean | 빠른 메시지 여부 |
| metions | string | 맨션된 리스트 |
| content | string | 메시지 내용 |
| sended_at | string | 보낸 일자 |
| created_at | string | 생성 일자 |
개별 메시지 정보
개별 메시지에 대한 정보를 가져올 수 있습니다.
Javascript/Typescript
var message = await nc.getMessage(channel_id, message_id);
Android (Kotlin)
NChat.getMessage([MESSAGE_ID]) { message, e -> {
if (e != null) {
// 오류
} else {
// 성공
}
}
iOS (Swift)
NChat.getMessage(channelId: [CHANNEL_ID], messageId: [MESSAGE_ID]) { result in
switch(result)
{
case .success(let message) :
// 성공
break;
case .failure(let error) :
// 실패
break;
}
}
iOS(Objective-C)
[NChatBridge.shared getMessageWithChannelId:[CHANNEL_ID] messageId:[MESSAGE_ID] :^(NSDictionary * _Nullable result, NSError * _Nullable error) {
if (error) {
// 오류 처리
} else {
// 성공 처리
}
}];
Unity
NBaseSDK.Message message = await nc.getMessage([CHANNEL_ID], [MESSAGE_ID]);
전체 메시지 정보
전체 메시지 정보를 가져올 수 있습니다.
- MessageData data class
| ID | Type | Description |
|---|---|---|
| totalCount | Int | 전체 메시지 수 |
| messages | Message | 메시지 데이터 리스트 |
Javascript/Typescript
const filter = { channel_id: channelId };
const sort = { created_at: -1 };
const option = { offset: 0, per_page: 100 };
const messages = nc.getMessages(filter, sort, option);
Android (Kotlin)
- 필터 설정
val filter: Map<String, Any?> = mapOf(
"channel_id" to [CHANNEL_ID],
)
- 정렬 설정
val sort: Map<String, Any?> = mapOf(
"created_at" to -1
)
- 옵션 설정
val options: Map<String, Any?> = mapOf(
"per_page" to 10,
"offset" to 0
)
NChat.getMessages(filter, sort, options) { data, e ->
if (e != null) {
// 오류
} else {
// 성공
}
}
iOS (Swift)
let filter: [String: Any] = ["channel_id": [CHANNEL_ID]]
let option: [String: Any] = ["per_page": 10, "offset": 0]
let sort: [String: Any] = ["created_at": "-1"]
NChat.getMessages(filter: filter, option: option, sort: sort) { result in
switch(result)
{
case .success(let messagesData) :
// 성공
break;
case .failure(let error) :
// 실패
break;
}
}
iOS(Objective-C)
NSMutableDictionary *filter = [NSMutableDictionary dictionary];
NSMutableDictionary *option = [NSMutableDictionary dictionary];
NSMutableDictionary *sort = [NSMutableDictionary dictionary];
filter[@"channel_id"] = @"[CHANNEL_ID]";
[NChatBridge.shared getMessagesWithChannelId:[CHANNEL_ID] filter:filter option:option sort:sort :^(NSDictionary * _Nullable result, NSError * _Nullable error) {
if (error) {
// 오류 처리
} else {
// 성공 처리
}
}];
Unity
Hashtable filter = new Hashtable
{
{ "channel_id", [CHANNEL_ID] }
};
Hashtable sort = new Hashtable
{
{ "sort_id", -1 }
};
Hashtable option = new Hashtable
{
{ "offset", 0 },
{ "per_page", 10 }
};
var messages = await nc.getMessages(filter, sort, option);
if (messages != null)
{
foreach (var message in messages.edges)
{
string id = message.Node.message_id.ToString();
Console.WriteLine("[CloudChatSample] id={0}", id);
}
}
- Parameters
| ID | Type | Description | Required |
|---|---|---|---|
| filter | object | 쿼리를 필터 모든 필드에 대해서 검색 가능 | O |
| sort | object | 정렬하고자 하는 필드의 필터 정의 | X |
| option | object | 옵션이 존재할 경우 아래를 참고 | X |
- Filter
| ID | Type | Description |
|---|---|---|
| message_id | String | 메시지 ID |
| channel_id | String | 채널 ID |
| sort_id | String | 정렬 ID |
| message_type | String | 메시지 타입 |
| embedProviders | String | 임베드 제공자 |
| isExpress | Boolean | 즉시 메시지 여부 |
| bytes | Int | 메시지 바이트 크기 |
| content | String | 메시지 내용 |
| sended_at | String | 메시지 전송 시간 |
| created_at | String | 메시지 생성 시간 |
- Sort
| ID | Type | Description |
|---|---|---|
| created_at | number | 생성 날짜 (오름차순 "1", 내림차순 "-1") |
- Options
| ID | Type | Description |
|---|---|---|
| offset | number | 시작 offset |
| per_page | number | 리턴하는 개수(최대 100개) |
안 읽은 메시지
읽지 않는 메시지 수를 리턴합니다. 첫 번째로 markRead를 통해서 마지막 읽은 메시지의 정보를 전달합니다.
Javascript/Typescript
nc.markRead(channelId, {
user_id: message.sender.id,
message_id: message.message_id,
sort_id: message.sort_id
});
const unread = await nc.unreadCount([CHANNEL_ID]);
Android (Kotlin)
NChat.unreadCount([CHANNEL_ID]) { data, e ->
if (e != null) {
// 오류
} else {
// 성공
}
}
iOS (Swift)
NChat.unreadCount(channelId: [CHANNEL_ID]) { result in
switch(result)
{
case .success(let mark) :
// 성공
break;
case .failure(let error) :
// 실패
break;
}
}
Unity
nc.markRead([CHANNEL_ID], new NBaseSDK.MarkInput
{
user_id = USER_ID,
message_id = MESSAGE_ID,
sort_id = SORT_ID
});
// 마크된 이후의 읽지 않은 메시지 전체 개수를 리턴합니다.
var unread = nc.unreadCount([CHANNEL_ID]);
| ID | Type | Description |
|---|---|---|
| USER_ID | string | 메시지에 포함된 user_id 입력 |
| MESSAGE_ID | string | 메시지에 포함된 message_id 입력 |
| SORT_ID | string | 메시지에 포함된 sort_id 입력 |
메시지 삭제
해당 채널내에 내가 보낸 메시지를 삭제할 수 있습니다.
Javascript/Typescript
await nc.deleteMessage([CHANNEL_ID], [MESSAGE_ID]);
Android (Kotlin)
NChat.deleteMessage([CHANNEL_ID], [MESSAGE_ID]) { data, e ->
if (e != null) {
// 오류
} else {
// 성공
}
}
iOS (Swift)
NChat.deleteMessage(channelId: [CHANNEL_ID], messageId: [MESSAGE_ID]) { result in
switch(result)
{
case .success(let message) :
// 성공
break;
case .failure(let error) :
// 실패
break;
}
}
iOS(Objective-C)
[NChatBridge.shared deleteMessageWithChannelId:[CHANNEL_ID] messageId:[MESSAGE_ID] :^(NSDictionary * _Nullable result, NSError * _Nullable error) {
if (error) {
// 오류 처리
} else {
// 성공 처리
}
}];
Unity
await nc.deleteMessage([CHANNEL_ID], [MESSAGE_ID]);
- Parameters
| ID | Type | Description |
|---|---|---|
| CHANNEL_ID | string | 채널 ID |
| MESSAGE_ID | string | 메시지 ID |
특정 메시지에 대한 안 읽은 사용자 수
채널에 참여한 사용자 목록에서 읽은 사용자 목록을 제외한 나머지 사용자가 안 읽은 사용자로 간주됩니다.
Javascript/Typescript
await nc.getMessageReadCount([CHANNEL_ID], [MESSAGE_ID]);
- Parameters
| ID | Type | Description |
|---|---|---|
| CHANNEL_ID | string | 채널 ID |
| MESSAGE_ID | string | 메시지 ID |
특정 메시지에 대한 안 읽은 사용자 수
이 메서드는 지정된 채널 내에서 특정 메시지를 읽지 않은 사용자의 수를 반환합니다.
Javascript/Typescript
await nc.getMessageUnreadCount(CHANNEL_ID, MESSAGE_ID);
- Parameters
| Parameter | Type | Description |
|---|---|---|
| CHANNEL_ID | string | 채널의 고유 식별자입니다. 이 값을 통해 특정 채널을 지정합니다. |
| MESSAGE_ID | string | 메시지의 고유 식별자입니다. 읽지 않은 사용자 수를 조회하고자 하는 메시지를 지정합니다. |
- Returns
getMessageUnreadCount 메서드는 다음과 같은 형식의 객체를 반환합니다.
{
"totalCount": 34,
"count": 34
}
| Parameter | Type | Description |
|---|---|---|
| totalCount | number | 지정된 채널에 참여한 전체 사용자 수를 나타냅니다. |
| count | number | 지정된 메시지를 아직 읽지 않은 사용자의 수를 나타냅니다. |
- 사용 예시
const result = await nc.getMessageUnreadCount("123456789", "987654321");
console.log(result.totalCount); // 예: 채널에 참여한 전체 사용자 수: 34
console.log(result.count); // 예: 메시지를 읽지 않은 사용자 수: 10
위의 예제에서는 채널 ID가 "123456789"이고 메시지 ID가 "987654321"인 특정 메시지에 대해, 해당 메시지를 읽지 않은 사용자의 수를 조회하고 있습니다. result.totalCount는 채널에 속한 전체 사용자의 수를 나타내며, result.count는 지정된 메시지를 아직 읽지 않은 사용자의 수를 나타냅니다.
이 기능을 통해 채널 내에서 특정 메시지가 얼마나 많은 사용자에게 읽히지 않았는지를 쉽게 파악할 수 있습니다.