Lingara Lingara 문서 학습 가이드 API 라이브러리 앱 만들기 웹 앱
언어: 한국어

OAuth 클라이언트를 만드는 방법

API 버전 2026-10-affable-towhee

연동 페이지에서 클라이언트 만들기를 누르기 전에 세 가지를 정하세요. 클라이언트가 무엇을 할 수 있는지, 어떤 프로세스가 시크릿을 보관하는지, 그리고 호출 비용을 누가 내는지입니다. 규칙은 인증 가이드에 나와 있으며, 이 페이지에서는 그 규칙을 가상의 두 회사 Luba와 Farducks에 적용합니다.

Luba: Dive Deck

Luba는 자율 운항 잠수함으로 운송 및 승차 공유 서비스를 운영합니다. Dive Deck은 객실 화면에 각 승객이 배우고 있는 언어로 그 잠항의 문구를 보여 주며, Luba 운영팀은 사용 한도가 얼마나 남았는지 지켜봅니다.

Luba는 Luba Dive Deck이라는 클라이언트 하나를 만들어 어휘 생성(vocab:generate)과 사용량 읽기(usage:read)를 허용하고, 과금 방식은 요금제 기본 제공량(allowance)으로 정합니다. 두 프로세스가 이 클라이언트를 함께 쓰며, 각 프로세스는 교환할 때 필요한 스코프만 요청합니다. scope를 생략한 교환은 클라이언트에 허용된 모든 스코프를 받습니다. 클라이언트에 허용되지 않은 스코프를 요청한 교환은 invalid_scope로 전체가 거부되며, 조용히 범위가 좁혀지는 일은 없습니다.

배차 서버는 각 잠항의 문구를 작성합니다. 이 서버는 vocab:generate 하나만 요청하므로, 여기서 토큰이 유출되더라도 Luba의 사용량을 읽을 수 없습니다.

export LINGARA_TOKEN="$(curl -sS --fail-with-body -X POST "https://api.getlingara.com/oauth/token" \
  -u "$LINGARA_CLIENT_ID:$LINGARA_CLIENT_SECRET" \
  -d "grant_type=client_credentials" \
  --data-urlencode "scope=vocab:generate" | jq -r '.access_token // error(.error)')"
curl -N -X POST "https://api.getlingara.com/v1/vocab/stream" \
  -H "Authorization: Bearer $LINGARA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"level":2,"source_lang":"en","target_lang":"zh","count":8}'

운영 대시보드는 같은 클라이언트 ID와 시크릿을 쓰는 두 번째 서버 측 프로세스입니다. usage:read 하나만 요청하고, 남은 사용 한도를 읽습니다.

export LINGARA_TOKEN="$(curl -sS --fail-with-body -X POST "https://api.getlingara.com/oauth/token" \
  -u "$LINGARA_CLIENT_ID:$LINGARA_CLIENT_SECRET" \
  -d "grant_type=client_credentials" \
  --data-urlencode "scope=usage:read" | jq -r '.access_token // error(.error)')"
curl "https://api.getlingara.com/v1/usage" \
  -H "Authorization: Bearer $LINGARA_TOKEN"

두 프로세스 모두 Luba의 서버에서 실행됩니다. 객실의 태블릿은 배차 서버에 문구를 요청할 뿐 시크릿이나 토큰을 절대 갖지 않습니다. 승객이 만질 수 있는 기기에 있는 것은 무엇이든 읽힐 수 있기 때문입니다. 그 이유는 인증 가이드의 '시크릿과 토큰은 서버에 보관하세요' 절에서 설명합니다.

같은 클라이언트를 복제해 실행할 수 있는 프로젝트로: integrations/luba-dive-deck

Farducks: Batter Rewards

Farducks는 피시 앤드 칩스 편의점 체인입니다. 주문한 음식이 튀겨지는 동안 Batter Rewards 로열티 앱이 Farducks 자체 백엔드에 짧은 수업 계획을 요청하고, 그 계획을 다시 읽어 옵니다. 앱과 계산대는 Lingara가 아니라 Farducks의 백엔드를 호출하므로, 어느 쪽도 시크릿을 갖지 않습니다.

Farducks는 Farducks Batter Rewards라는 클라이언트 하나를 만들어 수업 계획 만들기(lesson_plans:write)와 수업 계획 읽기(lesson_plans:read)를 허용하고, 과금 방식은 요금제 기본 제공량(allowance)으로 정합니다. 현재 클라이언트를 만들 때 선택할 수 있는 과금 방식은 이것뿐이며, 클라이언트의 과금 방식은 만들 때 고정됩니다. 다른 방식인 metered(사용량 기반 결제)는 인증 가이드의 '호출 비용은 누가 내나요' 절에서 설명합니다.

백엔드는 lesson_plans:write 하나만 요청해 계획을 만듭니다. 응답은 스트리밍되며, 그 started 이벤트에 계획의 plan_id가 담깁니다.

export LINGARA_TOKEN="$(curl -sS --fail-with-body -X POST "https://api.getlingara.com/oauth/token" \
  -u "$LINGARA_CLIENT_ID:$LINGARA_CLIENT_SECRET" \
  -d "grant_type=client_credentials" \
  --data-urlencode "scope=lesson_plans:write" | jq -r '.access_token // error(.error)')"
curl -N -X POST "https://api.getlingara.com/v1/lesson-plans" \
  -H "Authorization: Bearer $LINGARA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"context":"Ordering food at a night market","source_lang":"en","target_lang":"zh","level":2}'

ID를 그 plan_id로 설정한 뒤 lesson_plans:read를 요청해 계획을 다시 읽어 오세요. 한 번의 교환으로 클라이언트의 스코프 여러 개를 scope에 공백으로 구분해 요청할 수도 있습니다. 여기의 각 명령이 스코프 하나만 요청하는 것은 각각이 호출 하나로 구성되기 때문입니다.

export LINGARA_TOKEN="$(curl -sS --fail-with-body -X POST "https://api.getlingara.com/oauth/token" \
  -u "$LINGARA_CLIENT_ID:$LINGARA_CLIENT_SECRET" \
  -d "grant_type=client_credentials" \
  --data-urlencode "scope=lesson_plans:read" | jq -r '.access_token // error(.error)')"
curl "https://api.getlingara.com/v1/lesson-plans/$ID" \
  -H "Authorization: Bearer $LINGARA_TOKEN"

어느 날 시크릿이 지원 티켓에 붙여 넣어집니다. Farducks는 연동 페이지에서 새 시크릿을 눌러 백엔드에 배포하고, 이전 시크릿의 마지막 사용 날짜가 더 이상 바뀌지 않을 때까지 기다린 다음 이전 시크릿의 취소를 누릅니다. 그 순간부터 이전 시크릿으로 교환한 모든 액세스 토큰이 거부됩니다. 시크릿이 두 개까지라는 제한과 클라이언트의 유일한 시크릿을 취소할 수 없는 이유는 인증 가이드의 '시크릿 교체하기' 절에 나와 있습니다.

같은 클라이언트를 복제해 실행할 수 있는 프로젝트로: integrations/farducks-batter-rewards

다음 단계

인증 가이드는 교환의 오류, 토큰이 만료되었을 때 할 일, 교체 규칙을 다룹니다. 버전 가이드는 클라이언트가 고정된 버전과, 한 번의 호출에만 다른 버전을 선택하는 방법을 다룹니다.

번역본과 영어 참조 문서의 내용이 다른 경우, 영어 참조 문서가 올바른 것으로 봅니다.