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

# 원격 함수

> 함수 데코레이터를 사용하여 샌드박스 내에서 Python 함수를 실행합니다.

이 예시에서는 `CWSANDBOX_API_KEY`에 저장된 CoreWeave API 액세스 토큰을 사용합니다. Forge API 키 인증에 대해서는 [시작하기](/ko/products/sandboxes/get-started)를 참조하세요. CKS 요구 사항은 [배치 모드](/ko/products/sandboxes/placement)를 참조하세요.

이 가이드에서는 샌드박스에서 Python 함수를 실행하는 `@session.function()` 데코레이터를 다룹니다. 샌드박스 라이프사이클을 직접 관리하지 않고 개별 Python 연산을 격리된 환경으로 이전하려는 개발자를 대상으로 하며, 원격 함수를 정의하는 방법, API에서 지원하는 인수 및 반환 유형, 그리고 이 API가 적합한 상황을 설명합니다.

<h2 id="overview">
  개요
</h2>

함수 데코레이터 API를 사용하면 격리된 샌드박스 컨테이너에서 Python 함수를 실행할 수 있습니다. 호출 코드를 단순하게 유지하면서 개별 Python 작업을 원격으로 실행하려면 이 API를 사용하세요:

```python theme={"system"}
import cwsandbox
from cwsandbox import SandboxDefaults

with cwsandbox.Session(SandboxDefaults(container_image="python:3.11")) as session:
    @session.function()
    def compute(x: int, y: int) -> int:
        return x + y

    # 샌드박스에서 실행
    result = compute.remote(2, 3).result()
    print(result)  # 5
```

<h2 id="basic-usage">
  기본 사용
</h2>

<h3 id="define-functions">
  함수 정의
</h3>

`@session.function()` 데코레이터를 사용해 함수를 정의하세요:

```python theme={"system"}
@session.function()
def process_data(data: dict) -> dict:
    # 코드가 샌드박스 내부에서 실행됩니다
    import pandas as pd
    df = pd.DataFrame(data)
    return {"mean": df["value"].mean()}
```

<h3 id="call-functions">
  함수 호출
</h3>

데코레이터가 적용된 함수에서 `.remote()`를 호출하여 샌드박스에서 실행하세요:

```python theme={"system"}
# OperationRef를 즉시 반환합니다
ref = compute.remote(2, 3)

# 결과가 나올 때까지 대기합니다
result = ref.result()

# 한 줄로 작성
result = compute.remote(2, 3).result()
```

<h2 id="execution-methods">
  실행 메서드
</h2>

<h3 id="run-in-parallel-with-map">
  map()으로 병렬 실행하기
</h3>

여러 입력을 대상으로 실행합니다.

```python theme={"system"}
@session.function()
def square(x: int) -> int:
    return x * x

# 각 입력에 대해 실행
refs = square.map((x,) for x in range(10))

# 모든 결과 수집
from cwsandbox import results
all_results = results(refs)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
```

여러 인수를 위한 튜플 사용:

```python theme={"system"}
@session.function()
def add(x: int, y: int) -> int:
    return x + y

# 각 튜플은 언패킹되어 인수로 전달됩니다
refs = add.map([(1, 2), (3, 4), (5, 6)])
all_results = results(refs)  # [3, 7, 11]
```

<h3 id="run-locally-with-local">
  local()로 로컬에서 실행
</h3>

샌드박스 없이 로컬에서 실행할 수 있으며, 테스트에 유용합니다:

```python theme={"system"}
# 샌드박스를 생성하지 않고 현재 프로세스에서 실행
result = compute.local(2, 3)
print(result)  # 5
```

<h2 id="argument-and-return-types">
  인수 및 반환 값 유형
</h2>

원격 함수는 인수와 반환 값을 JSON으로 전송합니다. 따라서 둘 다 JSON으로 직렬화할 수 있는 값이어야 하며, 딕셔너리, 목록, 문자열, 숫자, 불리언, `None`을 사용할 수 있습니다.

```python theme={"system"}
@session.function()
def process(data: dict) -> dict:
    return {"result": data["value"] * 2}
```

JSON으로 표현할 수 없는 인수를 전달하면 샌드박스가 시작되기 전에 호출에서 `TypeError` 예외가 발생합니다.

```text title="Example output" theme={"system"}
TypeError: Function arguments are not JSON-serializable: Object of type ndarray is not JSON serializable
```

JSON으로 표현할 수 없는 반환 값도 같은 방식으로 실패하며, `return value is not JSON-serializable` 메시지가 표시됩니다.

JSON 객체는 문자열 키만 지원합니다. 정수, 부동소수점 또는 불리언을 키로 사용하는 딕셔너리는 변환되지 않고 거부됩니다. 따라서 샌드박스에서 함수가 받는 값의 유형은 전달한 값의 유형과 항상 일치합니다.

NumPy 배열, pandas DataFrame 또는 맞춤형 클래스 인스턴스를 사용하려면 함수를 호출하기 전에 JSON 호환 값으로 변환한 다음, 함수 내부에서 다시 원래 형태로 복원하세요.

```python theme={"system"}
@session.function()
def array_mean(values: list[float]) -> float:
    from statistics import fmean
    return fmean(values)

result = array_mean.remote([1.0, 2.0, 3.0, 4.0, 5.0]).result()  # 3.0
```

클라이언트는 함수를 실행하기 전에 아무것도 설치하지 않습니다. 함수가 임포트하는 라이브러리(예: NumPy)는 모두 컨테이너 이미지에 미리 포함되어 있어야 합니다.

데이터가 너무 커서 JSON으로 전달할 수 없다면, 샌드박스가 접근할 수 있는 저장소에 데이터를 저장하고 그 참조를 대신 전달하세요. 자세한 내용은 [파일 작업](/ko/products/sandboxes/client/guides/file-operations)을 참조하세요.

<h2 id="closures-and-globals">
  클로저와 전역 변수
</h2>

<h3 id="closure-variables">
  클로저 변수
</h3>

함수는 자신을 둘러싼 범위의 변수를 캡처합니다:

```python theme={"system"}
multiplier = 10

@session.function()
def multiply(x: int) -> int:
    return x * multiplier  # 'multiplier'를 캡처합니다

result = multiply.remote(5).result()  # 50
```

<h3 id="global-variables">
  전역 변수
</h3>

데코레이터는 참조된 전역 변수를 함수와 함께 직렬화합니다.

```python theme={"system"}
CONFIG = {"threshold": 0.5}

@session.function()
def check_value(x: float) -> bool:
    return x > CONFIG["threshold"]

result = check_value.remote(0.7).result()  # True
```

캡처된 클로저 변수와 전역 변수는 인수 및 반환 값과 마찬가지로 JSON 형식으로 샌드박스에 전송됩니다. 함수가 JSON으로 표현할 수 없는 값을 캡처하면, 전달한 인수가 모두 유효하더라도 그 값 때문에 호출이 실패합니다.

<h2 id="container-image">
  컨테이너 이미지
</h2>

특정 함수의 컨테이너 이미지를 재정의하세요:

```python theme={"system"}
@session.function(container_image="pytorch/pytorch:latest")
def train_model(data: dict) -> dict:
    import torch
    # GPU 트레이닝 코드
    return {"loss": 0.01}
```

<h2 id="error-handling">
  오류 처리
</h2>

함수에서 발생한 예외는 호출자에게 전파됩니다.

```python theme={"system"}
@session.function()
def failing_function() -> None:
    raise ValueError("Something went wrong")

try:
    failing_function.remote().result()
except Exception as e:
    print(f"Function failed: {e}")
```

<h2 id="when-to-use-functions-compared-to-sandboxes">
  함수와 샌드박스 중 언제 사용할지
</h2>

워크로드에 함수 데코레이터 API와 샌드박스 API 중 어느 것이 더 적합한지 결정하려면 다음 table을 사용하세요.

| 사용 사례 | 권장 API |
| - | - |
| 단순한 Python 연산 | 함수 데코레이터 |
| Map/reduce over data | 함수 데코레이터 |
| 대화형 워크플로, 여러 명령어 | 샌드박스 |
| 스트리밍 출력 | 샌드박스 |
| 파일 조작 | 샌드박스 |
| 장시간 실행되는 프로세스 | 샌드박스 |

<h2 id="limitations">
  제한 사항
</h2>

함수 API는 의도적으로 단순하게 설계되었습니다. 복잡한 워크플로의 경우:

* **재시도 및 백오프**: 호출하는 코드에서 구현하세요.
* **작업 의존성 및 DAG**: Airflow 또는 Prefect와 같은 워크플로 오케스트레이터를 사용하세요.
* **복잡한 스케줄링**: 샌드박스 API를 직접 사용하세요.

<h2 id="complete-example">
  전체 예제
</h2>

다음 예시는 이 가이드의 개념을 결합합니다. 단일 및 병렬 실행, 그리고 인수와 반환 값이 JSON으로 전달되는 계산을 보여줍니다:

```python theme={"system"}
import cwsandbox
from cwsandbox import SandboxDefaults, results

defaults = SandboxDefaults(
    container_image="python:3.11",
    tags=("remote-functions-demo",),
)

with cwsandbox.Session(defaults=defaults) as session:
    @session.function()
    def square(x: int) -> int:
        return x * x

    # 인수는 리스트이고 결과는 float이므로 둘 다 JSON으로 전달할 수 있습니다
    @session.function()
    def array_mean(values: list[float]) -> float:
        from statistics import fmean
        return fmean(values)

    # 단일 실행
    result = square.remote(7).result()
    print(f"7 squared: {result}")

    # 병렬 실행
    refs = square.map((x,) for x in range(5))
    all_results = results(refs)
    print(f"Squares: {all_results}")

    # JSON 호환 연산
    mean = array_mean.remote([1.0, 2.0, 3.0, 4.0, 5.0]).result()
    print(f"Array mean: {mean}")
```
