Sign In with Apple , supabase , react native cli

박정빈·2025년 7월 15일

Supabase

목록 보기
4/4

supabase를 사용하는 react native cli프로젝트에서 Sign In with Apple을 구현하는 과정을 기록했다.

웹 에서

  1. Apple Developer 로 이동
  2. account(계정)탭으로 이동
  3. 인증서,ID및 프로파일 탭에서 identifier(식별자)로 이동
  4. Identifiers 생성 , keys 에서 Sign In with Apple 체크박스 활성화 하거나 활성화하면서 새로 만들기 , 키는 다운로드하기
  5. supabase/Authentication에서 provider생성(Apple)
    client IDs 는 앱의 아이디(예시: com.company.name)
    Secret Key(for OAuth)는 Apple JWT Generator로 JWT를 만들어서 입력

XCode 에서

  1. XCode에서 프로젝트 열기 <프로젝트이름>.xcodeproj를 열어서 열 수 있다.
  2. 프로젝트 명 클릭하고, Signing & Capabilities 탭에서 Sign In with Apple추가
  3. IOS 네이티브 코드를 작성한다.
    xcode에 프로젝트 바로 밑에 아래 두 파일을 추가한다.
    ios/AppleSignInModule.m
#import <React/RCTBridgeModule.h>

@interface RCT_EXTERN_MODULE(AppleSignInModule, NSObject)
RCT_EXTERN_METHOD(signInWithApple:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
@end 

ios/AppleSignInModule.swift

import Foundation
import AuthenticationServices

@objc(AppleSignInModule)
class AppleSignInModule: NSObject, ASAuthorizationControllerDelegate {
  private var resolve: RCTPromiseResolveBlock?
  private var reject: RCTPromiseRejectBlock?

  @objc(signInWithApple:rejecter:)
  func signInWithApple(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
    self.resolve = resolve
    self.reject = reject

    let request = ASAuthorizationAppleIDProvider().createRequest()
    request.requestedScopes = [.email, .fullName]

    let controller = ASAuthorizationController(authorizationRequests: [request])
    controller.delegate = self
    controller.performRequests()
  }

  func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
    if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential,
       let identityToken = appleIDCredential.identityToken,
       let tokenString = String(data: identityToken, encoding: .utf8) {
      resolve?(["idToken": tokenString])
    } else {
      reject?("NO_TOKEN", "Unable to fetch identity token", nil)
    }
  }

  func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
    reject?("APPLE_SIGNIN_ERROR", error.localizedDescription, error)
  }
} 
  1. 브리지 헤더 만들기
    [프로젝트 명]-Bridging-Header.h를 프로젝트 폴더안에 생성한다. (위 파일들 만든 곳에)
//
//  [프로젝트 명]-Bridging-Header.h
//  [프로젝트 명]
//
//  Created by 이름 on MM/DD/YY.
//


#ifndef [프로젝트 명]_Bridging_Header_h
#define [프로젝트 명]_Bridging_Header_h


#endif /* [프로젝트 명]_Bridging_Header_h */

이런게 생성될텐데 여기에 아래 코드를 추가한다.

#import <React/RCTBridgeModule.h>
#import <React/RCTViewManager.h>
#import <React/RCTConvert.h>

그리고 파란색 루트를 선택, 타겟을 앱으로 선택하고
Build Settings에서 All 로 선택 후 오른쪽 검색에서 bridging을 검색
Objective-C Bridging Header에 아까만든 헤더파일 경로([프로젝트명]/[프로젝트명]-Bridging-Header.h) 입력

파일 경로가
[프로젝트명]/ios/[프로젝트명]/[프로젝트명]-Bridging-Header.h
가 되어야함

그리고 클린 빌드를 한다.

react native 프로젝트에서

  1. reactnative 함수 생성
    나는 zustand 전역 상태 스토어에 함수를 만들어서 사용했다.
handleAppleLogin: async () => {
    set({ isLoading: true });
    try {
      // 네이티브 모듈에서 idToken 받아오기
      const { signInWithAppleNative } = await import('../libs/native/AppleSignIn');
      const idToken = await signInWithAppleNative();
      // console.log('Apple idToken:',idToken)
      if (!idToken) {
        Alert.alert('Apple 로그인 오류', 'idToken을 받아오지 못했습니다.');
        set({ isLoggedIn: false });
        return;
      }

      const { data, error } = await supabase.auth.signInWithIdToken({
        provider: 'apple',
        token: idToken,
      });
      // console.log('data: ',data)

      if (error) {
        Alert.alert('Apple 로그인 오류', error.message || '로그인 중 오류가 발생했습니다.');
        set({ isLoggedIn: false });
      } else if (data.session) {
        set({
          isLoggedIn: true,
          userId: data.user.id,
        });
        if (__DEV__) {
          console.log('[AuthStore] isLoggedIn set to true in handleAppleLogin()');
        }
      }
    } catch (error: any) {
      Alert.alert('Apple 로그인 오류', error.message || '알 수 없는 오류가 발생했습니다.');
      set({ isLoggedIn: false });
    } finally {
      set({ isLoading: false });
    }
  },

2개의 댓글

comment-user-thumbnail
2025년 12월 29일

ios 파일은 직접 작성하신건가용?
현재 라이브러리를 쓸지 코드 그래도 써볼지 싶어서요

1개의 답글