728x90

AppleLogin 라이브러리에서 email 정보도 가져와서 사이트에서 활용해야 한다면 responseMode 를 form_post 로 설정하고 값을 보내고 다시 post 로 데이터를 받아야 한다.

 

 

post 데이터를 받는 부분이기 때문에 백엔드로 받아서 front 에서 토큰을 저장하는 로직을 구현 해주어야 한다. 

import React from 'react';
import AppleLogin from 'react-apple-login';

const AppleLoginButton = () => {
  const handleSuccess = (response) => {
    console.log("로그인 성공:", response);
    // 서버에 response.id_token을 보내서 사용자 정보를 처리합니다.
    fetch('https://yourapp.com/api/auth/apple', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        id_token: response.id_token,
      }),
    })
    .then(res => res.json())
    .then(data => {
      console.log("서버 응답:", data);
      // 사용자 정보를 처리합니다.
    })
    .catch(error => {
      console.error("서버 통신 실패:", error);
    });
  };

  const handleError = (error) => {
    console.error("로그인 실패:", error);
  };

  return (
    <AppleLogin
      clientId="com.yourapp.identifier" // 애플 개발자 계정에서 등록한 클라이언트 ID
      redirectURI="https://yourapp.com/auth/apple/callback" // 리다이렉트 URI
      responseType="id_token" // id_token으로 변경
      responseMode="form_post" // POST 방식으로 변경
      usePopup={true} // 팝업으로 로그인할지 여부
      onSuccess={handleSuccess}
      onError={handleError}
    />
  );
};

export default AppleLoginButton;

 

이때 redirectURI 는 백엔드 api url 을 주어야 하고 아래와 같이 백엔드에서는 post 로 받아서 다시 front 로 /front/login 으로 id 와 email 정보를 넘겨 주고 front 에서는 세션 처리를 하면 된다.

email 값이 안넘어 온다면 form_post 로 변경해 보길 권한다. 

const appleToken = async (request, response) => {
    const { code } = request.body;

    if (!code) {
        return response.status(400).json({ message: 'Code is required.' });
    }

    const result = (data, message) => {
        if (message === messageMap.OK) {
            const { id, email } = data;
            response.redirect(`https://프런트도메인/front/login?snsid=${id}&email=${email}`);
        } else {
            response.status(message.status).json({ message: message.string });
        }
    };
};
728x90
728x90

vue 에서 api 호출시 axios 로 호출 되는 모든 api 의 오류를 체크 할수 있는 파일은 interceptor.js 에서 한번에 처리 할수 있다. 그래서 headers 부분도 매번 api 호출 할때마다 적어주는것이 아니라 congif.headers 로 한번에 지정이 가능하다. 

 

아래 예시는 localStorage 에 토큰값을 저장해 두고 api 호출시 토큰값을 헤더에 실어 보내는 예시다. 보통 권한 오류는 401 로 떨어 지기에 401 로 코드를 받았을때 와 403, 404 정도로 분기를 하고 필유시 코드별로 메세지를 지정해 둘수도 있다. 

 

원래는 이렇게 router 가 사용이 가능해야 하는데 안되는 경우도 있으니 참고하는게 좋겠다. 

import axios from 'axios';
import store from '@/store'; // Vuex store
import router from '@/router'; // Vue Router

// Axios 인스턴스 생성
const axiosInstance = axios.create();

// 요청 인터셉터
axiosInstance.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('token'); // 토큰 가져오기
    if (token) {
      config.headers.Authorization = `Bearer ${token}`; // Authorization 헤더 추가
    }
    return config;
  },
  (error) => {
    return Promise.reject(error); // 요청 오류 처리
  }
);

// 응답 인터셉터
axiosInstance.interceptors.response.use(
  (response) => {
    return response; // 응답이 성공적일 경우 응답 반환
  },
  async (error) => {
    if (error.response) {
      const status = error.response.status;

      // 401 Unauthorized 처리
      if (status === 401) {
        alert('로그인 세션이 종료되었습니다. 다시 로그인해주세요.');
        store.dispatch('auth/logout'); // 로그아웃 액션
        router.push('/auth/login'); // 로그인 페이지로 리다이렉트
        return Promise.reject(error);
      }

      // 403 Forbidden 처리
      if (status === 403) {
        alert('이 작업을 수행할 권한이 없습니다.');
        return Promise.reject(error);
      }

      // 404 Not Found 처리
      if (status === 404) {
        router.push('/error/404'); // 404 페이지로 리다이렉트
        return Promise.reject(error);
      }

      // 기타 오류 처리
      alert(`오류 발생: ${error.response.data.message || '알 수 없는 오류'}`);
      router.push('/error/general'); // 일반 오류 페이지로 리다이렉트
    } else {
      // 네트워크 오류 처리
      alert('네트워크 오류가 발생했습니다. 인터넷 연결을 확인해주세요.');
    }

    return Promise.reject(error); // 오류를 다음으로 전파
  }
);

export default axiosInstance;

 

코드상에서 api 호출 예시는 아래와 같다. intercepter.js 를 먼저 타기 때문에 일괄로 관리하기에 효율적이다. 

import axios from '@/path/to/interceptor'; // interceptor.js 경로

// API 요청 예시
axios.get('/api/example')
  .then(response => {
    // 성공적으로 데이터를 받아온 경우 처리
  })
  .catch(error => {
    // 에러 처리 (여기서는 interceptor가 처리하므로 추가 필요 없음)
  });
728x90
728x90

1.애플 개발자 계정 설정

먼저, 애플개발자계정에서 앱을 등록하고,"SigninwithApple"기능을 활성화 해야합니다.이 과정에서 BundleID와 관련된 설정을 하게 됩니다.

 

2.필요한 라이브러리 설치

리액트에서 애플로그인을 쉽게구현하기 위해react-apple-login같은 라이브러리를 사용할수 있습니다.다음과 같이 설치합니다.

npm install react-apple-login

 

3. 로그인 버튼 구현

애플로그인에서 AppleLogin 라이브러리를 사용한다면 한가지 유의할 점이 있다. 아래와 같이 responseMode 를 query 보내게 되면 이메일 계정 정보를 선택하는 화면이 노출 되지 않는다. 단순히 애플 로그인만 사용 할수 있으니 이메일정보를 받아와야 하는 프로젝트라면 post 방식을 이용해야 한다. 

import React from 'react';
import AppleLogin from 'react-apple-login';

const AppleLoginButton = () => {
  const handleSuccess = (response) => {
    console.log("로그인 성공:", response);
    // 서버에 response를 보내서 사용자 정보를 처리합니다.
  };

  const handleError = (error) => {
    console.error("로그인 실패:", error);
  };

  return (
    <AppleLogin
      clientId="com.yourapp.identifier" // 애플 개발자 계정에서 등록한 클라이언트 ID
      redirectURI="https://yourapp.com/auth/apple/callback" // 리다이렉트 URI
      responseType="code"
      responseMode="query"
      usePopup={true} // 팝업으로 로그인할지 여부
      onSuccess={handleSuccess}
      onError={handleError}
    />
  );
};

export default AppleLoginButton;

 

4. 서버 백엔드 처리

애플 로그인 후, 받은 인증 코드를 서버로 전송하여 사용자 정보를 가져오는 과정이 필요합니다. 서버에서는 애플의 API를 호출하여 사용자 정보를 검증하고, 필요한 경우 데이터베이스에 저장합니다.

 

5. 애플 로그인 api 예시 (Node.js)

const axios = require('axios');

const verifyAppleToken = async (token) => {
  const response = await axios.post('https://appleid.apple.com/auth/token', {
    // 필요한 파라미터 추가
  });
  return response.data;
};

 

728x90

+ Recent posts