# API 키

앱, 서버, CI는 프로젝트의 API 키로 Mocco API를 호출합니다. 키는 프로젝트 하나에 속하며 그 프로젝트의 데이터에만 접근할 수 있습니다. 키는 프로젝트의 **API keys** 페이지에서 관리합니다.

![API keys 페이지: publishable 키와 secret 키, 각 키의 힌트, 스코프, 마지막 사용 시각](https://fi-workers-mocco-storage.s3.ap-northeast-2.amazonaws.com/pub/w/93e11fe8-0494-4e3d-b1cb-fe4dffd3ee7e/p/d64785b8-9a23-4fa1-a81d-550af30e203a/helpcenter/fc1eca9d-f98f-4bb7-9423-f61b70a47cd8/api-keys.png)

## Publishable 키와 secret 키

키는 두 종류이고, 키의 앞부분으로 종류를 알 수 있습니다.

**Publishable** 키(`mk_pub_…`)는 누구나 읽을 수 있는 웹 앱이나 React Native 앱 안에 넣도록 만든 키입니다. 클라이언트 앱에 필요한 스코프만 가질 수 있고, 그중 설정을 바꾸는 스코프는 없습니다. 브라우저에서는 프로젝트의 웹 앱 오리진에서만 동작합니다. 오리진은 프로젝트의 **Overview** 페이지에서 **Edit origins**로 설정합니다. 다른 사이트의 페이지는 `403 origin_not_allowed`를 받습니다.

**Secret** 키(`mk_sec_…`)는 서버와 CI용입니다. 어떤 스코프든 가질 수 있으므로 앱에 넣지 말고 시크릿 저장소에 보관하세요. Mocco는 웹 페이지에서 보낸 secret 키를 거부하므로(`401 secret_key_from_browser`) 프론트엔드 코드가 실수로 쓸 수 없습니다. 그래도 secret 키가 앱이나 공개 저장소에 들어갔다면 폐기하세요.

| 코드가 실행되는 곳 | 키 | 스코프 |
|---|---|---|
| 웹 페이지 또는 React 웹 앱 | Publishable | `flags:read` |
| React Native 앱 | Publishable | `flags:read`, `messenger:chat` |
| 플래그를 평가하는 Node 서버 | Secret | `flags:read` |
| 호스팅 OTA 업데이트를 업로드하고 승격하는 CI | Secret | `ota:write` |

## 스코프

스코프는 키가 할 수 있는 일입니다. 각 키에는 그 키를 쓰는 코드에 필요한 스코프만 주세요.

- `flags:read`는 기능 플래그를 평가합니다. 이 스코프가 있는 키는 키를 만들 때 고른 플래그 환경 하나만 읽습니다. 환경마다 키를 하나씩 만드세요. publishable 키를 쓰면 앱에는 클라이언트에 공개로 표시한 플래그만 보입니다. [브라우저와 앱에서 기능 플래그 쓰기](https://www.mocco.club/docs/ko/articles/nb48sq-browsers-and-apps)를 참고하세요.
- `messenger:chat`은 로그인한 사용자가 문의할 수 있게 합니다. 호출마다 서버가 서명한 사용자 ID도 필요합니다. [Mocco Messenger로 앱 안에서 문의받기](https://www.mocco.club/docs/ko/articles/ky2kfv-contact-us)를 참고하세요.
- `ota:write`는 CI에서 호스팅 OTA 업데이트를 업로드하고 배포합니다. [Mocco에서 OTA 업데이트 호스팅하기](https://www.mocco.club/docs/ko/articles/em6rkw-hosted-updates)를 참고하세요.
- `ota:read`와 `flags:write`는 양식에 있지만, 아직 이 스코프가 필요한 Mocco API 호출은 없습니다.

키가 필요 없는 호출도 있습니다. 강제 업데이트 버전 확인과, 앱의 업데이트 클라이언트가 내려받는 OTA 매니페스트입니다.

## 키 만들기

키는 소유자와 관리자가 만듭니다. 멤버는 목록을 읽기만 할 수 있습니다.

1. 프로젝트의 **API keys** 페이지에서 **Create key**를 선택합니다.
2. **Kind**에서 **Publishable** 또는 **Secret**을 고릅니다. publishable 키에는 `ota:read`, `flags:read`, `messenger:chat`만 나옵니다.
3. 키를 쓰는 곳을 알 수 있는 **Name**을 붙입니다. 예: `Acme web`, `CI publishing`.
4. **Scopes**에 체크합니다. `flags:read`를 고르면 키가 읽을 **Flag environment**를 선택합니다.
5. **Create key**를 선택합니다.

![publishable 키 만들기: 클라이언트 스코프만 나오고, 웹 오리진에 대한 안내가 있습니다](https://fi-workers-mocco-storage.s3.ap-northeast-2.amazonaws.com/pub/w/93e11fe8-0494-4e3d-b1cb-fe4dffd3ee7e/p/d64785b8-9a23-4fa1-a81d-550af30e203a/helpcenter/b5ca7072-dfde-421e-ab3c-436fcea0ce01/api-keys-publishable.png)

Mocco는 새 키를 **Copy the key now** 아래에 한 번만 보여 줍니다. 앱 설정이나 시크릿 저장소에 복사한 다음 **Done**을 선택하세요. Mocco는 키의 해시만 보관하므로 다시 보여 줄 수 없습니다. 키를 잃어버렸다면 폐기하고 새로 만드세요.

키는 `Authorization: Bearer <key>`로 보냅니다. SDK에 키를 넘기면 SDK가 대신 보냅니다.

여기서 만든 키는 만료되지 않고, 폐기할 때까지 동작합니다. 만료일이 지난 키에는 **Expired**가 표시되고 거부됩니다.

## 키 폐기하기

키에서 **Revoke**를 선택하고, 확인하려면 **Revoke key**를 선택합니다. 이 키를 쓰는 호출은 즉시 실패하고(`401 invalid_key`), 키는 **Revoked**로 표시된 채 목록에 남습니다.

다운타임 없이 키를 교체하려면 새 키를 만들어 배포하고, 이전 키의 "last used" 시각이 더 이상 갱신되지 않는지 확인한 뒤 이전 키를 폐기하세요. 각 키에는 만든 시각과 마지막으로 쓴 시각이 표시됩니다(마지막 사용 시각은 1분에 한 번까지만 갱신됩니다).

키 생성과 폐기는 [감사 로그](https://www.mocco.club/docs/ko/articles/2yiscf-audit-log)에 `apikey.created`와 `apikey.revoked`로 기록됩니다.

## 오류

Mocco는 상태 코드와 짧은 코드로 응답합니다.

| 응답 | 의미 |
|---|---|
| `401 missing_key` | 키를 보내지 않았습니다. |
| `401 invalid_key` | 알 수 없는 키이거나, 폐기되었거나, 만료되었습니다. |
| `401 secret_key_from_browser` | 웹 페이지에서 secret 키를 보냈습니다. |
| `403 origin_not_allowed` | 프로젝트의 웹 오리진이 아닌 사이트에서 publishable 키를 썼습니다. |
| `403 wrong_key_kind`, `403 insufficient_scope` | 키의 종류나 스코프가 이 호출을 허용하지 않습니다. |
| `429 rate_limited` | 요청이 너무 많습니다. `Retry-After`에 적힌 초만큼 기다리세요. publishable 키는 분당 600건, secret 키는 분당 1,200건까지 요청할 수 있습니다. |
