# 상태

**URL:** https://heroiclabs.com/docs/kr/nakama/concepts/status/
**Summary:** Nakama 사용자는 연결 시 상태 메시지를 설정하고 온라인 상태에서 업데이트할 수 있습니다. 상태는 각 연결에 대해 설정되며 사용자가 연결을 끊으면 사라집니다. 사용자는 상태 변경에 대한 알림을 받기 위해 서로 서로 팔로우할 수 있습니다. 이것은 친구가 온라인 상태이고 무엇을 하는지 알려고 할 때 아주 좋습니다.

---


# 상태

Nakama 사용자는 연결 시 상태 메시지를 설정하고 온라인 상태에서 업데이트할 수 있습니다.

사용자는 상태 변경에 대한 알림을 받기 위해 서로 서로 팔로우할 수 있습니다. 이것은 친구가 온라인 상태인지 그리고 최근 활동 상태가 무엇인지 알려고 할 때 아주 좋습니다

상태는 각 연결에 대해 설정되며 사용자가 연결을 끊으면 사라집니다. 사용자가 여러 장치에서 연결된 경우 각 장치의 상태가 다를 수 있습니다.

## 상태 설정

기본적으로 사용자는 처음 연결하는 경우 상태가 없으며 팔로워에게 온라인으로 표시되지 않습니다. 온라인으로 표시되려면 사용자가 상태를 설정해야 합니다.

상태는 사용자가 팔로워에게 보내는 문자 메시지처럼 간단할 수 있거나, 사용자가 현재 포함되어 있는 [실시간 멀티플레이어 대결 ID](../multiplayer/relayed/)와 같은 복잡한 정보가 있는 구조화된 JSON 문자열이 될 수 있습니다. 따라서 친구들이 바로 참석하여 가입할 수 있습니다!

{{< code type="client" >}}
```javascript
socket.updateStatus("Hello everyone!");
```
{{< / code >}}

{{< code type="client" >}}
```csharp
await socket.UpdateStatusAsync("Hello everyone!");
```
{{< / code >}}

{{< code type="client" >}}
```cpp
rtClient->updateStatus("Hello everyone!");
```
{{< / code >}}

{{< code type="client" >}}
```java
socket.updateStatus("Hello everyone!").get();
```
{{< / code >}}

{{< code type="client" framework="godot3" >}}
```gdscript
var update : NakamaAsyncResult = yield(socket.update_status_async(JSON.print({"status": "happy"})), "completed")
if update.is_exception():
    print("An error occurred: %s" % update)
    return
print("Status updated")
```
{{< / code >}}

{{< code type="client" framework="defold" >}}
```lua
socket.status_update(socket, "Hello everyone!")
```
{{< / code >}}

{{< missing type="client" lang="bash" />}}
{{< missing type="client" lang="shell" />}}

이 작업으로 필요할 때마다 상태를 설정하고 업데이트할 수 있습니다.

## 오프라인으로 표시

사용자를 오프라인으로 표시하거나 "보이지 않는" 상태로 나타내려면 해당 상태를 지웁니다. 팔로워는 사용자가 연결을 끊을 때와 같은 상태 업데이트를 받습니다.

{{< code type="client" >}}
```javascript
socket.updateStatus();
```
{{< / code >}}

{{< code type="client" >}}
```csharp
await socket.UpdateStatusAsync(null);
```
{{< / code >}}

{{< code type="client" >}}
```cpp
rtClient->updateStatus("");
```
{{< / code >}}

{{< code type="client" >}}
```java
socket.updateStatus(null).get();
```
{{< / code >}}

{{< code type="client" framework="godot3" >}}
```gdscript
var leave : NakamaAsyncResult = yield(socket.update_status_async(""), "completed")
if leave.is_exception():
    print("An error occurred: %s" % leave)
    return
print("Status updated")
```
{{< / code >}}

{{< missing type="client" lang="lua" framework="defold" />}}
{{< missing type="client" lang="bash" />}}
{{< missing type="client" lang="shell" />}}

## 상태 업데이트 받기

사용자가 상태를 업데이트하면 모든 팔로워가 이전 상태와 새 상태가 모두 포함된 이벤트를 수신합니다. 클라이언트는 상태 업데이트를 받을 때 호출될 이벤트 핸들러를 등록합니다.

{{< code type="client" >}}
```javascript
socket.onstatuspresence = (statuspresence) => {
    statuspresence.leaves.forEach((leave) => {
        console.log("User %o no longer has status %o", leave.user_id, leave.status);
    });
    statuspresence.joins.forEach((join) => {
        console.log("User %o now has status %o", join.user_id, join.status);
    });
};
```
{{< / code >}}

{{< code type="client" >}}
```csharp
socket.ReceivedStatusPresence += presenceEvent =>
{
    Console.WriteLine(presenceEvent);
    foreach (var joined in presenceEvent.Joins)
    {
        Console.WriteLine("User id '{0}' status joined '{1}'", joined.UserId, joined.Status);
    }
    foreach (var left in presenceEvent.Leaves)
    {
        Console.WriteLine("User id '{0}' status left '{1}'", left.UserId, left.Status);
    }
};
```
{{< / code >}}

{{< code type="client" >}}
```cpp
rtListener->setStatusPresenceCallback([](const NStatusPresenceEvent& event)
{
    for (auto& presence : event.leaves)
    {
        std::cout << "User " << presence.username << " no longer has status " << presence.status << std::endl;
    }

    for (auto& presence : event.joins)
    {
        std::cout << "User " << presence.username << " now has status " << presence.status << std::endl;
    }
});
```
{{< / code >}}

{{< code type="client" >}}
```java
SocketListener listener = new AbstractSocketListener() {
    @Override
    public void onStatusPresence(final StatusPresenceEvent presence) {
        for (UserPresence userPresence : presence.getJoins()) {
            System.out.println("User ID: " + userPresence.getUserId() + " Username: " + userPresence.getUsername() + " Status: " + userPresence.getStatus());
        }

        for (UserPresence userPresence : presence.getLeaves()) {
            System.out.println("User ID: " + userPresence.getUserId() + " Username: " + userPresence.getUsername() + " Status: " + userPresence.getStatus());
        }
    }
};
```
{{< / code >}}

{{< code type="client" framework="godot3" >}}
```gdscript
func _ready():
    # First, setup the socket as explained in the authentication section.
    socket.connect("received_status_presence", self, "_on_status_presence")

func _on_status_presence(p_presence : NakamaRTAPI.StatusPresenceEvent):
    print(p_presence)
    for j in p_presence.joins:
        print("%s joined with status: %s" % [j.user_id, j.status])
    for j in p_presence.leaves:
        print("%s left with status: %s" % [j.user_id, j.status])
```
{{< / code >}}

{{< missing type="client" lang="lua" framework="defold" />}}
{{< missing type="client" lang="bash" />}}
{{< missing type="client" lang="shell" />}}

사용자가 연결이 끊기거나 오프라인으로 표시되면 이전 상태는 유지되지만 해당하는 새 상태는 없습니다.

## 사용자 팔로우하기

사용자는 자신이 팔로우하는 사람의 상태 업데이트를 받습니다. 사용자는 관심 있는 모든 사람을 팔로우할 수 있지만 친구의 온라인 상태와 최근 활동을 확인하기 위해 친구 목록을 팔로우하는 것이 일반적입니다.

일련의 사용자를 팔로우하는 경우 이 작업은 즉시 온라인 상태이고 표시되는 상태를 설정한 사용자의 상태를 반환합니다.

사용자를 팔로우하는 것은 현재 세션에서만 활성화됩니다. 사용자가 연결을 끊으면 연결 중 팔로우한 사람을 자동으로 팔로우 취소합니다.

{{< code type="client" >}}
```javascript
var status = await socket.followUsers(["<user id>"]);
status.presences.forEach((presence) => {
  console.log("User %o has status %o", presence.user_id, presence.status);
});
```
{{< / code >}}

{{< code type="client" >}}
```csharp
await socket.FollowUsersAsync(new[] { "<user id>" });
```
{{< / code >}}

{{< code type="client" >}}
```cpp
auto successCallback = [](const NStatus& status)
{
    for (auto& presence : status.presences)
    {
        std::cout << "User " << presence.username << " has status " << presence.status << std::endl;
    }
};

rtClient->followUsers({ "<user id>" }, successCallback);
```
{{< / code >}}

{{< code type="client" >}}
```java
socket.followUsers("<user id>").get();
```
{{< / code >}}

{{< code type="client" framework="godot3" >}}
```gdscript
var user_ids = ["<user-id1>", "<user-id2>"]
var status : NakamaRTAPI.Status = yield(socket.follow_users_async(user_ids), "completed")
if status.is_exception():
    print("An error occurred: %s" % status)
    return
print(status)
```
{{< / code >}}

{{< missing type="client" lang="lua" framework="defold" />}}
{{< missing type="client" lang="bash" />}}
{{< missing type="client" lang="shell" />}}

## 사용자 팔로우 취소하기

일련의 사용자를 팔로우 취소하면 사용자는 취소한 사용자의 추가 상태 업데이트를 받지 않습니다.

{{< code type="client" >}}
```javascript
socket.unfollowUsers(["<user id>"]);
```
{{< / code >}}

{{< code type="client" >}}
```csharp
await socket.UnfollowUsersAsync(new[] { "<user id>" });
```
{{< / code >}}

{{< code type="client" >}}
```cpp
rtClient->unfollowUsers({ "<user id>" });
```
{{< / code >}}

{{< code type="client" >}}
```java
socket.unfollowUsers("<user id>").get();
```
{{< / code >}}

{{< code type="client" framework="godot3" >}}
```gdscript
var user_ids = ["<user-id1>", "<user-id2>"]
var status : NakamaAsyncResult = yield(socket.unfollow_users_async(user_ids), "completed")
if status.is_exception():
    print("An error occurred: %s" % status)
    return
print(status)
```
{{< / code >}}
