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

# 퍼블릭 엔드포인트

> 샌드박스 내부의 서비스에 플랫폼 TLS 또는 TLS passthrough를 사용하여 공개 주소를 부여하세요.

<Note>
  `Sandbox.run(auth=...)`를 생략한 예시는 `CWSANDBOX_API_KEY`에 설정된 CoreWeave API 액세스 토큰을 사용합니다. Forge API 키 인증을 사용하려면 [시작하기](/ko/products/sandboxes/get-started#forge-api-key)의 안내에 따라 진행한 후, 생성된 `AuthHeaders`를 오퍼레이션에 전달하세요.
</Note>

이 페이지는 퍼블릭 엔드포인트의 작동 방식, 샌드박스 생성 시 선언하는 방법, 그리고 연결하는 방법을 설명합니다.

퍼블릭 엔드포인트는 샌드박스 내부에서 실행되는 서비스에 인터넷에서 클라이언트가 접근할 수 있는 주소를 제공합니다. 샌드박스를 생성할 때 요청하며, 플랫폼은 라우팅, DNS 및 네트워크 액세스를 프로비저닝합니다. 주소는 샌드박스가 실행되는 동안 샌드박스에 속합니다.

엔드포인트는 TLS가 종료되는 위치에 따라 두 가지 종류가 있습니다:

* **HTTPS**: 플랫폼은 에지에서 프로비저닝하고 갱신하는 인증서로 TLS를 종료한 다음, 요청을 일반 텍스트 HTTP로 포트에 전달합니다.
* **TLS passthrough**: 플랫폼은 [Server Name Indication (SNI)](https://en.wikipedia.org/wiki/Server_Name_Indication)를 사용하여 연결을 포트로 라우팅하며, 복호화하지 않습니다. 워크로드는 TLS를 종료하고 자체 인증서를 소유합니다.

워크로드가 개인 키를 직접 보유해야 하는 경우 TLS passthrough를 선택하세요: 상호 TLS, 인증서를 고정하는 클라이언트, 또는 HTTP가 아닌 프로토콜.

<h2 id="compare-the-two-kinds">
  두 종류 비교
</h2>

| | HTTPS | TLS passthrough |
| - | - | - |
| Terminates TLS | Platform edge | Your 워크로드 |
| Owns certificates | Platform | You |
| Carries | HTTP, WebSockets over HTTP Upgrade, and Server-Sent Events | Any protocol over TLS |
| `endpoint.kind` | `HTTPS` | `TLS_PASSTHROUGH` |
| `endpoint.auth` | `OPEN` (required) | Omit |
| 주소를 조회 | `service_urls` | `service_addresses` |

<Warning>
  Both kinds are open to the internet. The platform does not authenticate callers, so the 서비스 behind the 엔드포인트 is responsible for its own 액세스 control.
</Warning>

<h2 id="declare-an-endpoint">
  Declare an 엔드포인트
</h2>

샌드박스를 생성할 때 `services` 목록에 엔드포인트를 선언하세요. 포트는 샌드박스의 수명 동안 고정되며, 이미 실행 중인 샌드박스에 포트를 노출하는 호출은 없습니다.

서비스에 엔드포인트를 부여하려면 해당 서비스에 `visibility=PUBLIC`과 `endpoint` 값을 설정하세요. `endpoint` 값이 없는 서비스는 샌드박스 내부의 포트에서 수신하지만 공개 주소는 받지 않습니다.

HTTPS 엔드포인트의 경우 `kind=EndpointKind.HTTPS`와 `auth=EndpointAuth.OPEN`을 설정하세요:

```python theme={"system"}
from cwsandbox import (
    Endpoint,
    EndpointAuth,
    EndpointKind,
    Sandbox,
    Service,
    ServiceVisibility,
)

sandbox = Sandbox.run(
    "python3", "-m", "http.server", "8080",
    container_image="python:3.11",
    services=[
        Service(
            port=8080,
            name="web",
            visibility=ServiceVisibility.PUBLIC,
            endpoint=Endpoint(kind=EndpointKind.HTTPS, auth=EndpointAuth.OPEN),
        ),
    ],
)
```

TLS passthrough 엔드포인트의 경우 `kind=EndpointKind.TLS_PASSTHROUGH`로 설정하고 `auth`는 설정하지 않은 상태로 두세요. run하는 command는 포트 자체에서 TLS를 종료해야 합니다. 플랫폼이 연결을 복호화하지 않고 전달하기 때문입니다:

```python theme={"system"}
from cwsandbox import (
    Endpoint,
    EndpointKind,
    Sandbox,
    Service,
    ServiceVisibility,
)

sandbox = Sandbox.run(
    "python3", "/srv/serve_tls.py",
    container_image="python:3.11",
    services=[
        Service(
            port=8443,
            name="tls",
            visibility=ServiceVisibility.PUBLIC,
            endpoint=Endpoint(kind=EndpointKind.TLS_PASSTHROUGH),
        ),
    ],
)
```

하나의 샌드박스는 두 종류를 모두 혼합할 수 있습니다. `services` 엔트리마다 다음 규칙이 적용됩니다:

* **포트는 고유해야 합니다**, 그리고 설정하는 모든 이름도 고유해야 합니다. 이름은 Kubernetes container 포트 이름에 매핑되며, 고유성이 필요합니다.
* `endpoint`가 설정된 경우 **`visibility`는 `PUBLIC`이어야 합니다**, 설정되지 않은 경우에는 설정하지 않은 상태로 두어야 합니다. visibility 자체는 엔드포인트나 주소를 생성하지 않습니다.
* **`protocol`은 `TCP`이거나 설정되지 않아야 합니다.** 플랫폼은 `UDP`와 `SCTP` 엔드포인트를 거부합니다.
* **TLS passthrough의 경우 `auth`와 `request_timeout_seconds`를 생략합니다.** `0` 대신 `None`을 전달하세요. `0`은 설정된 값으로 간주되며, 플랫폼은 create call을 거부합니다.
* **플랫폼 한도는 하나의 샌드박스가 선언할 수 있는 서비스 수를 제한합니다.** Operator가 한도를 설정하며, 배포는 일반적으로 이를 5로 설정합니다.

<h2 id="read-the-assigned-address">
  부여된 주소 조회
</h2>

플랫폼이 주소를 부여합니다. 호스트 이름을 선택하거나 자체 도메인을 제공할 수 없습니다. 주소를 구성하는 대신 샌드박스에서 조회하세요. DNS 존은 클러스터마다 다르며 API 계약의 일부가 아니기 때문입니다.

TLS passthrough 주소는 `service_addresses`에 `host:port` 형식으로 도착하고, HTTPS URL은 `service_urls`에 도착합니다. 두 목록은 별도로 유지됩니다. TLS 엔드포인트는 `service_urls`에 절대 나타나지 않습니다.

```python theme={"system"}
for endpoint in sandbox.service_addresses:
    print(endpoint.port, endpoint.name, endpoint.address)
```

다음과 유사한 출력을 볼 수 있습니다:

```text theme={"system"}
8443 tls 8443-2f8d41b6-9c3e-4a17-b5d2-7e0a13c64f89.a1b2c3d4.ep2.cwsandbox.com:443
```

광고된 포트는 플랫폼의 TLS 리스너 포트이며, 샌드박스 내부에서 프로세스가 바인딩하는 포트가 아닙니다. 이 예제에서 워크로드는 `8443`에서 수신 대기하고 클라이언트는 `443`에 연결합니다.

샌드박스 시작 과정에서 두 종류의 주소는 서로 다른 시점에 확인할 수 있습니다.

* **TLS passthrough 주소는 샌드박스가 생성될 때 부여**되므로, 생성 응답에 포함되며 샌드박스가 생성 중이거나 실행 중인 동안 계속 사용할 수 있습니다.
* **HTTPS URL은 샌드박스가 `RUNNING` 상태에 도달하고** 경로에 호스트 이름이 할당될 때까지 비어 있습니다. URL이 나타나거나 사용자가 설정한 기한이 지날 때까지 `get_status()`를 반복 호출하세요.
* **어느 쪽이든 애플리케이션이 서비스 중임을 의미하지는 않습니다.** 플랫폼은 프로세스가 포트를 바인딩하기 전에 샌드박스를 실행 중으로 보고하므로, 첫 연결 시 재시도해야 합니다.

플랫폼은 샌드박스가 생성 중이거나 실행 중일 때 엔드포인트를 보고하며, 그 외 상태에서는 모두 지웁니다. 일시 중지되거나 완료된 샌드박스에는 연결 가능한 엔드포인트가 없습니다.

<h2 id="connect-to-a-tls-passthrough-endpoint">
  TLS passthrough 엔드포인트에 연결
</h2>

플랫폼은 연결을 복호화하지 않으므로 클라이언트가 받는 인증서는 워크로드가 제시하는 인증서입니다. 클라이언트에게는 두 가지가 따릅니다:

* **엔드포인트 호스트를 SNI 서버 이름으로 전송하세요.** 플랫폼은 SNI만으로 라우팅하므로 이를 생략하거나 다른 이름을 전송하는 연결은 샌드박스에 도달하지 않습니다.
* **워크로드의 인증서를 신뢰하세요.** 엔드포인트 호스트 이름은 플랫폼이 할당하므로, 직접 발급한 인증서는 해당 호스트 이름으로 발급하지 않는 한 일치하지 않습니다. 클라이언트를 설정하여 자체 인증 기관을 신뢰하거나 인증서를 고정하세요.

다음 클라이언트는 광고된 주소에 연결하면서 엔드포인트 호스트를 SNI로 전송합니다. `[ENDPOINT-ADDRESS]`를 `service_addresses`에서 조회한 주소로, `[PATH-TO-CA-CERT]`를 워크로드의 인증서에 서명한 인증 기관의 경로로 바꾸세요:

```python theme={"system"}
import socket
import ssl

address = "[ENDPOINT-ADDRESS]"  # service_addresses에서 host:port
host, port = address.rsplit(":", 1)

context = ssl.create_default_context(cafile="[PATH-TO-CA-CERT]")

with socket.create_connection((host, int(port))) as sock:
    with context.wrap_socket(sock, server_hostname=host) as tls:
        print(tls.version(), tls.getpeercert()["subject"])
```

<h2 id="endpoint-lifetime">
  엔드포인트 lifetime
</h2>

엔드포인트는 이를 소유한 샌드박스가 존재하는 한 유지됩니다:

* **샌드박스에 키가 지정되며, 파드에는 지정되지 않습니다.** 기본 파드가 재시작되더라도 주소는 동일하게 유지됩니다.
* **샌드박스를 삭제하면 엔드포인트가 제거됩니다.** 주소는 다른 샌드박스로 이동하지 않으며, 새 샌드박스는 새 주소를 받습니다.
* **샌드박스 간에 예약된 것은 없습니다.** 호스트 이름을 재사용하기 위해 보유할 수 없습니다.

<h2 id="troubleshoot-create-failures">
  create 실패 문제 해결
</h2>

요청한 엔드포인트 종류를 fleet의 러너가 지원하지 않으면, 엔드포인트가 조용히 제외된 상태로 샌드박스를 시작하는 대신 create call이 실패합니다.

| Reason | Meaning |
| - | - |
| `CWSANDBOX_TLS_PASSTHROUGH_ENDPOINTS_NOT_SUPPORTED` | 연결할 수 있는 러너가 TLS passthrough용으로 설정되어 있지 않습니다. Admin에게 러너에서 해당 기능을 활성화하도록 요청하세요. |
| `CWSANDBOX_NO_SUITABLE_RUNNER` | 샌드박스가 두 엔드포인트 종류를 모두 선언했으나, 러너 중 어느 것도 두 종류를 모두 지원하지 않습니다. response의 `unsupported_endpoint_kinds` 메타데이터에 누락된 종류가 명시되어 있습니다. |
| `CWSANDBOX_INVALID_REQUEST` | `services` entry가 [Declare an 엔드포인트](#declare-an-endpoint)의 규칙 중 하나를 위반합니다. 예: 포트 중복 또는 TLS passthrough 엔드포인트에 `auth` 설정. |
| `CWSANDBOX_NOT_IMPLEMENTED` | 요청이 아직 구현되지 않은 기능(예: `auth=TOKEN`)을 사용했습니다. |

<h2 id="related-pages">
  관련 페이지
</h2>

* [샌드박스 설정](/ko/products/sandboxes/client/guides/sandbox-configuration): 리소스, 포트, 시크릿, timeout.

* [샌드박스 아키텍처](/ko/products/sandboxes/architecture): 러너, 프로필, control plane이 상호 작용하는 방식.

* [샌드박스 라이프사이클](/ko/products/sandboxes/client/guides/sandbox-lifecycle): 샌드박스가 거치는 상태.
