콘텐츠로 이동

OAuth2 그랜트 타입 (권한을 얻는 네 가지 방법)

사용자가 동의 화면을 지나고 나면, 앱은 어떻게 그 "허락"을 실제 API 호출 자격으로 바꿀까요? 그 다리를 놓는 절차를 그랜트 타입(grant type)이라고 불러요. 말 그대로 "권한을 부여받는 방식"이죠. 어떤 상황에서 권한을 주고받느냐에 따라 다른 타입을 골라 씁니다.

그랜트 타입은 크게 사용자가 직접 허락하는 방식(대화형 앱)과 서비스끼리 신뢰로 주고받는 방식(기계 간 통신)으로 나뉜다. 각각이 언제 쓰이는지, 보안상 신경 쓸 지점이 어딘지 아래에서 짚어볼게요.

개요

OAuth 2.0은 권한 위임을 위한 프레임워크라서, 절차를 하나로 못 박아 두지 않아요. 대신 여러 그랜트 타입을 제공하고, 클라이언트의 종류(브라우저 앱이냐, 서버 앱이냐)와 신뢰 수준에 따라 적절한 타입을 쓰도록 유도합니다. 이 중에서 현재 실제로 널리 쓰이는 건 몇 개로 줄어들었어요.

핵심 개념

Authorization Code(인가 코드). 가장 안전하고 권장되는 방식이에요. 사용자가 인증 서버에서 로그인·동의하면 서버는 임시 코드를 앱에 넘기고, 앱은 그 코드를 다시 서버에 보내 액세스 토큰으로 교환해요. 이 교환은 클라이언트 비밀을 함께 보내는 백엔드 통신으로 일어나서, 토큰이 브라우저나 사용자 손을 거치지 않습니다.

사용자 → 인증 서버 로그인·동의 → 임시 코드 → 앱 백엔드 → 토큰 교환 → API

PKCE(Proof Key for Code Exchange). 인가 코드 방식이지만, 코드를 토큰으로 바꾸는 단계에서 코드 검증자(code_verifier)가 진짜인지 추가로 확인해요. 공개 클라이언트(SPA, 모바일 앱처럼 클라이언트 비밀을 안전히 숨길 수 없는 앱)에서 코드 탈취를 막으려고 쓰입니다. 그래서 지금은 인가 코드 흐름과 사실상 함께 쓰는 게 표준이 됐어요.

Client Credentials(클라이언트 자격증명). 사용자가 아예 없고 서비스끼리 통신할 때 쓰는 방식이에요. 앱이 자기 자신의 자격(client_id와 client_secret)으로 직접 토큰을 받아요. 우리 백엔드가 다른 백엔드 기능을 호출할 때처럼, "사용자 대신"이 아니라 "시스템 자격으로" 권한을 얻는 경우죠.

그 외에 리소스 소유자의 비밀번호를 직접 받는 Password 방식과 브라우저 리다이렉트만으로 토큰을 주는 Implicit 방식이 있었지만, 보안 문제로 지금은 권장되지 않아요. 최신 가이드는 거의 모두 인가 코드(+PKCE)를 권합니다.

실제 적용(데이터스케쳐스)

우리가 외부 서비스(Notion, Google 등)를 연동할 때는 인가 코드 + PKCE를 기준으로 잡아요. 웹빌더 같은 브라우저 앱은 클라이언트 비밀을 숨길 수 없으니 PKCE가 있어야 코드 탈취 위험을 줄일 수 있어요.

반대로 우리 백엔드가 다른 내부/파트너 서비스를 호출할 때는 client credentials로 시스템 자격 토큰을 받는 식으로 나눠요. 사용자 흐름과 서비스 간 흐름을 명확히 구분해 두면, 각 토큰이 "누구를 대신하는지"를 감사 로그에서도 바로 알 수 있어요.

더 알아보기