---
type: reference
title: 위젯 메서드와 이벤트
summary: Caputchin 위젯 요소에서 호출할 수 있는 모든 메서드와 그것들이 내는 모든 이벤트를, 각각의 정확한 페이로드, 어떤 요소가 노출하는지, 그리고 언제 유효한지와 함께.
---

Caputchin 위젯은 두 커스텀 요소를 내고, 당신의 페이지는 두 방향으로 그것들과 상호작용합니다: 요소를 몰아가려고 그 위에서 **메서드를 호출**하고, 반응하려고 그것이 내는 **이벤트를 수신 대기**합니다. 이 페이지는 두 표면 모두의 빠짐없는 레퍼런스입니다.

모든 이벤트는 `bubbles: true`와 `composed: true`로 디스패치된 `CustomEvent`라, 위젯의 섀도 DOM을 탈출하고 당신은 요소(또는 어떤 조상)에서 직접 그것을 수신 대기할 수 있습니다. 데이터는 늘 `event.detail`에 있습니다.

## 한눈에 보는 두 요소

| 요소 | 목적 | 메서드 |
|---|---|---|
| `<caputchin-widget>` | 검증만(proof-of-work / 체크박스). | `start()` |
| `<caputchin-game>` | 게임 호스트, 선택적 검증과 함께. | `pass()`, `fail()` |

체크박스 위젯은 `start()`만 가집니다; 그것은 `pass()` / `fail()`을 노출하지 **않습니다**. 게임 호스트는 `start()`가 없습니다(그 라운드는 인라인은 마운트 시, 모달 / 풀스크린은 첫 다이얼로그 열기 시 라이브가 됩니다). 두 요소 모두 `start`, `pass`, `error`, `degraded`를 냅니다; 게임 호스트는 추가로 `dialog-shown`과 `dialog-hidden`을 냅니다. 커버리지는 아래 [이벤트 표](#events)에 있습니다.

## 메서드

### `start()` (`<caputchin-widget>` only)

검증을 즉시 시작합니다. 그 목적은 **수동 트리거**입니다: 요소가 `trigger="manual"`을 가질 때, 내장 체크박스 대신 당신 자신의 제스처(예를 들어, 당신 폼의 제출에서)에서 proof-of-work 풀이를 발사하려고 `start()`를 호출합니다. 기본 `auto` / `click` 트리거에서는 요소가 자기 활성화를 배선하니, 이것을 호출하지 않습니다.

```js
const widget = document.querySelector("caputchin-widget");
widget.start();
```

게임 호스트는 `start()`가 없습니다. 직접-몰아가기 전체 안내는 [수동 모드](/docs/custom-game-development/manual-mode)를 보세요.

### `pass(payload)` (`<caputchin-game>` only)

검증 게이트를 해제합니다: 방문자가 성공했습니다. **`trigger="manual"`일 때만 유효**; 비수동 게임에서 그것을 호출하면 코드 `invalid-call`로 `error`를 냅니다. 첫 `pass()`가 판정을 사용하고 **잠급니다**; 나중 호출은 조용히 무시됩니다(세션당 한 라운드).

```js
const widget = document.querySelector("caputchin-game");
widget.pass({ trace: roundRecord });
```

| `payload` 필드 | 타입 | 의미 |
|---|---|---|
| `trace` | `string` | 당신의 게임이 내는 불투명 라운드 기록. 게이트된 라운드에서는 서버가 권위 있는 판정을 도출하려고 그것을 리플레이합니다; 게이트되지 않은 키나 게임 전용 키에서는 그것이 그대로 받아들여집니다. 당신의 상호작용에 리플레이할 기록이 없으면 빈 문자열을 넘기세요. |

이 메서드에는 `score` 필드가 없으며, 게이트는 클라이언트가 주장한 점수가 아니라 서버의 `trace` 리플레이입니다. (`score`는 [`pass` 이벤트](#the-pass-event-and-the-token)에는 나타나며, 그것은 당신이 위젯에가 아니라 위젯이 당신에게 보고하는 것입니다.)

라운드가 시작되기 전에(모달 / 풀스크린, 다이얼로그가 아직 열리지 않음) `pass()`를 호출하면 코드 `invalid-call`로 `error`를 냅니다. 게임 전용 키(`sitekey` 없음)에서는 해제할 게이트가 없으니, `pass()`는 그저 `token: null`로 `pass` 이벤트를 냅니다.

### `fail(payload?)` (`<caputchin-game>` only)

라운드를 중단합니다: 확정적 패배. **`trigger="manual"`일 때만 유효**(아니면 `invalid-call`). 선택입니다, 끝나지 않은 라운드는 어쨌든 비통과로 다뤄집니다. 그것은 진행 중인 검증(proof-of-work와 계측 확인)을 중단하고 코드 `game-error-relayed`로 `error` 이벤트를 드러냅니다.

```js
widget.fail({ code: "out-of-moves", message: "no moves left" });
```

| `payload` 필드 | 타입 | 의미 |
|---|---|---|
| `code` | `string` (선택) | 당신의 진단 코드; `error` 이벤트의 `originalCode`로 드러남. 기본값 `game-failed`. |
| `message` | `string` (선택) | 사람이 읽을 수 있는 사유. |

## 이벤트 [#events]

`addEventListener(type, handler)`로 수신 대기하세요. 모든 페이로드는 `event.detail`에 삽니다.

| 이벤트 | 내는 곳 | `event.detail` | 발생 시점 |
|---|---|---|---|
| `start` | 둘 다 | `{ gameId: string \| null }` | 검증이 시작됨(마운트 시 auto, 활성화 시, 또는 `start()`를 통해). `gameId`는 게임 라운드에 설정되고, 순수 위젯에는 `null`. |
| `pass` | 둘 다 | `{ token: string \| null, score: number \| null, durationMs: number \| null }` | 검증이 해제됨. `token`은 당신의 백엔드로 보낼 감싼 토큰; 게임 전용 키(`sitekey` 없음)에는 `null`. |
| `error` | 둘 다 | `{ code, message, severity, originalCode? }` | 무해한 구성 경고부터 단단한 실패까지 무엇이든. [error 이벤트](#the-error-event)를 보세요. |
| `degraded` | 둘 다 | `{ reason: "timeout" \| "network" \| "http" \| "malformed" }` | 위젯이 당신이 구성한 크기 / 스킨 / 로케일을 제때 해소하지 못해, 번들된 기본값으로 렌더했습니다. 오류가 아닙니다. [degraded 이벤트](#the-degraded-event)를 보세요. |
| `dialog-shown` | `<caputchin-game>` | `{ layout: "modal" \| "fullscreen" }` | 오버레이 게임 다이얼로그가 열림(프로그램적 또는 첫 클릭). |
| `dialog-hidden` | `<caputchin-game>` | `{ layout: "modal" \| "fullscreen" }` | 오버레이 게임 다이얼로그가 닫힘(프로그램적, Escape, 또는 배경 클릭). |

### `pass` 이벤트와 토큰 [#the-pass-event-and-the-token]

`pass` 이벤트는 검증이 성공했다는 당신의 신호이지만, 그것은 신뢰 결정이 **아닙니다**. 신뢰 결정은 당신의 백엔드가 `detail.token`을 확인하는 것입니다. 늘 [백엔드에서 토큰을 검증](/docs/integration-guides/verify-on-your-backend)하세요; 결코 프런트엔드 이벤트만으로 접근을 부여하지 마세요. 폼에서, 위젯은 평범한 폼 POST가 그것을 싣도록 토큰을 `caputchin-token` 필드로도 주입합니다. 이 이벤트의 `score`와 `durationMs`는 클라이언트가 보고한 분석이며 `null`일 수 있습니다; 결코 그것들을 신뢰 신호로 다루지 마세요.

### `error` 이벤트 [#the-error-event]

`error` 이벤트는 안정된 `code`, 사람용 `message`, `severity`, 그리고 때로 `originalCode`를 지닙니다. 각 코드는 고정된 기본 severity를 가지니, 코드-대-severity 표를 하드코딩하지 **않고** "계속 돌았음" 경고를 "실제로 깨짐" 실패에서 거를 수 있습니다, 그저 `detail.severity`를 읽으세요. 전체 코드 묶음:

| `code` | `severity` | 의미 |
|---|---|---|
| `invalid-config` | `warn` | 위젯이 거부한 속성이나 조합; 그것은 우아하게 저하되고 계속 돕니다. |
| `invalid-call` | `warn` | 유효하지 않을 때 호출된 메서드(예: 비수동 게임에서의 `pass()`, 또는 라운드 시작 전). |
| `verification-failed` | `error` | proof-of-work나 계측 확인(또는 토큰 사용)이 실패함; 토큰 발급 안 됨. |
| `game-load-failed` | `error` | 게임 번들을 해소, 로드, 또는 등록할 수 없음. |
| `gate-unavailable` | `error` | 서버가 부트스트랩에서 권위 있는 거부를 반환함(게이트된 키가 유효한 게임을 공급할 수 없음). |
| `game-error-relayed` | `error` | 게임 안에서 오류가 드러남(iframe에서 중계됨, 또는 수동 `fail()`에서). |

`detail.originalCode`는 공개 `code`가 더 구체적인 내부 사유의 일반화일 때 있습니다(예를 들어, `game-load-failed`로 중계된 iframe 로드 실패는 날 `iframe-load-failed` / `iframe-script-blocked` / `game-not-registered`를 `originalCode`에 지닙니다). 분기에는 `code`를, 진단에만 `originalCode`를 쓰세요.

### `degraded` 이벤트 [#the-degraded-event]

마운트 시, 위젯은 당신이 구성한 크기, 스킨, 로케일(그리고 마켓플레이스 게임이라면, 그 선호 풋프린트)을 해소하려고 Caputchin에 짧은 호출을 한 번 합니다. 그 호출이 실패하거나 너무 느리면, 위젯은 막히거나 깨지지 않습니다: 번들에 구워 넣은 값으로 렌더하고 `degraded`를 내보내, 폴백이 결코 조용하지 않게 합니다. 위젯은 `degraded` 이벤트 후에도 완전히 작동하며, 해소된 표현만 당신이 구성한 것과 다를 수 있습니다(게임이 기본 크기로 나타나거나, 체크박스가 기본 테마로 나타날 수 있습니다). 위젯은 폴백 전에 느린 해소를 재시도하므로, `degraded`는 재시도가 소진됐음을 뜻하지, 한 번의 시도가 느렸음을 뜻하지 않습니다.

`detail.reason`은 해소가 왜 폴백했는지 알려주니, 당신 자신의 텔레메트리에 드러낼 수 있습니다:

| `reason` | 의미 |
|---|---|
| `timeout` | 해소가 시간 예산 안에 답하지 않았습니다(서비스가 느리거나 닿을 수 없음). |
| `network` | 요청 자체가 실패했습니다(오프라인, DNS, 차단됨, 또는 연결 재설정). |
| `http` | 서비스가 오류 상태로 답했습니다. |
| `malformed` | 서비스가 답했으나, 본문이 유효하지 않았습니다. |

`degraded`는 실패가 아니라 알림이라, 의도적으로 `error` 이벤트가 **아닙니다**: 느린 해소가, 진짜 실패를 위해 당신이 배선한 핸들러를 발동해서는 안 됩니다. 저하된 렌더를 관찰하고 싶을 때만, 예를 들어 방문자가 폴백 표현을 보고 있을 때 경보를 울리기 위해, 이것을 수신 대기하세요.

## 실제로 수신 대기하기

```js
const widget = document.querySelector("caputchin-game");

const onPass = (e) => {
  // send e.detail.token to your backend to verify
};
const onError = (e) => {
  if (e.detail.severity === "error") {
    console.error(e.detail.code, e.detail.message);
  }
};

widget.addEventListener("pass", onPass);
widget.addEventListener("error", onError);

// Clean up when you tear down your view:
widget.removeEventListener("pass", onPass);
widget.removeEventListener("error", onError);
```

이것들은 네이티브 DOM `CustomEvent`라, React에서는 `ref`와 `addEventListener`로 붙입니다(JSX `onPass` prop이 아니라); [프런트엔드 예제](/docs/integration-guides/frontend-examples)가 프레임워크별 배선을 보여 줍니다. 모든 이벤트가 버블링되고 composed이므로, 각 위젯을 개별로 바인딩하는 대신 컨테이너 요소에서 위임할 수도 있습니다.

## 함께 보기

- [위젯 추가](/docs/getting-started/add-the-widget): 당신이 마크업에 설정하는 구성 속성(이 출력 측에 대한 입력 측).
- [수동 모드로 검증을 직접 몰아가기](/docs/custom-game-development/manual-mode): `start()` / `pass()` / `fail()`을 쓰는 튜토리얼.
- [백엔드에서 검증하기](/docs/integration-guides/verify-on-your-backend): `pass` 이벤트의 토큰으로 무엇을 할지.
- [프런트엔드 예제](/docs/integration-guides/frontend-examples): React, Vue, 순수 JS에서 이 이벤트 배선하기.
