[ React ] 정말 쉽다! 카카오 소셜 로그인 프론트에서 이해하고 구현하기.

(React) 소셜 로그인 구현 (카카오, 구글, 네이버)

Kakao Developers

// 로그아웃 관련 문제
const logOut = () => {
    axios.post(import.meta.env.VITE_BASE_URL + "/api/consumers/logout", null, {
      headers: {
        Authorization: `Bearer ${localStorage.getItem("access-token")}`
    }
    })
    .then((res) => {
      console.log(res)
      window.alert("로그아웃 했습니다.")
      // console.log("로그아웃 했습니다.")
      localStorage.clear()
      sessionStorage.clear()
      navigate("/")
    })
    .catch((err) => {
      console.error(err)
      console.log("로그아웃 실패!")
    })
  }
  
// 로컬스토리지에 access-token 값은 삭제가 되지만, 쿠키가 남아서
// 다시 로그인을 시도하면, 기존의 로그인했던 아이디로 자동 로그인이 되는 것 같다.
// friends.jsx 240327
// 친구 목록만 불러온 상태

// 이미지 import
import refreshIcon from '/imgs/refreshIcon.png'
import searchIcon from '/imgs/searchIcon.png'
import searchIconTrue from '/imgs/searchIconTrue.png'
import filterIcon from '/imgs/filterIcon.png'
import filterIconTrue from '/imgs/filterIconTrue.png'
import normalProfileImage from '/imgs/normalProfileImage.png'

// react 관련 import
import { useEffect, useState } from 'react';
import axios from 'axios'

function Friends() {
    const TEST_URL = "<https://j10d201.p.ssafy.io>"
    const [isSearch, setIsSearch] = useState(false)
    const [isFilter, setIsFilter] = useState(false)
    const [friends, setFriends] = useState([])

    const searchState = () => {
        setIsSearch(prevSearch => !prevSearch)
    }
    const filterState = () => {
        setIsFilter(prevFilter => !prevFilter)
    }

    // useEffect(() => {
    //     axios.get(TEST_URL + `/api/friends/${consumerId}`, {
    //         headers: {
    //             Authorization: `Bearer ${localStorage.getItem("access-token")}`
    //         }
    //     })
    //         .then((res) => {
    //             console.log(res)
    //             setGood("잘 된다.")
    //         })
    //         .catch((err) => {
    //             console.error(err)
    //             setGood("안 된다.")
    //         })
    //     console.log("토큰 : ", localStorage.getItem("access-token"))
    // }, [])

    useEffect(() => {
        axios.get(TEST_URL + "/api/friends/kakao", {
            headers: {
                Authorization: `Bearer ${localStorage.getItem("access-token")}`
            }
        })
            .then((res) => {
                console.log(res.data.data.elements)
                setFriends(res.data.data.elements)
                console.log("친구목록 받아왔다.")
            })
            .catch((err) => {
                console.error(err)
                console.log("안 된다 ㅠㅠ")
            })
    }, [])

    return (
        <div className="justify-start main-layer top-[70px] fixed">
            <div className="w-full h-[40px] flex flex-row justify-between">
                <div className="flex flex-row items-center p-3 ">
                    <p className=" font-cusFont3 font-bold text-lg p-2.5">친구 {friends.length}</p>
                    <button>
                        <img src={refreshIcon} alt="동기화아이콘" />
                    </button>
                </div>

                <div className=' flex flex-row items-center p-2.5'>
                    {isSearch ? <input type="text" className=' w-[160px] h-[25px] border border-cusColor3 rounded-[10px] m-1' /> : ''}
                    <button onClick={searchState} className='p-1 '>
                        <img src={isSearch ? searchIconTrue : searchIcon} alt="검색아이콘" />
                    </button>
                    <button onClick={filterState} className='p-1 '>
                        <img src={isFilter ? filterIconTrue : filterIcon} alt="필터아이콘" />
                    </button>
                </div>
            </div>

            <div className='max-w-[500px] w-full h-full flex flex-col items-center justify-start'>
                {/* <p className='text-4xl font-cusFont5'>친구목록 나올거에요</p> */}
                <div className="w-full h-full gap-3 overflow-y-scroll">
                    {friends.map((friend, index) => (
                        <div key={index} {...friend} className='flex flex-row items-center justify-between gap-3 m-2'>
                            <div className='flex flex-row items-center gap-3'>
                                <img src={friend.profileThumbnailImage === "" ? normalProfileImage : friend.profileThumbnailImage} alt="카톡프사" className='w-[100px] h-[100px] rounded-lg' />
                                <h1>{friend.profileNickname}</h1>
                            </div>
                            {friend.profileThumbnailImage === "" ? "기본프사" : "👍"}
                        </div>
                    ))}
                </div>
            </div>
        </div>
    )
}

export default Friends;
// 집 가기전
import { useEffect, useState } from "react";
import refreshIcon from "/imgs/refreshIcon.png";
import searchIcon from "/imgs/searchIcon.png";
import searchIconTrue from "/imgs/searchIconTrue.png";
import filterIcon from "/imgs/filterIcon.png";
import filterIconTrue from "/imgs/filterIconTrue.png";
import fish from "/imgs/fish.PNG"
import axios from "axios";

function Friends() {
  const [isSearch, setIsSearch] = useState(false);
  const [isFilter, setIsFilter] = useState(false);
  const [friends, setFriends] = useState([])

  const searchState = () => {
    setIsSearch((prevSearch) => !prevSearch);
  };
  const filterState = () => {
    setIsFilter((prevFilter) => !prevFilter);
  };

  // 카카오톡 친구목록 불러오는 api
  useEffect(() => {
    axios.get(import.meta.env.VITE_BASE_URL + "/api/friends/kakao", {
      headers: {
        Authorization: `Bearer ${localStorage.getItem("access-token")}`
      }
    })
      .then((res) => {
        console.log(res.data.data.elements)
        setFriends(res.data.data.elements)
        console.log("친구목록 받아왔다.")
      })
      .catch((err) => {
        console.error(err)
        console.log("안 된다 ㅠㅠ")
      })
  }, [])

  return (
	  // 전체 레이어
    <div className="sub-layer top-[40px] justify-start">
    
	    // 친구목록 내 헤더
      <div className="flex flex-row justify-between w-full ">
        <div className="flex flex-row items-center p-3 ">
          <p className=" p-2.5 font-cusFont3 text-lg font-bold">친구 {friends.length}</p>
          <button>
            <img src={refreshIcon} alt="동기화아이콘" />
          </button>
        </div>

        <div className=" flex flex-row items-center p-2.5">
          {isSearch ? (
            <input
              type="text"
              className=" m-1 h-[25px] w-[160px] rounded-[10px] border border-cusColor3"
            />
          ) : (
            ""
          )}
          <button onClick={searchState} className="p-1 ">
            <img
              src={isSearch ? searchIconTrue : searchIcon}
              alt="검색아이콘"
            />
          </button>
          <button onClick={filterState} className="p-1 ">
            <img
              src={isFilter ? filterIconTrue : filterIcon}
              alt="필터아이콘"
            />
          </button>
        </div>
      </div>

			// 친구목록 관련 div
      <div className='max-w-[500px] w-full h-full flex flex-col items-center justify-start'>
        <div className="w-full h-full gap-3 overflow-y-scroll">
          {friends.map((friend, index) => (
            <div key={index} className='flex flex-row items-center justify-between gap-3 m-2'>
              <div className='flex flex-row items-center gap-3'>
                <img src={friend.profileThumbnailImage === "" ? fish : friend.profileThumbnailImage} alt="카톡프사" className='w-[100px] h-[100px] rounded-lg' />
                <h1 className='text-xl font-bold signup-font'>{friend.profileNickname}</h1>
              </div>
              {friend.profileThumbnailImage === "" ? "기본프사" : "👍"}
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

export default Friends;