> ## 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.

# 네트워크 초기화 상태 감지

> 네트워크 초기화 상태 감지

## 네트워크 초기화

이 문서를 사용하여 Microsoft Game Development Kit (GDK) 타이틀에서 네트워크 연결 및 초기화 정보를 검색하는 방법을 이해합니다. 이들은 종종 핵심 OS 컴포넌트와 네트워킹 서비스가 실행되기 전에 시작됩니다. 결과적으로 타이틀이 시작된 직후에 `WinSock`, `WinHTTP`, `BCrypt`, `WinCrypt`, `schannel`, `IPHLPAPI`를 포함한 대부분의 네트워킹 및 보안 API를 호출하려고 시도하면 예측할 수 없는 동작이 발생합니다. 이러한 동작은 예상치 못한 실패, 초기화되지 않은 반환 값, 임의의 패킷 손실, 잠재적인 메모리 손상 및 크래시를 포함할 수 있습니다.

이러한 예측할 수 없는 동작을 피하기 위해 Microsoft Game Development Kit (GDK) 타이틀은 [XNetworkingGetConnectivityHint](/reference/networking/xnetworking/functions/xnetworkinggetconnectivityhint) 및 [XNetworkingRegisterConnectivityHintChanged](/reference/networking/xnetworking/functions/xnetworkingregisterconnectivityhintchanged) 함수를 사용해야 합니다. 특히 `XNetworkingConnectivityHint::networkInitialized` 필드는 네트워크가 초기화되었는지 여부를 나타냅니다. 타이틀은 네트워킹 및 보안 API를 호출하기 전에 `networkInitialized` 필드가 `true`가 될 때까지 기다려야 합니다.

많은 미들웨어 라이브러리도 내부적으로 네트워킹 및 보안 API를 사용합니다. 네트워킹이 아닌 미들웨어조차도 텔레메트리 또는 디버깅용으로 네트워크 스택을 사용할 수 있습니다. 각각의 경우에 어떻게 해야 할지 미들웨어 제공자와 상의하세요. 미들웨어 자체가 네트워크 초기화를 기다리지 않는 경우, 네트워크가 초기화될 때까지 미들웨어 로딩을 지연시켜야 할 수 있습니다. Microsoft Game Development Kit (GDK) 내의 [XSAPI](https://learn.microsoft.com/windows/uwp/xbox-live/xsapi-flat-c) 및 [Azure PlayFab Party](/build/console-features/networking/game-mesh/playfab-party-intro-networking)와 같은 여러 라이브러리는 사용하기 전에 네트워크가 초기화될 때까지 기다려야 합니다.

## HTTP 스택 순서 지정

`xCurl`과 `libHttpClient`는 이 문서 세트에서 네트워크 초기화를 자동으로 관리하는 유일한 HTTP 라이브러리입니다. 타이틀이 다른 HTTP 스택을 사용하는 경우 시작 순서를 명시적으로 만드세요. 안전한 패턴은 다음과 같습니다.

1. 현재 연결 힌트를 쿼리하거나 연결 변경에 등록합니다.
2. `XNetworkingConnectivityHint::networkInitialized`가 `true`가 될 때까지 기다립니다.
3. `WinSock` 및 기타 네트워킹 종속성을 초기화합니다.
4. 인증서 상태에 액세스하고 신뢰를 구성합니다.
5. HTTP 스택을 만들고 요청 발행을 시작합니다.

네트워크 준비가 먼저 이루어져야 합니다. `WinSock`, 인증서 상태 또는 HTTP 상태를 너무 일찍 가져오면 표시되는 오류가 종종 근본 원인보다 나중에 나타나기 때문에 진단하기 어려운 실패를 초래할 수 있습니다.

다음 예제는 타이틀이 소유한 HTTP 스택 시작 순서의 처음 몇 단계를 보여줍니다. `WinSock`을 가져오기 직전에 `XNetworkingConnectivityHint`를 직접 쿼리합니다.

```cpp theme={null}
HRESULT InitializeNetworkingDependencies()
{
    XNetworkingConnectivityHint connectivityHint{};
    HRESULT hr = XNetworkingGetConnectivityHint(&connectivityHint);
    if (FAILED(hr))
    {
        return hr;
    }

    if (!connectivityHint.networkInitialized)
    {
        // Try again after your title receives a connectivity change notification.
        return E_PENDING;
    }

    WSADATA wsaData{};
    int winsockResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (winsockResult != 0)
    {
        return HRESULT_FROM_WIN32(winsockResult);
    }

    return S_OK;
}
```

이러한 단계가 성공한 후 HTTP 스택 객체를 만든 다음 요청을 발행하기 전에 스택 특정 신뢰 구성을 적용합니다. Schannel이 아닌 스택의 경우 디버깅 도구에 필요한 프록시 인증서를 로드하는 것이 포함될 수 있습니다.

## 일시 중지 및 재개

또한 타이틀 일시 중지/재개 주기는 `networkInitialized` 필드를 다시 `false`로 재설정합니다. 일시 중지 시 타이틀은 모든 네트워크 및 보안 컴포넌트에 대한 모든 핸들을 정리하고 모든 네트워크 작업을 중단해야 합니다. 일시 중지 시 해당 API에 대한 요구 사항에 대한 자세한 내용은 각 네트워킹 API의 개요 페이지를 참조하세요. 재개 시 타이틀은 연결을 다시 설정하고 네트워킹 또는 보안 API를 사용하려고 시도하기 전에 다시 `networkInitialized` 필드가 `true`가 될 때까지 기다려야 합니다. 재개 네트워크 초기화 경로가 초기 타이틀 시작 경로와 동일하도록 하는 것이 좋습니다. 재개 시 또는 타이틀 시작 시, 네트워크 코드를 시작하기 전에 네트워크가 초기화될 때까지 기다리세요. GameChat2 및 Azure PlayFab Party와 같이 일시 중지/재개를 인식하지 못하는 미들웨어 라이브러리는 일시 중지 시 정리되고 네트워크가 초기화될 때까지 기다린 후 재개 시 다시 초기화되어야 합니다.

xCurl을 제외한 모든 HTTP 스택은 명시적인 수명 주기 처리가 필요하다고 가정하세요. 일시 중지 또는 종료 시 새 요청 큐잉을 중지하고 진행 중인 작업을 취소하거나 배출합니다. 일시 중지에서 살아남아서는 안 되는 요청 핸들, 세션 및 소켓을 파괴합니다.

재개 시 네트워크 가동을 새로운 초기화 경로로 처리합니다. HTTP 상태를 재생성하거나 리스너를 다시 등록하기 전에 `networkInitialized`를 다시 기다립니다. 취소 가능하고 블로킹하지 않는 작업을 기반으로 하는 설계는 오래 지속되는 블로킹 호출보다 일시 중지 중에 깔끔하게 되감기 쉽습니다.

## 네트워크 초기화 테스트

네트워크 초기화는 일반적으로 재개와 타이틀 시작 시 몇 초 정도 걸리며 콘솔 유형과 사용자의 네트워크 환경에 따라 달라집니다. 개발 중에는 네트워크 초기화가 거의 즉각적입니다. 이는 타이틀의 다양한 부분이 네트워크가 초기화될 때까지 제대로 기다리지 않는 문제를 숨길 수 있습니다. 네트워크 초기화 시나리오를 테스트하려면 `xbconfig NetworkInitDelayInSeconds=30`을 사용하여 네트워크 초기화 프로세스에 임의의 지연을 추가합니다. 이 설정을 사용할 때 각 테스트 사이에 `xbapp terminate /full`을 사용하여 타이틀을 완전히 다시 시작해야 합니다. 테스트가 끝나면 `NetworkInitDelayInSeconds`를 다시 `0`으로 설정합니다.

자체 네트워킹 상태를 생성하는 HTTP 스택의 경우 테스트 커버리지에 최소한 다음 시나리오를 포함시키세요.

* Cold boot
* 요청이 활성 상태인 동안 일시 중지
* 정상 일시 중지 후 재개
* Quick Resume 또는 이에 상응하는 복원 흐름
* 일시 중지 및 재개 경계 주변의 네트워크 연결 끊김

## 네트워크 초기화 코드 예제

다음 코드 예제는 네트워크가 초기화되었는지 실시간, 안전한 방식으로 폴링하는 방법을 보여줍니다.

```cpp theme={null}

bool IsNetworkInitialized()
{
    XNetworkingConnectivityHint connectivityHint;
    if (SUCCEEDED(XNetworkingGetConnectivityHint(&connectivityHint)))
    {
        return connectivityHint.networkInitialized;
    }
    return false;
}

```

다음 코드 예제는 타이틀이 네트워크가 초기화될 때까지 블로킹하는 방법을 보여줍니다.

```cpp theme={null}
static
void
NetworkConnectivityHintChangedCallback(
    _In_ void* context,
    _In_ const XNetworkingConnectivityHint* connectivityHint
    )
{
    HANDLE networkInitializedEvent = static_cast<HANDLE>(context);
    if (connectivityHint->networkInitialized)
    {
        (void)SetEvent(networkInitializedEvent);
    }
}

HRESULT EnsureNetworkInitialized()
{
    HRESULT hr = S_OK;
    XNetworkingConnectivityHint connectivityHint;
    XTaskQueueHandle queue;

    hr = XTaskQueueCreate(XTaskQueueDispatchMode::Immediate, XTaskQueueDispatchMode::Immediate, &queue);
    if (SUCCEEDED(hr))
    {
        // Use the new XNetworking APIs to check if the network is initialized.
        hr = XNetworkingGetConnectivityHint(&connectivityHint);
        if (SUCCEEDED(hr))
        {
            if (!connectivityHint.networkInitialized)
            {
                // The network isn't initialized. Wait until the network becomes initialized.
                HANDLE networkInitializedEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
                if (networkInitializedEvent != nullptr)
                {
                    XTaskQueueRegistrationToken token;
                    hr = XNetworkingRegisterConnectivityHintChanged(queue, networkInitializedEvent, NetworkConnectivityHintChangedCallback, &token);
                    if (SUCCEEDED(hr))
                    {
                        DWORD result = WaitForSingleObjectEx(networkInitializedEvent, INFINITE, FALSE);
                        if (result != WAIT_OBJECT_0)
                        {
                            hr = HRESULT_FROM_WIN32(GetLastError());
                        }

                        XNetworkingUnregisterConnectivityHintChanged(token, true);
                    }

                    CloseHandle(networkInitializedEvent);
                }
                else
                {
                    hr = HRESULT_FROM_WIN32(GetLastError());
                }
            }
        }

        XTaskQueueCloseHandle(queue);
    }

    return hr;
}

```

## 네트워크 정보

Microsoft Game Development Kit (GDK) 타이틀의 네트워크 정보는 [XNetworkingGetConnectivityHint](/reference/networking/xnetworking/functions/xnetworkinggetconnectivityhint) API로 검색할 수 있습니다.

[XNetworkingGetConnectivityHint](/reference/networking/xnetworking/functions/xnetworkinggetconnectivityhint) API는 디바이스 전체 정보, 네트워크 연결 수준, 데이터 제한, 유선 대 무선 연결 유형, 네트워크 초기화 여부를 반환합니다. 이는 현재 정보를 즉시 반환하는 실시간, 안전한 API입니다. [XNetworkingRegisterConnectivityHintChanged](/reference/networking/xnetworking/functions/xnetworkingregisterconnectivityhintchanged) 및 [XNetworkingUnregisterConnectivityHintChanged](/reference/networking/xnetworking/functions/xnetworkingunregisterconnectivityhintchanged) 함수로 변경을 수신할 수 있습니다.

다음 코드 예제는 [XNetworkingGetConnectivityHint](/reference/networking/xnetworking/functions/xnetworkinggetconnectivityhint) 함수를 사용하여 현재 네트워크 상태에 대한 정보를 쿼리하는 방법을 보여줍니다.

```cpp theme={null}

XNetworkingConnectivityHint connectivityHint;
if (SUCCEEDED(XNetworkingGetConnectivityHint(&connectivityHint)))
{
    printf(L"network initialized %u\n", connectivityHint.networkInitialized);
    printf(L"network connectivity level hint %u\n", connectivityHint.connectivityLevel);
    printf(L"network connectivity cost hint %u\n", connectivityHint.connectivityCost);
    printf(L"network approaching data limit %u\n", connectivityHint.approachingDataLimit);
    printf(L"network over data limit %u\n", connectivityHint.overDataLimit);
    printf(L"device is roaming %u\n", connectivityHint.roaming);
    switch (connectivityHint.ianaInterfaceType) {
    case IF_TYPE_ETHERNET_CSMACD:
        printf(L"network type is wired\n");
            break;
    case IF_TYPE_IEEE80211:
        printf(L"network type is wireless\n");
        break;
    case IF_TYPE_WWANPP:
    case IF_TYPE_WWANPP2:
        printf(L"network type is broadband\n");
        break;
    default:
        printf(L"network type is unusually esoteric %u\n", connectivityHint.connectivityLevel);
        break;
    }
}

```

## 네트워크 연결 모범 사례

`XNetworkingConnectivityHint::networkInitialized` 필드를 제외하고 반환된 [XNetworkingConnectivityHint](/reference/networking/xnetworking/structs/xnetworkingconnectivityhint) 구조체의 필드는 힌트입니다. 이들은 디바이스에서 관찰된 네트워크 트래픽의 휴리스틱을 기반으로 하여 디바이스가 현재 네트워크 상태에 대해 최선을 다한 추측입니다.

`XNetworkingConnectivityLevelHint`의 상태는 타이틀의 연결 로직을 단순화하기 위한 일반적인 네트워크 수준 근사치를 나타냅니다. 타이틀은 `XNetworkingConnectivityLevelHint::None`이 네트워크 매체 연결 해제 및 네트워크 환경이 몇 분 동안 변경되지 않은 정상 상태에서 전반적인 연결 부족을 반영할 것으로 예상할 수 있습니다. 다른 상태는 특정 타이틀 엔드포인트에 대한 연결이 있는지 여부를 나타내지 않습니다.

결과적으로 네트워크 초기화를 기다린 후 `XNetworkingConnectivityHint::connectivityLevelHint` 필드의 상태와 관계없이 `WinSock` 및/또는 `WinHTTP`를 사용하여 엔드포인트에 연결을 시도하는 것이 좋습니다. 나중에 이러한 API가 실패하면 UI 및 진단 보고 목적으로 [XNetworkingGetConnectivityHint](/reference/networking/xnetworking/functions/xnetworkinggetconnectivityhint) API를 사용하는 것이 좋습니다. 그런 다음 다시 시도하기 전에 네트워크 연결 수준의 변경을 기다려야 합니다.

## 고급 네트워크 정보 검색

대부분의 Microsoft Game Development Kit (GDK) 타이틀은 IP 주소와 같은 네트워크 및 기본 네트워크 정보에 대한 상태를 검색하기 위해 `WinSock` API와 함께 [XNetworkingGetConnectivityHint](/reference/networking/xnetworking/functions/xnetworkinggetconnectivityhint) API를 사용해야 합니다. 더 많은 정보가 필요한 경우 GDK에서 저수준 [IP Helper API](https://learn.microsoft.com/windows/desktop/IpHlp/ip-helper-start-page)를 사용할 수 있습니다.

일반적으로 Microsoft Game Development Kit (GDK)의 `IP Helper` API는 Win32 프로그램에서 이 API를 사용하는 방식과 동일한 방식으로 작업합니다.

1. 소스 파일에서 `#include <winsock2.h>` 뒤에 `#include <iphlpapi.h>`를 추가합니다.

2. `Ws2_32.lib` 및 `Iphlpapi.lib`에 직접 링크하는 대신 `XGamePlatform.lib`에 링크합니다.

Microsoft Game Development Kit (GDK) 타이틀에서는 `WINAPI\_PARTITION\_GAMES` API 계열 아래의 API만 작동합니다.

XBOX 콘솔에서는 기본 플랫폼 추상화로 인해 `IP Helper` API를 사용할 때 특정 정보가 정확하지 않습니다. 여기에는 다음이 포함되지만 이에 국한되지 않습니다.

* MAC 주소는 항상 `AA-AA-AA-AA-AA-AA`입니다.
* 모든 인터페이스는 기본 네트워크 연결 유형과 관계없이 항상 유선 인터페이스로 보고합니다. 실제 인터페이스 유형은 [XNetworkingGetConnectivityHint](/reference/networking/xnetworking/functions/xnetworkinggetconnectivityhint)에서만 검색할 수 있습니다.

## 지원되지 않는 네트워크 연결 API

다음 네트워크 연결 API는 Microsoft Game Development Kit (GDK) 타이틀에서 지원되지 않으며, 대신 [XNetworkingGetConnectivityHint](/reference/networking/xnetworking/functions/xnetworkinggetconnectivityhint) API를 사용하여 네트워크 연결을 결정해야 합니다.

* [Windows.Networking.Connectivity Namespace](https://learn.microsoft.com/uwp/api/windows.networking.connectivity)

* [Network List Manager](https://learn.microsoft.com/windows/desktop/nla/portal)

## 참고 항목

[XNetworkingGetConnectivityHint](/reference/networking/xnetworking/functions/xnetworkinggetconnectivityhint)

[XNetworkingRegisterConnectivityHintChanged](/reference/networking/xnetworking/functions/xnetworkingregisterconnectivityhintchanged)

[XNetworkingUnregisterConnectivityHintChanged](/reference/networking/xnetworking/functions/xnetworkingunregisterconnectivityhintchanged)

[Windows Sockets 2 (Winsock)](https://learn.microsoft.com/windows/desktop/WinSock/windows-sockets-start-page-2)

[Windows HTTP Services (WinHTTP)](https://learn.microsoft.com/windows/desktop/winhttp/winhttp-start-page)

[IP Helper API](https://learn.microsoft.com/windows/desktop/IpHlp/ip-helper-start-page)


## Related topics

- [선호 로컬 UDP 멀티플레이어 포트 네트워킹 API](/ko/build/console-features/networking/game-mesh/preferred-local-udp-multiplayer-port-networking.md)
- [GDK로 XBOX 콘솔에서 네트워킹](/ko/build/console-features/networking/index.md)
- [XNetworkingGetConnectivityHint](/ko/reference/networking/xnetworking/functions/xnetworkinggetconnectivityhint.md)
- [Microsoft Game Development Kit 네트워킹 소개](/ko/build/console-features/networking/introduction-networking.md)
- [Game Saves 오프라인 모드](/ko/services/playfab/player-progression/game-saves/offline.md)
