> For the complete documentation index, see [llms.txt](https://docs.overdare.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.overdare.com/korean/development/api-reference/classes/remotefunction.md).

# RemoteFunction

RemoteFunction : `Instance`

## Overview

RemoteFunction은 클라이언트와 서버 간 요청과 응답 처리를 위해 제공되는 객체로, 동기 양방향 통신을 지원합니다.

이 인스턴스는 서버와 클라이언트 양쪽에서 접근할 수 있어야 하므로, ReplicatedStorage나 Workspace처럼 공유 가능한 위치에 배치하는 것이 적절합니다.

호출한 스크립트는 대상 콜백이 값을 반환할 때까지 일시 중단(yield)되며, 반환값은 여러 개를 동시에 받을 수 있습니다.

클라이언트가 전송한 인자는 엔진이 검사하지 않고 OnServerInvoke에 설정된 함수로 그대로 전달됩니다. 타입과 값의 범위 검증은 서버에서 직접 수행해야 합니다.

서로 다른 클라이언트 간의 직접 통신은 지원하지 않습니다. 클라이언트 간에 값을 전달하려면 서버를 경유해야 합니다.

반환값을 받을 필요가 없는 통신에는 RemoteEvent를 사용하는 것이 더 적합합니다.

## Properties

### OnClientInvoke

`Value`

서버에서 InvokeClient 메서드가 호출될 때 대상 클라이언트에서 실행할 함수를 지정하는 속성입니다. 클라이언트의 LocalScript에서 설정합니다.

이벤트가 아니므로 Connect()가 아닌 대입 연산으로 설정하며, 하나의 함수만 설정할 수 있습니다. 자세한 동작과 주의사항은 Callback 항목의 OnClientInvoke을 참고하세요.

#### Code Samples

### OnServerInvoke

`Value`

클라이언트에서 InvokeServer 메서드가 호출될 때 서버에서 실행할 함수를 지정하는 속성입니다. 서버의 Script에서 설정합니다.

이벤트가 아니므로 Connect()가 아닌 대입 연산으로 설정하며, 하나의 함수만 설정할 수 있습니다. 자세한 동작과 주의사항은 Callback 항목의 OnServerInvoke을 참고하세요.

#### Code Samples

## Methods

### InvokeClient

서버에서 특정 클라이언트의 OnClientInvoke에 설정된 함수를 실행하고, 그 반환값을 받을 때 사용하는 메서드입니다.

대상 클라이언트를 지정하기 위해 Player 인자를 반드시 전달해야 합니다.

이 메서드는 Script에서만 호출할 수 있습니다. 클라이언트의 LocalScript에서 호출하면 오류가 발생합니다.

**주의사항**

이 메서드는 서버가 클라이언트의 응답에 의존하게 만들기 때문에 사용을 권장하지 않습니다.

* 클라이언트에서 발생한 오류가 **서버로 전파되어** 서버 코드가 중단됩니다.
* 호출 도중 대상 클라이언트의 연결이 해제되면 오류가 발생합니다.
* 클라이언트가 값을 반환하지 않으면 **서버가 재개되지 않습니다.**
* OnClientInvoke에 함수가 설정되어 있지 않아도 서버가 재개되지 않습니다.

결과를 받아야 하는 경우에는 RemoteEvent의 FireClient()로 요청을 전달하고, 클라이언트가 별도의 RemoteEvent로 결과를 전송하는 방식을 사용하는 것이 안전합니다.

#### Parameters

| `Player` Player | <p>클라이언트의 OnClientInvoke를 실행할 Player입니다.</p><p>다음의 경우 호출 시점에 오류가 발생하며, OnClientInvoke에 설정된 함수는 실행되지 않습니다.</p><ul><li>nil인 경우</li><li>Player가 아닌 Instance인 경우</li><li>Instance가 아닌 값인 경우</li><li>이미 퇴장한 Player의 참조인 경우</li></ul> |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `any` ...       | <p>OnClientInvoke에 설정된 함수로 전달되는 인자입니다.</p><ul><li>InvokeServer와 동일한 전달 제한이 적용됩니다.</li></ul>                                                                                                                                     |

#### Return

| `Tuple` | <p>OnClientInvoke에 설정된 함수가 반환한 값입니다.</p><ul><li>여러 개의 값을 동시에 반환받을 수 있습니다.</li><li>설정된 함수에 return이 없는 경우 nil을 반환받습니다.</li></ul> |
| ------- | ------------------------------------------------------------------------------------------------------------------------------ |

#### Code Samples

```lua
-- Script
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local S2C_GetSetting = ReplicatedStorage:WaitForChild("S2C_GetSetting")

local function RequestSetting(player, settingKey)
    -- 호출 직전에 대상 Player가 아직 접속 중인지 확인합니다
    if player.Parent ~= Players then
        return
    end

    local Value = S2C_GetSetting:InvokeClient(player, settingKey) -- Passing arguments
    print("[InvokeClient]", player.Name, " / Value : ", Value)
end


-----------------------------------------------------------------------------------
-- LocalScript
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local S2C_GetSetting = ReplicatedStorage:WaitForChild("S2C_GetSetting")

local function OnGetSetting(settingKey)
    return SettingTable[settingKey]
end
S2C_GetSetting.OnClientInvoke = OnGetSetting
```

### InvokeServer

클라이언트에서 서버의 OnServerInvoke에 설정된 함수를 실행하고, 그 반환값을 받을 때 사용하는 메서드입니다.

이 메서드는 LocalScript에서만 호출할 수 있습니다. 서버의 Script에서 호출하면 오류가 발생합니다.

OnServerInvoke에 함수가 설정되어 있지 않은 상태에서 이 메서드를 호출하면, 오류나 시간 초과 없이 호출한 스크립트가 재개되지 않습니다.

OnServerInvoke에 설정된 함수에서 오류가 발생하면 해당 오류가 호출한 클라이언트로 전파되므로, pcall()로 감싸 처리할 수 있습니다.

#### Parameters

| `any` ... | <p>OnServerInvoke에 설정된 함수의 두 번째 인자부터 전달되는 값입니다. 첫 번째 인자 player는 서버가 직접 지정합니다.</p><ul><li>number, boolean, string, table 등 Luau의 기본 자료형을 전달할 수 있습니다.</li><li>Instance 같은 객체도 전달할 수 있습니다.</li><li>모든 데이터 타입이 완전히 지원되는 것은 아니기 때문에, 사용 전 실제 동작을 확인해보는 것이 좋습니다.</li><li>function은 전달되지 않습니다. 인자로 직접 전달하면 nil이 되고, table의 값으로 담으면 해당 키가 함께 사라집니다.</li><li>ServerStorage 하위처럼 복제되지 않는 Instance도 같은 방식으로 전달되지 않습니다.</li><li>table은 복사본으로 전달되며 메타테이블은 전달되지 않습니다.</li></ul> |
| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

#### Return

| `Tuple` | <p>OnServerInvoke에 설정된 함수가 반환한 값입니다.</p><ul><li>여러 개의 값을 동시에 반환받을 수 있습니다.</li><li>설정된 함수에 return이 없는 경우 nil을 반환받습니다.</li><li>인자에 적용되는 전달 제한이 반환값에도 동일하게 적용됩니다.</li><li>StreamingEnabled가 활성화된 경우, 서버가 반환한 Instance가 클라이언트에 아직 전송되지 않았다면 nil을 반환받습니다.</li></ul> |
| ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

#### Code Samples

```lua
-- LocalScript
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local C2S_BuyItem = ReplicatedStorage:WaitForChild("C2S_BuyItem")

local ItemId = 1001
local Amount = 2

local IsSuccess, Balance = C2S_BuyItem:InvokeServer(ItemId, Amount) -- Passing arguments
print("[InvokeServer]", "IsSuccess : ", IsSuccess, " / Balance : ", Balance)


-----------------------------------------------------------------------------------
-- Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local C2S_BuyItem = ReplicatedStorage:WaitForChild("C2S_BuyItem")

local function OnBuyItem(player, itemId, amount)
    print("[OnBuyItem]", player.Name, " / itemId : ", itemId, " / amount : ", amount)
    return true, 500
end
C2S_BuyItem.OnServerInvoke = OnBuyItem
```

## Events

## Callback

### OnServerInvoke

RemoteFunction 인스턴스에서 InvokeServer 메서드가 호출되면 서버에서 OnServerInvoke에 설정된 함수가 실행되며, 호출 시 전달된 인자는 설정된 함수의 두 번째 인자부터 그대로 전달됩니다.

OnServerInvoke는 이벤트가 아니라 함수를 담는 프로퍼티이므로 Connect()를 사용할 수 없으며, 대입 연산으로 설정합니다.

**주의사항**

* 하나의 함수만 설정할 수 있으며, 여러 번 설정한 경우 **마지막에 설정한 함수**만 실행됩니다.
* 함수가 아닌 값을 설정해도 설정 시점에는 오류가 발생하지 않습니다. InvokeServer가 호출되는 시점에 오류가 발생합니다.
* 첫 번째 인자 player는 서버가 요청 경로에서 직접 확인한 값이므로 권한 검증의 기준으로 사용할 수 있습니다. 두 번째 인자부터는 **클라이언트가 전송한 값이므로 신뢰할 수 없습니다.**
* 클라이언트는 Instance처럼 보이는 table을 전송할 수 있으므로, typeof()로 실제 타입을 확인해야 합니다.
* NaN은 모든 크기 비교가 false이므로 범위 검사를 통과합니다. Inf는 상한 검사가 없으면 통과합니다.
* 설정된 함수 안에서 오래 대기하면 호출한 클라이언트도 그만큼 함께 대기합니다.

#### Parameters

| `Player` Player   | InvokeServer를 호출한 클라이언트의 Player입니다. 클라이언트가 전송한 값이 아니라 서버가 요청 경로에서 확인해 전달하는 값입니다.                                                                                     |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Tuple` Arguments | <p>InvokeServer 호출 시 전달된 인자입니다.</p><ul><li>엔진이 검사하지 않고 그대로 전달하므로, 타입과 값의 범위를 직접 검증해야 합니다.</li><li>table로 받은 인자는 복사본이므로, 이 함수에서 수정해도 호출한 쪽의 원본에는 반영되지 않습니다.</li></ul> |

#### Return

| `Tuple` | <p>InvokeServer를 호출한 클라이언트로 전달할 반환값입니다.</p><ul><li>여러 개의 값을 동시에 반환할 수 있습니다.</li><li>return을 작성하지 않으면 호출한 쪽은 nil을 받습니다.</li><li>인자에 적용되는 전달 제한이 반환값에도 동일하게 적용됩니다.</li></ul> |
| ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

#### Code Samples

```lua
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local C2S_BuyItem = ReplicatedStorage:WaitForChild("C2S_BuyItem")

local function OnBuyItem(player, item, amount)
    -- 권한 확인
    if not CanPurchase(player) then
        return false
    end

    -- 타입과 구조 확인
    if typeof(item) ~= "Instance" or not item:IsA("Tool") then
        return false
    end

    -- 값의 범위 확인
    if typeof(amount) ~= "number" then
        return false
    end
    if amount ~= amount then -- NaN
        return false
    end
    if math.abs(amount) == math.huge then -- Inf
        return false
    end
    if amount < 1 or amount > 99 then
        return false
    end

    return Purchase(player, item, amount)
end
C2S_BuyItem.OnServerInvoke = OnBuyItem -- Connect가 아닌 대입으로 설정
```

### OnClientInvoke

RemoteFunction 인스턴스에서 InvokeClient 메서드가 호출되면 대상 클라이언트에서 OnClientInvoke에 설정된 함수가 실행되며, 호출 시 전달된 인자는 설정된 함수로 그대로 전달됩니다.

OnClientInvoke는 이벤트가 아니라 함수를 담는 프로퍼티이므로 Connect()를 사용할 수 없으며, 대입 연산으로 설정합니다.

**주의사항**

* 하나의 함수만 설정할 수 있으며, 여러 번 설정한 경우 **마지막에 설정한 함수**만 실행됩니다.
* 이 함수에서 발생한 오류는 InvokeClient를 호출한 **서버로 전파됩니다.**
* 함수가 아닌 값을 설정해도 설정 시점에는 오류가 발생하지 않습니다. InvokeClient가 호출되는 시점에 오류가 발생하며, 이 오류도 서버로 전파됩니다.
* 이 함수가 값을 반환하지 않고 대기하면 서버가 함께 대기합니다.

#### Parameters

| `Tuple` Arguments | <p>InvokeClient 호출 시 전달된 인자입니다. Player 인자는 제외되고 그 뒤의 인자부터 전달됩니다.</p><ul><li>table로 받은 인자는 복사본이므로, 이 함수에서 수정해도 호출한 쪽의 원본에는 반영되지 않습니다.</li></ul> |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |

#### Return

| `Tuple` | <p>InvokeClient를 호출한 서버로 전달할 반환값입니다.</p><ul><li>여러 개의 값을 동시에 반환할 수 있습니다.</li><li>return을 작성하지 않으면 호출한 쪽은 nil을 받습니다.</li></ul> |
| ------- | ----------------------------------------------------------------------------------------------------------------------------- |

#### Code Samples

```lua
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local S2C_GetSetting = ReplicatedStorage:WaitForChild("S2C_GetSetting")

local SettingTable = { Volume = 80, Quality = "High" }

local function OnGetSetting(settingKey)
    return SettingTable[settingKey]
end
S2C_GetSetting.OnClientInvoke = OnGetSetting -- Connect가 아닌 대입으로 설정
```

## See also

{% content-ref url="/pages/rznBJB0DomrXzxffvYtu" %}
[서버-클라이언트 통신](/korean/manual/script-manual/events-and-communication/remoteevent.md)
{% endcontent-ref %}
