팀 프로젝트 - 소셜 로그인(구글)

BooKi·2022년 3월 30일
0
post-thumbnail

팀 프로젝트 - 소셜 로그인(구글)

카카오 로그인 바뀐 점

일단 저번에는 인가코드만 백으로 넘기는 것 까지 구현하였다
근데 조금 방식이 변경되어서 액세스 코드를 넘기기로 하였다
우선 RedirectURI 를 우리 사이트 회원가입 시에 필요한 추가정보 입력하는 곳으로 두었다
그리고 추가정보 입력하는 곳에 들어와서

register 버튼을 누르면 인가코드로 액세스 토큰을 받아오고 액세스 토큰을 백으로,
추가 정보 입력한 것과 마케팅에 동의했는지를 백으로 보낸다

import axios from 'axios';
import React, { useState, useEffect } from 'react'
import qs from "qs";

export function ktoken() {
  

  const REST_API_KEY = "본인 API KEY";
  const REDIRECT_URI = "http://localhost:3000/extrainfo";
  const CLIENT_SECRET = "5kIEwgPacM7aV9m1Yk6BXRqdaTLe2jh1";
  
  const code = new URL(window.location.href).searchParams.get("code");
  const getToken = async () => {
    const payload = qs.stringify({
      grant_type: "authorization_code",
      client_id: REST_API_KEY,
      redirect_uri: REDIRECT_URI,
      code: code,
      client_secret: CLIENT_SECRET,
      },console.log(`code: ${code}`));

    // access token 가져오기
    const res = await axios.post(
     "https://kauth.kakao.com/oauth/token",
      payload
    );
      
    const token = res.data.access_token
    console.log(token)

    let body = {
      token: token,
      registrationId: "KaKao"
    }

    axios.post('/api/token', body) //토큰, 추가 정보 전송
    .then(res => {
      if(res.data.success){
        console.log(res.data)
      }
    })
    .catch(err => console.log(err))
    };
  
  return getToken()
}


export default ktoken

테스트 하느라고 파일 이름을 제대로 못지었는데 ktoken은 카카오톡 토큰을 받아오는 컴포넌트 이다

import React from 'react'

function MainPage() {
  const REST_API_KEY = "본인 API KEY";
  const REDIRECT_URI = "http://localhost:3000/extrainfo";
  const KAKAO_AUTH_URL = `https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code`;
    
  return (
    <div>
      <a href={KAKAO_AUTH_URL}>Kakao Login</a>
    </div>
  )
}

export default MainPage

이부분은 메인페이지를 보여주는 곳이다
메인페이지에서 하이퍼링크를 클릭하면 카카오로 이동되고 '동의하고 계속하기'를 클릭하면 추가정보로 이동하는 것이다

import axios from 'axios';
import React, { useState, useEffect } from 'react'
import { useNavigate } from "react-router-dom";
import * as ktoken from "./ktoken"

function ExtraInformation(props) {
  const navigate = useNavigate()
  const [NickName, setNickName] = useState("")
  const [allCheck, setAllCheck] = useState(false);
  const [ageCheck, setAgeCheck] = useState(false);
  const [useCheck, setUseCheck] = useState(false);
  const [marketingCheck, setMarketingCheck] = useState(false);

  const onNickNameHandler = (event) => {
    setNickName(event.currentTarget.value)
  }

  const allBtnEvent =()=>{
    if(allCheck === false) {
      setAllCheck(true);
      setAgeCheck(true);
      setUseCheck(true);
      setMarketingCheck(true);
    }else {
      setAllCheck(false);
      setAgeCheck(false);
      setUseCheck(false);
      setMarketingCheck(false);
    } 
  };
  
  const ageBtnEvent =()=>{
    if(ageCheck === false) {
      setAgeCheck(true)
    }else {
      setAgeCheck(false)
    }
  };
  
  const useBtnEvent =()=>{
    if(useCheck === false) {
      setUseCheck(true)
    }else {
      setUseCheck(false)
    }
  };
  
  const marketingBtnEvent =()=>{
    if(marketingCheck === false) {
      setMarketingCheck(true)
    }else {
      setMarketingCheck(false)
    }
  };

  useEffect(()=>{
    if(ageCheck===true && useCheck===true && marketingCheck===true){
      setAllCheck(true)
    } else {
      setAllCheck(false)
    }
  }, [ageCheck,useCheck, marketingCheck])

  const onSubmitHandler = (event) => {
    event.preventDefault();

    if(ageCheck===true && useCheck===true){ //필수동의사항 체크
      ktoken.ktoken()

      let body = {
        nickName: NickName,
        agreeMarketing: marketingCheck
      }
      axios.post('/api/extraInfo', body) //토큰, 추가 정보 전송
      .then(res => {
        if(res.data.success){
          navigate('/')
          console.log(res.data)
        }
      })
      .catch(err => console.log(err))
    } else {
      alert("필수 사항을 체크하여 주십시오.")
    }
  }

  return (
    <div style={{
      display: 'flex', justifyContent: 'center', alignItems: 'center',
      width: '100%', height: '100vh'
    }}>
      <form style={{ display: 'flex', flexDirection: 'column' }}
        onSubmit={onSubmitHandler}>
        <label>닉네임</label>
        <input type="text" value={NickName} onChange={onNickNameHandler} />

        <div>
        		<input type="checkbox" id="all-check" checked={allCheck} onChange={allBtnEvent}/>
        		<label>전체동의</label>
        </div>

        <div>
        		<input type="checkbox" id="check1" checked={ageCheck} onChange={ageBtnEvent}/>
        		<label>만 14세 이상입니다 <span >(필수)</span></label>
        </div>

        <div>
        		<input type="checkbox" id="check2" checked={useCheck}  onChange={useBtnEvent}/>
        		<label>이용약관 <span >(필수)</span></label>
        </div>
        
        <div>
        		<input type="checkbox" id="check3" checked={marketingCheck}  onChange={marketingBtnEvent}/>
        		<label>마케팅 동의 <span >(선택)</span></label>
        </div>

        <br />
        <button type="submit">
          Register
        </button>
      </form>
    </div>
    
  )
}

export default ExtraInformation

이 부분이 추가정보를 입력하는 곳이다

import "./App.css";
import React from 'react';
import ExtraInformation from "./components/ExtraInformation"
import ExtraInformation2 from "./components/ExtraInformation2"
import { BrowserRouter as Router, Route, Routes} from "react-router-dom";
import MainPage from "./components/MainPage";


 function App() {
   return (
     <Router>
     <div className="App">
       <Routes>
         <Route path="/" element={<MainPage />} />
         <Route path="/extrainfo" element={<ExtraInformation />} />
         <Route path="/extrainfo2" element={<ExtraInformation2 />} />
       </Routes>
     </div>
     </Router>
   );
 }
 export default App;

이건 App.js이다

이제 구글도 이런식으로 구현해보자

구글 소셜 로그인

우선 구글 소셜 로그인을 구현하기 위해 카카오와 똑같이 구글링을 하였다
이번에는 이 블로그를 참고하면서 만들었다

우선 하단에 있는 내용처럼 클라우드 구글 플랫폼에서 설정을 해주어야 한다
프로젝트 설정은 참고한 블로그에 상세하게 나와있다

import React from 'react';
import GoogleLogin from 'react-google-login';
import axios from 'axios';
import { useNavigate } from "react-router-dom";

const clientId = "클라이언트ID";

export function Google({ onGoogleLogin }){
  const navigate = useNavigate()
  const onSuccess = async(response) => {

    const token = response.tokenObj.access_token
    console.log(token)

    let body = {
      token: token,
      registrationId: "Google"
    }

    axios.post('/api/token', body) //토큰, 추가 정보 전송
    .then(res => {
      if(res.data.success){
        console.log(res.data)
        navigate('/extrainfo2')
      }
    })
    .catch(err => console.log(err))
  }

  const onFailure = (error) => {
    console.log(error);
  }

  return (
    <GoogleLogin
      clientId={clientId}
      responseType={"id_token"}
      onSuccess={onSuccess}
      onFailure={onFailure}
      button="Google"
    />
  )
}

export default Google

이렇게 Google.js 컴포넌트를 만들고 MainPage.js에 Google.js를 추가해주었다

import React from 'react'
import Google from "./Google";

function MainPage() {
  const REST_API_KEY = "본인 API KEY";
  const REDIRECT_URI = "http://localhost:3000/extrainfo";
  const KAKAO_AUTH_URL = `https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code`;
    
  return (
    <div>
      <a href={KAKAO_AUTH_URL}>Kakao Login</a>
      <Google/>
    </div>
  )
}

export default MainPage

그런데 아무리 생각해도 추가사항 페이지에서 구글에서 넘어왔는지 카카오에서 넘어왔는지 파악할 방법이 생각이 나지 않았다
그래서 그냥 추가사항 페이지를 똑같이 하나 더 만들고 구글 함수를 불러오도록 바꿨다

import axios from 'axios';
import React, { useState, useEffect } from 'react'
import { useNavigate } from "react-router-dom";
import * as Google from "./Google"

function ExtraInformation2(props) {
  const navigate = useNavigate()
  const [NickName, setNickName] = useState("")
  const [allCheck, setAllCheck] = useState(false);
  const [ageCheck, setAgeCheck] = useState(false);
  const [useCheck, setUseCheck] = useState(false);
  const [marketingCheck, setMarketingCheck] = useState(false);

  const onNickNameHandler = (event) => {
    setNickName(event.currentTarget.value)
  }

  const allBtnEvent =()=>{
    if(allCheck === false) {
      setAllCheck(true);
      setAgeCheck(true);
      setUseCheck(true);
      setMarketingCheck(true);
    }else {
      setAllCheck(false);
      setAgeCheck(false);
      setUseCheck(false);
      setMarketingCheck(false);
    } 
  };
  
  const ageBtnEvent =()=>{
    if(ageCheck === false) {
      setAgeCheck(true)
    }else {
      setAgeCheck(false)
    }
  };
  
  const useBtnEvent =()=>{
    if(useCheck === false) {
      setUseCheck(true)
    }else {
      setUseCheck(false)
    }
  };
  
  const marketingBtnEvent =()=>{
    if(marketingCheck === false) {
      setMarketingCheck(true)
    }else {
      setMarketingCheck(false)
    }
  };

  useEffect(()=>{
    if(ageCheck===true && useCheck===true && marketingCheck===true){
      setAllCheck(true)
    } else {
      setAllCheck(false)
    }
  }, [ageCheck,useCheck, marketingCheck])

  const onSubmitHandler = (event) => {
    event.preventDefault();

    if(ageCheck===true && useCheck===true){ //필수동의사항 체크
      //Google.onSuccess()

      let body = {
        nickName: NickName,
        agreeMarketing: marketingCheck
      }
      axios.post('/api/extraInfo', body) //토큰, 추가 정보 전송
      .then(res => {
        if(res.data.success){
          navigate('/')
          console.log(res.data)
        }
      })
      .catch(err => console.log(err))
    } else {
      alert("필수 사항을 체크하여 주십시오.")
    }
  }

  return (
    <div style={{
      display: 'flex', justifyContent: 'center', alignItems: 'center',
      width: '100%', height: '100vh'
    }}>
      <form style={{ display: 'flex', flexDirection: 'column' }}
        onSubmit={onSubmitHandler}>
        <label>닉네임</label>
        <input type="text" value={NickName} onChange={onNickNameHandler} />

        <div>
        		<input type="checkbox" id="all-check" checked={allCheck} onChange={allBtnEvent}/>
        		<label>전체동의</label>
        </div>

        <div>
        		<input type="checkbox" id="check1" checked={ageCheck} onChange={ageBtnEvent}/>
        		<label>만 14세 이상입니다 <span >(필수)</span></label>
        </div>

        <div>
        		<input type="checkbox" id="check2" checked={useCheck}  onChange={useBtnEvent}/>
        		<label>이용약관 <span >(필수)</span></label>
        </div>
        
        <div>
        		<input type="checkbox" id="check3" checked={marketingCheck}  onChange={marketingBtnEvent}/>
        		<label>마케팅 동의 <span >(선택)</span></label>
        </div>

        <br />
        <button type="submit">
          Register
        </button>
      </form>
    </div>
    
  )
}

export default ExtraInformation2

이렇게 하였고 메인페이지는 아래와 같다

노드로 서버를 만들어서 백으로 post 해보았고 제대로 카카오, 구글 둘다
데이터가 넘어가는걸로 확인되었다!!
이제 다시 리액트 공부를 하자!

profile
성장을 보여주는 기록

0개의 댓글