• oidc
  • supabase
  • auth
  • rls
  • jwt

Supabase 통합 방법

Logto를 Supabase와 통합하여 애플리케이션의 인증 경험을 향상시키는 방법을 배워보세요.

Yijun
Yijun
Developer

Logto는 애플리케이션에 대한 안전하고, 종합적이며 사용자가 쉽게 로그인할 수 있도록 지원하는 현대적인 ID 인증 서비스 제공자입니다. Logto는 다양한 프레임워크와 프로그래밍 언어를 아우르는 SDK 및 통합 가이드를 제공하며, 몇 분 안에 엔터프라이즈급 ID 인증 서비스를 애플리케이션에 원활하게 통합할 수 있습니다.

이 글은 주로 Supabase와 Logto를 어떻게 통합할 수 있는지에 대해 자세히 설명하는 것을 목표로 합니다.

Supabase 기본 사항

Supabase는 데이터 접근 권한을 제어하기 위해 Postgres의 Row-Level Security를 사용합니다. 간단히 말해서, 데이터베이스의 테이블에 대해 Row Level Security 정책을 만들면, 특정 사용자가 테이블에서 데이터를 읽고, 쓰고, 업데이트할 수 있는지를 제한하고 관리할 수 있습니다.

예를 들어, 데이터베이스에 "posts"라는 테이블이 있으며, 다음과 같은 내용을 포함하고 있다고 가정해 봅시다:

포스트 테이블

테이블의 user_id 필드는 각 포스트 데이터가 어떤 사용자에게 속해 있는지를 나타냅니다. user_id 필드를 기반으로 각 사용자가 자신의 포스트 데이터만 접근할 수 있도록 제한할 수 있습니다.

그러나 이를 구현하기 전에 Supabase가 데이터베이스에 접근하는 현재 사용자를 식별할 수 있어야 합니다.

Supabase 요청에 사용자 데이터 추가하기

JWT를 지원하는 Supabase 덕분에, 우리의 애플리케이션이 Supabase와 상호작용할 때, Supabase에서 제공하는 JWT 비밀 키를 사용하여 사용자 데이터를 포함한 JWT를 생성할 수 있습니다. 그런 다음 이 JWT를 요청할 때 인증 헤더로 사용합니다. 요청을 받으면 Supabase는 JWT의 유효성을 자동으로 확인하고, 이후 프로세스 전체에서 JWT에 포함된 데이터에 대한 접근을 허용합니다.

먼저, Supabase 대시보드의 “프로젝트 설정”에서 Supabase가 제공하는 JWT 비밀 키를 얻을 수 있습니다:

Supabase API 설정 페이지

그런 다음, Supabase SDK를 사용하여 Supabase에 요청할 때 이 비밀 키를 사용하여 JWT를 생성하고 이 JWT를 요청의 인증 헤더에 첨부합니다. (이 과정은 애플리케이션의 백엔드 서비스 내에서 이루어지며, JWT 비밀 키는 제 3자에게 절대 노출되어서는 안 됩니다).

다음으로, Supabase 대시보드의 SQL Editor로 이동하여 요청에 담긴 userId를 가져오는 함수를 생성합니다:

사용자 ID 함수 생성하기

이미지에서 사용된 코드는 다음과 같습니다:

코드에서 보듯이, Supabase에서는 우리가 생성한 JWT의 페이로드를 가져오려면 request.jwt.claims를 호출하면 됩니다. 페이로드 내의 userId 필드는 우리가 설정한 값입니다.

이 함수를 사용하여 Supabase는 현재 데이터베이스에 접근하는 사용자를 식별할 수 있습니다.

Row-Level Security 정책 생성하기

다음으로, posts 테이블의 user_id 필드를 기반으로 각 사용자가 자신의 포스트 데이터만 접근할 수 있도록 제한하는 Row-Level Security 정책을 생성할 수 있습니다.

  1. Supabase 대시보드에서 Table Editor 페이지로 이동하여 posts 테이블을 선택합니다.
  2. 테이블 상단에서 "Add RLS Policy"를 클릭합니다.
  3. 창이 뜨면 "Create policy"를 클릭합니다.
  4. 정책 이름을 입력하고 SELECT Policy 명령을 선택합니다.
  5. 다음 코드의 using 블록에서 다음을 입력합니다:
RLS 정책 생성하기

이런 정책을 활용해 Supabase 내에서 데이터 접근 제어가 이루어집니다.

실제 애플리케이션에서는 데이터 삽입 및 수정과 같은 사용자 작업을 제한하는 다양한 정책을 만들게 됩니다. 하지만 이는 이 글의 범위를 벗어납니다. Row-Level Security (RLS)에 대한 자세한 내용은 Postgres Row Level Security 를 사용하여 데이터를 보호하기를 참조하세요.

Logto와의 기본 통합 과정

앞서 언급한 것처럼, Supabase는 접근 제어를 위해 RLS를 사용하므로 Logto(또는 다른 인증 서비스)와의 통합의 핵심은 인증된 사용자의 사용자 ID를 얻고 이를 Supabase로 전송하는 데 있습니다. 전체 프로세스는 아래 다이어그램에 나와 있습니다:

다음으로는 이 프로세스 다이어그램을 기반으로 Logto를 Supabase와 통합하는 방법을 설명합니다.

Logto 통합

Logto는 다양한 프레임워크와 프로그래밍 언어에 대한 통합 가이드를 제공합니다.

일반적으로 이러한 프레임워크와 언어들로 빌드된 앱들은 네이티브 앱, SPA (단일 페이지 앱), 전통적인 웹 앱, M2M (기계 대 기계) 앱과 같은 카테고리에 속합니다. 사용하고 있는 기술 스택을 기반으로 Logto를 애플리케이션에 통합하려면 Logto 빠른 시작 페이지를 방문하세요. 이후 애플리케이션의 유형에 따라 아래 지침을 따라 Logto를 프로젝트에 통합하세요.

네이티브 앱 또는 SPA

네이티브 앱과 SPA는 모두 기기에서 실행되며, 로그인 후 얻은 자격 증명(access token)은 기기 내에 저장됩니다.

따라서, 애플리케이션을 Supabase와 통합할 때 각 사용자의 기기에 민감한 정보를 노출할 수 없기 때문에 백엔드 서비스를 통해 Supabase와 상호작용해야 합니다.

React와 Express를 사용하여 SPA를 빌드하고 있다고 가정해 봅시다. Logto React SDK 가이드를 따라 애플리케이션에 Logto를 성공적으로 통합했다고 가정합니다 (해당 코드는 react 샘플을 참조할 수 있습니다). 또한, 백엔드 서버에 노드 (Express)에서 API 보호하기 문서를 따라 Logto 엑세스 토큰 검증을 추가했습니다.

이후 Logto에서 얻은 엑세스 토큰을 사용하여 백엔드 서버에서 사용자 데이터를 요청할 수 있습니다:

백엔드 서버에서 이미 미들웨어를 사용하여 엑세스 토큰에서 로그인된 사용자의 ID를 추출했습니다:

이제 이 미들웨어로 얻은 userId 를 Supabase와의 후속 요청에서 사용되는 JWT에 첨부하는 getSupabaseClient를 사용할 수 있습니다. 또는, Supabase와 상호작용할 필요가 있는 요청에 대해 Supabase 클라이언트를 생성하는 미들웨어를 만들 수도 있습니다:

후속 처리 흐름에서는 ctx.supabase를 호출하여 Supabase와 직접 상호작용할 수 있습니다:

이 코드에서, Supabase는 이전에 설정한 정책에 따라 현재 사용자에게 속하는 포스트 데이터만 반환하게 됩니다.

전통적인 웹 앱

전통적인 웹 앱과 네이티브 앱 또는 SPA의 주요 차이점은 전통적인 웹 앱은 웹 서버에서만 페이지를 렌더링하고 업데이트한다는 점입니다. 따라서, 네이티브 앱과 SPA에서는 사용자 기기에 자격 증명을 저장하는 반면, 전통적인 웹 앱에서는 웹 서버에서 자격 증명을 직접 관리합니다.

Supabase에서 전통적인 웹 앱과 Logto를 통합할 때, 로그인된 사용자의 ID를 백엔드에서 직접 가져올 수 있습니다.

Next.js 프로젝트를 예로 들어, Next.js SDK 가이드를 따라 프로젝트에 Logto를 통합한 후, Logto SDK를 사용하여 사용자 정보를 가져오고 Supabase와 상호작용하기 위해 해당 JWT를 생성할 수 있습니다.

기계 간 애플리케이션

기계 대 기계 (M2M)는 애플리케이션이 리소스 서버와 직접적으로 통신해야 할 때, 예를 들어 매일 포스트를 가져오는 정적 서비스 등에서 자주 사용됩니다.

M2M 애플리케이션 인증을 위해 M2M: Logto로 인증하기 가이드를 사용할 수 있습니다. Supabase와 M2M 애플리케이션의 통합은 네이티브 앱과 SPA의 통합과 유사합니다 ("네이티브 앱 또는 단일 페이지 앱" 섹션 참조). 여기에는 Logto로부터 엑세스 토큰을 얻고 백엔드의 보호된 API를 통해 이를 검증하는 과정이 포함됩니다.

그러나 네이티브 앱과 SPA는 일반적으로 최종 사용자를 위한 것이므로, 얻은 사용자 ID는 사용자를 나타냅니다. 반면, M2M 애플리케이션에 대한 엑세스 토큰은 애플리케이션 자체를 나타내며, 엑세스 토큰 페이로드의 sub 필드는 특정 사용자가 아니라 M2M 앱의 클라이언트 ID입니다. 따라서 개발 중에는 M2M 애플리케이션을 위한 데이터와 그렇지 않은 데이터를 구분해야 합니다.

더 나아가, 특정 M2M 앱이 RLS 제약을 우회하여 서비스 전체를 대신해 Supabase에 접근해야 하는 경우, Supabase의 service_role 비밀 키를 사용하여 Supabase 클라이언트를 생성할 수 있습니다. 이는 개별 사용자를 위한 Row-Level Security 정책의 제약 없이 모든 데이터에 접근해야 하는 관리 작업이나 자동화 작업을 수행하고자 할 때 유용합니다.

service_role 비밀 키는 JWT 비밀 키와 동일한 페이지에서 확인할 수 있습니다:

서비스 역할 비밀 키

Supabase 클라이언트를 생성할 때 service_role 비밀 키를 사용하면 이 클라이언트는 데이터베이스의 모든 데이터에 접근할 수 있습니다:

요약

이 글에서는 Logto와 Supabase를 통합하는 방법에 대해 심층적으로 설명하며, 중요한 통합 측면과 주요 내용을 다루었습니다. JWT 인증 및 Row-Level Security 정책과 같은 개념을 탐구하며, Logto를 Supabase 기반 애플리케이션에 원활하게 통합하는 방법을 안내했습니다. 이 지식을 바탕으로 애플리케이션의 보안 및 기능을 자신 있게 강화할 수 있기를 바라며, 추가적인 기능을 프로젝트에 확장할 수 있기를 바랍니다.