> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Using direct peer-to-peer connections

> PlayFab Party에서 직접 피어 연결을 활성화하여 트래픽을 투명 클라우드 릴레이가 아닌 엔드포인트 간에 직접 라우팅함으로써 지연 시간을 줄이는 방법을 알아봅니다.

# PlayFab Party 및 직접 피어-투-피어 연결

이 페이지는 예제 게임 코드를 사용하여 PlayFab Party에서 직접 피어-투-피어 연결을 활성화하고 사용하는 방법을 설명합니다. 또한 게임에서 직접 피어-투-피어 연결을 언제 사용할지 평가하는 데 도움이 되는 고려 사항도 포함되어 있습니다.

## 직접 피어-투-피어 연결을 사용할 때

PlayFab Party는 다양한 통신 토폴로지를 지원합니다. 개념적으로 모든 채팅 또는 데이터 메시지는 한 피어 디바이스 또는 사용자로부터 다른 피어에게 직접 전달됩니다. 그러나 Party는 직접 피어-투-피어 연결을 설정할 때 발생하는 일반적인 환경적, 보안적 문제를 방지하기 위해 투명 클라우드 릴레이 서비스를 자동으로 활용합니다. 백그라운드 서비스 품질(QoS) 측정을 활용하여 저지연 데이터 전송을 달성할 수 있습니다. (자세한 내용은 [PlayFab Party QoS measurements](/services/playfab/multiplayer/networking/concepts-regions)를 참조하세요.) 데이터 전송 지연 시간을 더 줄이기 위해 선택적으로 직접 피어-투-피어 연결을 활성화할 수 있습니다. 아래 “보안 고려 사항”에 자세히 설명된 보안 우려로 인해, Microsoft는 타이틀이 엄격한 지연 시간 요구 사항을 가지지 않는 한 직접 피어-투-피어 연결을 활성화하는 대신 클라우드 릴레이 서비스를 사용할 것을 권장합니다.

### 플랫폼 지원

직접 피어 연결은 Party 라이브러리의 Windows 10, Microsoft Game Core, Nintendo Switch, PlayStation®4, PlayStation®5 버전에서 지원됩니다. 라이브러리의 다른 버전은 클라이언트 API를 통해 지정된 직접 피어 연결 옵션과 관계없이 항상 클라우드 릴레이를 사용하여 데이터를 전송합니다.

“PlayStation”은 Sony Interactive Entertainment Inc.의 등록 상표 또는 상표입니다.

### 보안 고려 사항

직접 피어 연결은 클라이언트 간에 데이터를 직접 보내는 데 사용되므로 모든 클라이언트가 서로 연결하는 방법을 알아야 합니다. 이는 함께 있는 게임 세션의 클라이언트 간에 IP 주소를 공유하여 수행됩니다. 예를 들어 16인 멀티플레이어 게임이 플레이어 위치를 업데이트하기 위해 직접 피어 연결을 사용하는 경우, 16개의 게임 클라이언트 각각은 데이터를 보낼 대상을 알기 위해 다른 15개 클라이언트의 IP 주소를 알아야 합니다.

게임 클라이언트 간에 IP 주소를 공유하는 것은 보안 위험입니다. IP 주소를 공유하면 악의적인 행위자가 IP 주소를 감지하여 게임 밖에서 다른 플레이어를 악의적으로 공격하는 데 사용할 수 있습니다. 이러한 공격을 수행하는 일반적인 방법은 DoS(Denial-of-Service, 서비스 거부) 공격 또는 그 변형인 DDoS(Distributed Denial of Service, 분산 서비스 거부) 공격을 통해서입니다. 이러한 공격은 불필요한 네트워크 트래픽으로 네트워크를 압도하려는 방식으로 작동합니다. 공격자가 피해자에게 충분한 네트워크 트래픽을 보낼 수 있다면 피해자의 네트워크 하드웨어(모뎀 및 라우터)는 모든 시간을 불필요한 트래픽을 처리하는 데 소비해야 하며, 합법적인 네트워킹 연결 처리라는 일반적인 작업을 할 시간이 없게 됩니다. 실질적으로 이는 피해자가 공격이 진행되는 동안 자신의 네트워크를 사용할 수 없다는 것을 의미합니다. 이를 흔히 “부팅 오프라인(booted offline)”이라고 합니다.

결론적으로, 성공적인 직접 피어 연결은 일부 디바이스 간에 더 낮은 지연 시간을 제공할 수 있습니다. 그러나 이를 설정하려는 시도 자체가 사용자가 IP 주소를 다른 사람에게 공개해야 하며, 이는 악의적인 사용자가 타이틀 밖에서 그들의 디바이스와 인터넷 연결을 공격할 수 있게 만들 수도 있습니다. 정책상의 이유로 특정 플랫폼에서는 직접 피어 연결이 허용되지 않을 수도 있습니다. 성능 및 보안 목표에 맞는 적절한 직접 피어 연결 옵션을 사용해야 합니다. 위험을 고려한 후 직접 피어 연결을 사용하기로 결정한 경우, 다음 예시를 사용하여 네트워크 및 디바이스 단위로 타이틀을 옵트인하세요.

### LAN 시나리오

Party의 직접 피어 연결은 LAN 시나리오에서 매우 낮은 지연 시간을 달성하는 데 사용할 수 있습니다. 그러나 이러한 시나리오에서도 사용자 인증, LiveOps 데이터 및 인사이트, 음성 채팅 접근성 기능을 지원하기 위해 제한된 인터넷 연결이 필요합니다.

### 업스트림 대역폭 고려 사항

직접 피어-투-피어 연결을 사용하면 게임의 업스트림 대역폭 사용량이 증가할 수 있습니다. 클라우드 릴레이 서비스를 통해 게임 또는 음성 메시지를 전송할 때 Party는 서비스에 단일 메시지를 보냅니다. 그런 다음 서비스는 메시지를 복제하여 각 대상 디바이스로 전달합니다. 직접 피어-투-피어 연결을 통해 게임 또는 음성 메시지를 전송할 때 Party는 직접 피어-투-피어 연결이 설정된 각 대상 디바이스에 대해 직접 연결을 통해 메시지를 복제하고 전송합니다. 따라서 게임의 업스트림 대역폭 사용량은 직접 피어-투-피어 연결이 설정된 디바이스 수에 비례하여 확장됩니다. 직접 피어-투-피어 연결을 활성화하기 전에 이 업스트림 대역폭 증가가 게임에 허용되는지 고려하세요.

## 게임에서 직접 피어-투-피어 연결을 사용하는 방법

### 네트워크에서 직접 피어-투-피어 연결 활성화

[`PartyManager::CreateNewNetwork()`](/services/playfab/multiplayer/networking/reference/classes/PartyManager/methods/partymanager_createnewnetwork)를 통해 네트워크를 만들 때, 호출에 제공된 [`PartyNetworkConfiguration`](/services/playfab/multiplayer/networking/reference/structs/partynetworkconfiguration)을 통해 다양한 네트워크 구성 매개 변수를 지정할 수 있습니다. `PartyNetworkConfiguration::directPeerConnectivityOptions` 필드를 사용하여 네트워크의 디바이스에 대해 직접 피어-투-피어 연결이 지원되는지 여부와 방법을 지정할 수 있습니다.

다음 예시는 플랫폼 유형이나 로그인 공급자와 관계없이 네트워크의 모든 디바이스 간에 직접 피어-투-피어 연결을 시도해야 함을 지정하는 네트워크 구성을 보여줍니다.

```cpp theme={null}
PartyNetworkConfiguration configuration = {};
configuration.directPeerConnectivityOptions = PartyDirectPeerConnectivityOptions::AnyPlatformType | PartyDirectPeerConnectivityOptions::AnyEntityLoginProvider;
// Initialize the rest of the network configuration parameters appropriately for your game before using.
```

디바이스는 초기 사용자를 네트워크에 성공적으로 인증하는 과정의 일부로, 네트워크 구성이 허용할 때 네트워크에 이미 참여 중인 다른 디바이스와 직접 피어-투-피어 연결을 설정하려고 시도할 수 있습니다. 성공한 시도의 경우, 디바이스 간의 엔드포인트 메시지와 채팅 데이터가 해당 직접 연결을 사용하여 전송됩니다. 디바이스 간의 환경적 비호환성으로 인해 실패한 시도의 경우, 해당 디바이스 간의 모든 통신은 대신 투명 클라우드 릴레이 서버를 통해 전송됩니다. 네트워크 구성에서 디바이스가 직접 피어 연결을 시도할 수 있도록 허용되지 않은 경우, 디바이스는 IP 주소 정보를 결코 교환하지 않으며 항상 투명 클라우드 릴레이 서버를 통해 엔드포인트 메시지와 채팅 데이터를 전송합니다.

<Note>
  직접 피어 연결을 설정하는 것은 최선의 노력이며, 환경적 요인, 디바이스별 연결 옵션 또는 플랫폼 정책으로 인해 불가능할 수 있습니다. 특정 디바이스와의 직접 피어-투-피어 연결이 설정되었는지 평가하는 방법에 대한 자세한 내용은 [연결 유형 및 지연 시간 평가](#evaluating-the-connection-type-and-latency)를 참조하세요.
</Note>

### 디바이스별 직접 피어 연결 제약

네트워크 구성의 직접 피어 연결 옵션 외에도, 디바이스는 [`PartyManager::SetOption()`](/services/playfab/multiplayer/networking/reference/classes/PartyManager/methods/partymanager_setoption)을 사용하여 [`PartyOption::LocalDeviceDirectPeerConnectivityOptionsMask`](/services/playfab/multiplayer/networking/reference/enums/partyoption)를 설정함으로써 인증하는 모든 네트워크에 대해 직접 피어 연결을 추가로 제약할 수 있습니다. 모든 플래그는 비트 AND 연산을 사용하여 평가됩니다. 즉, 특정 플래그는 네트워크 구성과 두 디바이스의 각각의 로컬 마스크 옵션 세 곳 모두에서 활성화된 경우에만 특정 네트워크의 디바이스 쌍에 대해 유효합니다. 네트워크 구성이 해당 형태의 직접 피어 연결을 허용하더라도, 두 디바이스 중 하나는 로컬 디바이스 마스크 옵션에서 플래그를 활성화하지 않음으로써 그들 사이의 IP 주소 공개 및 직접 연결 시도를 독립적으로 옵트아웃할 수 있습니다. 직접 피어 연결을 지원하는 라이브러리 버전에서 `PartyOption::LocalDeviceDirectPeerConnectivityOptionsMask` 값은 기본적으로 네트워크에 의해 활성화된 모든 직접 피어 연결을 허용합니다. 따라서 로컬 디바이스와 관련된 일부 또는 모든 직접 피어 연결을 방지해야 하는 디바이스별 요구 사항이 있는 경우에만 이를 구성하면 됩니다.

다음 예시는 로컬 디바이스가 동일한 플랫폼의 디바이스와만 직접 피어 연결을 시도하도록 제약하는 방법을 보여줍니다.

```cpp theme={null}
PartyDirectPeerConnectivityOptions localDeviceMask = PartyDirectPeerConnectivityOptions::SamePlatformType | PartyDirectPeerConnectivityOptions::AnyEntityLoginProvider;
PartyError error = PartyManager::GetSingleton().SetOption(nullptr, PartyOption::LocalDeviceDirectPeerConnectivityOptionsMask, &localDeviceMask);
if (PARTY_FAILED(error))
{
    printf("Failed to set local device direct peer connectivity options mask! error = 0x%08x\n", error);
}
```

### 연결 유형 및 지연 시간 평가

[`PartyNetwork::GetDeviceConnectionType()`](/services/playfab/multiplayer/networking/reference/classes/PartyNetwork/methods/partynetwork_getdeviceconnectiontype)을 호출하여 로컬 디바이스가 특정 원격 디바이스와 직접 피어-투-피어 연결을 설정했는지 여부를 확인할 수 있습니다.

사용 중인 특정 기본 전송 방법이 통신할 수 있는 전반적인 논리적 능력을 변경하지 않기 때문에, 어떤 디바이스 쌍에 대해서든 직접 피어-투-피어 연결의 가용성을 적극적으로 강제하지 않는 것을 권장합니다(즉, PartyNetwork::GetDeviceConnectionType()이 [`PartyDeviceConnectionType::DirectPeerConnection`](/services/playfab/multiplayer/networking/reference/enums/partydeviceconnectiontype) 이외의 값을 보고하는 경우에도 [`PartyNetwork::LeaveNetwork()`](/services/playfab/multiplayer/networking/reference/classes/PartyNetwork/methods/partynetwork_leavenetwork)를 호출하지 마세요). 게임 디자인이 직접 피어 연결을 장려하는 최대 메시지 지연 시간에 대한 엄격한 요구 사항을 가지고 있다면, 전송 메커니즘에 기반하여 추상적으로 가정하는 대신 [`PartyEndpointStatistic::AverageDeviceRoundTripLatencyInMilliseconds`](/services/playfab/multiplayer/networking/reference/enums/partyendpointstatistic) 통계로 보고된 해당 지연 시간의 현재 구체적인 관측치에 대해 조치를 취하는 것이 좋습니다. 그렇지 않으면 통제할 수 없는 환경적 요인으로 인해 항상 근처의 투명 클라우드 릴레이 서버를 사용해야 하는 같은 친구들과 플레이하려는 사용자를 지속적으로 방해할 수 있습니다.

다음 예시는 `network`에서 `localEndpoint`로부터 `remoteEndpoint`까지의 왕복 지연 시간을 검사하는 방법을 보여줍니다.

```cpp theme={null}
// A helper for inspecting the connection type and average round trip latency between a local endpoint and a remote
// endpoint in a network.
void PrintConnectionTypeAndLatency(
    PartyNetwork* network,
    PartyLocalEndpoint* localEndpoint,
    PartyEndpoint* remoteEndpoint
    )
{
    // Retrieve the device associated with the remote endpoint.
    PartyDevice* remoteDevice;
    PartyError error = remoteEndpoint->GetDevice(&remoteDevice);
    if (PARTY_FAILED(error))
    {
        printf("Failed to get the remote device! error = 0x%08x\n", error);
        return;
    }

    // Get the device connection type.
    PartyDeviceConnectionType connectionType;
    PartyError error = network->GetDeviceConnectionType(remoteDevice, &connectionType);
    if (PARTY_FAILED(error))
    {
        printf("Failed to get device connection type! error = 0x%08x\n", error);
        return;
    }

    // Retrieve the latency statistic.
    PartyEndpointStatistic latencyStatistic = PartyEndpointStatistic::AverageDeviceRoundTripLatencyInMilliseconds;
    uint64_t latencyStatisticValue;
    error = localEndpoint->GetEndpointStatistics(
        1,                       // targetEndpointCount
        &remoteEndpoint,         // targetEndpoints
        1,                       // statisticCount
        &latencyStatistic,       // statisticTypes
        &latencyStatisticValue); // statisticValues
    if (PARTY_FAILED(error))
    {
        printf("Failed to get latency statistic! error = 0x%08x\n", error);
        return;
    }

    // Print the results.
    printf("Local endpoint 0x%p and remote endpoint 0x%p in network 0x%p have average round trip latency %llu ms and device connection type %i\n",
        localEndpoint,
        remoteEndpoint,
        network,
        latencyStatisticValue,
        static_cast<int32_t>(connectionType));
}
```

### 연결 유형 변경

환경 조건이 변화하여 직접 피어 연결이 방해받아 PlayFab Party에서 사용할 수 없게 될 가능성이 있습니다.
이런 일이 발생하면 디바이스는 클라우드 릴레이 서버를 통한 통신으로 대체하려고 시도합니다. 릴레이 통신이 여전히 가능하다면 [PartyNetwork::GetDeviceConnectionType()](/services/playfab/multiplayer/networking/reference/classes/PartyNetwork/methods/partynetwork_getdeviceconnectiontype) 함수는 [PartyDeviceConnectionType::RelayServer](/services/playfab/multiplayer/networking/reference/enums/partydeviceconnectiontype)를 보고하기 시작하고, 디바이스는 앞으로도 새로운 연결 유형을 사용하여 Party 네트워크에 계속 남아 있게 됩니다. 그렇지 않으면 연결이 방해받은 디바이스는 네트워크에서 나갑니다.

<Warning>
  직접 피어 연결이 방해받았을 때 아직 전송 중이거나 수신 중이던 채팅 및 게임 메시지는, [PartySendMessageOptions::GuaranteedDelivery](/services/playfab/multiplayer/networking/reference/enums/partysendmessageoptions)를 사용하여 전송되었더라도, 그리고 [PartyLocalEndpoint::GetEndpointStatistics()](/services/playfab/multiplayer/networking/reference/classes/PartyLocalEndpoint/methods/partylocalendpoint_getendpointstatistics)가 반환한 [PartyEndpointStatistic::CurrentlyQueuedSendMessages](/services/playfab/multiplayer/networking/reference/enums/partyendpointstatistic) 또는 [PartyEndpointStatistic::CurrentlyActiveSendMessages](/services/playfab/multiplayer/networking/reference/enums/partyendpointstatistic) 값에 더 이상 계수되지 않더라도 도착하지 않을 수 있습니다.
</Warning>

또한 연결 유형 전환 기간 중에 전송된 메시지는 [PartySendMessageOptions::SequentialDelivery](/services/playfab/multiplayer/networking/reference/enums/partysendmessageoptions)를 사용하여 전송되었더라도 순서가 잘못 도착할 수 있습니다.
타이틀은 직접 피어 연결과 이러한 PartySendMessageOptions를 사용할 때 이러한 데이터 손실 및 순서 오류 가능성에 대비해야 합니다.

PartyDeviceConnectionType::RelayServer의 연결 유형은 해당 값이 디바이스가 처음 네트워크에 참가했을 때 할당되었든 이전에 방해받은 직접 피어 연결 이후에 할당되었든 관계없이 결코 다른 유형으로 변경되지 않습니다.

## 청구 미터

직접 피어-투-피어 연결을 사용하는 네트워크에는 클라우드 릴레이 서비스를 사용하는 네트워크와 동일한 [청구 미터](/services/playfab/pricing/meters/meters#party)가 적용됩니다. 그러나 **Network egress** 및 **Party voice** 미터에는 클라우드 릴레이 서비스를 통과하는 게임 또는 음성 데이터만 계산됩니다.


## Related topics

- [PlayFab Party 개요](/ko/services/playfab/multiplayer/networking/index.md)
- [세션 템플릿 상수](/ko/services/xbox-services/multiplayer/mpsd/concepts/live-session-template-constants.md)
- [PartyDirectPeerConnectivityOptions](/ko/services/playfab/multiplayer/networking/reference/enums/partydirectpeerconnectivityoptions.md)
- [DirectPeerConnectivityOptions](/ko/services/playfab/multiplayer/networking/unity-party-api-reference/enums/partyunitydirectpeerconnectivityoptions.md)
- [PartyNetwork::GetDeviceConnectionType](/ko/services/playfab/multiplayer/networking/reference/classes/PartyNetwork/methods/partynetwork_getdeviceconnectiontype.md)
