카카오 소셜로그인 구현하기
1. 인가코드 받기 및 플랫폼 추가
kakao develpoers에서 인가 코드를 받을 수 있으며 플랫폼을 추가할 수 있다.
kakao developers 링크
2. Redirect URI 설정
로그인 성공시 Redirect할 URI의 주소를 작성한다.

3. 인가코드 받기
인가코드는 Redirect URI를 통해서 받을 수 있다.
KAKAO_AUTH_URL의 경로로 요청을 보내면, Redirect URI로 이동하면서 인가 코드를 발급 받는다.
이때, client_id, redirect_uri, response_type이 필수로 담겨야 한다.
client_id는 REST API키, redirect_uri에는 2. Redirect URI 설정에서 작성한 URI, reponse_type에는 code 고정 값을 담으면 된다.

Key는 공개되지 않는 것이 보안에 좋으므로 따로 파일을 생성하여 관리한다. 해당 파일은 .gitignore
에 작성하여 깃허브에 업로드되지 않도록 한다.

카카오로 시작하기 버튼을 클릭하면 지정한 Redirect URI로 이동하여 인가코드를 얻을 수 있다.
4. Redirect 주소 Router 설정
Redirect URI에 작성했던 successlogin으로 이동할 수 있도록 라우터를 설정해준다. 라우터를 설정하지 않으면 페이지가 존재하지 않아서 이동할 수 없다.

5. 사용자 토큰 받기
버튼을 클릭하면 localhost:3000/successogin?code=-4Wr…
로 이동하는데 -4Wr…부분은 카카오에서 제공한 인가코드이다. 해당 인가코드는 매번 변경된다. 따라서 인가코드를 사용하여 토큰을 가져온다.
토큰은 POST 방식으로 카카오에서 얻을 수 있다. 파라미터에 인가 코드가 필요한데, 이 인가 코드를 사용하기 위해서 URL에 담겨있는 뒷부분을 추출한다.
const location = useLocation();
const KAKAO_CODE = location.search.split('=')[1];
fetch 함수를 이용하여 POST 방식으로 요청을 보내 localstorage에 토큰을 저장한다.
토큰을 정상적으로 잘 받아서 로그인이 되었다면 자동으로 Redirect로 설정한 페이지로 이동한다.
로그인에 실패했다면 else 부분의 navigate(’주소’)
로 이동한다.

4. 여러 페이지 생성
-
로그인 실패 페이지

-
로그인 성공 페이지

5. 실제 구현된 페이지

로그인 페이지

카카오 소셜 로그인

카카오 소셜 로그인 정보 제공 동의

로그인 성공 페이지

로그인 실패 페이지
트러블 슈팅
localStorage에 토큰 저장 안됨
-
문제
localStorage에 토큰이 저장 안된다…
에러 코드도 따로 발생하지 않아서 어떤게 원인인지는 잘 모르겠다…
ERR_SSL_PROTOCOL_ERROR를 검색했을때, 크롬 문제일 수도 있다고 해서 사파리로 접속했으나 똑같이 에러 발생. 모바일로 접속해도 똑같이 에러 발생..
캐시 삭제 및 강한 새로고침을 해도 똑같이 에러가 발생한다.
KakaoLoginData.js에 담아둔 값들도 정상적으로 넘어온다. 코드도 참고 자료를 바탕으로 작성했으나, 토큰이 localStorage에 저장이 안된다.
-
해결
REDIRECT_URI
의 주소를 https로 설정해둬서 안됐다.. localhost라 http로 했어야 했는데..ㅋ
종합소감
카카오에서 REST API KEY 발급받아 카카오 소셜 로그인을 구현해보았다. 이전에, MOA WEBTOON 프로젝트를 진행했을 때, 네이버와 카카오 소셜 로그인을 구현했었다. 하지만, 나는 그저 버튼만 만들었을 뿐 실제로 기능 구현은 백엔드 분이 했었다. 그때 옆에서 보았던 것을 되새기고 참고 자료의 글을 읽고 공부하면서 구현해 보았다.
간단하게 생각했지만.. 전혀 간단하지만은 않았다 ^^.. 물론 다 하고 느낀 것은 내가 능숙해지면 이건 쉽게 할 수 있을 것이다! 라는 건 느껴졌다. 다음 번에는 더욱 빠르게 구현 할 수 있을 것 같다!
참고자료
카카오 소셜로그인 프론트엔드 (리액트) 파트
Kakao Developers
[React] 카카오 소셜 로그인 구현하기
Styled Component 적용하기
마켓컬리 접속 시, 뜨는 팝업창에 스타일드 컴포넌트를 사용했다.


PopupWrapper와 ButtonBox를 생성하여 스타일을 적용해줬고, button 스타일은 새로 생성하는 것이 아니라 태그에 스타일드 컴포넌트를 사용하여 스타일을 적용하였다.

화면에 잘 출력되는 것을 확인할 수 있다!
반응형 웹 구현

미디어 쿼리를 사용하여 화면이 1260px 이하 일 때, 다음과 같이 스타일이 변경되도록 설정하였다.



화면의 비율이 줄어들어도 아이템 잘림이 없이 잘 줄어든 것을 확인할 수 있다.
문제 및 해결
- 중첩 적용 안됨 (미디어쿼리)
- 문제
content-right의 left를 36px로 설정했는데, 화면 사이즈가 1260px이 되었을 때, left 설정했던 것을 없애려고 left: 0;을 하였으나 중첩이 적용되지 않았다.
- 해결
중첩이 안되는 이유는 찾지 못했지만..
해결은
!important
를 사용하여 left: 0;이 무조건 적용하도록 했다.
소감
미디어 쿼리는 사용해본 적이 있지만 styled-component는 처음 배우고 사용해 보았다. 처음에는 styled-component를 복잡하게 생각하고 느꼈는데, 새삼 이것처럼 간단하게 배울 수 있는건 없는 것 같다. 시작도 안하고 지레 겁먹는 것은 좀 고쳐야 겠다..!
반응형 웹을 만들기 위해서 미디어쿼리를 사용했는데, 생각해줘야 할 것이 은근 많았다. 그래서 화면의 비율에 따라 잘 줄어드는 것을 보면서 뿌듯했다..!
useEffect를 사용하여 팝업창 띄우기
팝업창 만들기 (스타일)
팝업창은 position을 fixed로 설정하여 스크롤을 해도 화면에 고정되도록 한다.
z-index를 사용하여 화면의 최상단에 위치하도록 한다. (z-index는 position 값이 존재해야 적용된다. 단, position:static은 불가)

팝업창 만들기 (기능)
팝업창의 닫기와 오늘 하루 안 보기 기능을 만들기 위해서는 localStorage에 대해 알아야 한다.
localStorage를 사용하여 브라우저를 다시 실행해도 정보를 저장하도록 한다. localStorage.setItem
으로 데이터를 저장하는데, key는 homeVisited로 value는 팝업창을 띄운 시간에 24시를 더한 값(expires)이다.


useState를 통해 state를 관리한다.
기본값은 false로 setShowMainPop(false)가 되면서 팝업창 노출이 없다.
만약, 기본 값을 true로 할 경우, ‘오늘 하루 안보기’를 클릭하여도 리렌더링을 하면 팝업창이 나타난다.
HOME_VISITED 정수에 localStorage에서 homeVisited를 가져온다.
useEffect를 사용하여 ‘오늘 하루 안보기’ 버튼을 클릭하면, 리렌더링을 하여도 팝업창이 뜨지 않도록 한다.
today는 오늘의 시간(즉, 현재 시간)을 담은 정수이다.
handleMainPop은 화살표 함수에서 실행한 값을 저장한다.
만약, localStorage에 저장된 시간이 존재(true)하고 현재 시간(today)이 localStorage의 시간보다 작다면(true) return을 한다.
이때, return은 useState에서 기본값으로 세팅한 false이다. 즉, setShowMainPop(false)가 되면서 팝업창 노출이 없다.
localStorage의 시간: 이전에 팝업창이 떴을 때, ‘오늘 하루 보지 않기’를 클릭한 시간 + 24시간
다른 조건으로는, 만약 localStorage에 저장된 시간이 없거나(false) localStorage에 저장된 시간이 현재 시간(today)보다 작다면 setShowMainPop(true)를 실행하여 팝업창이 노출된다.
window.setTimeout에 실행할 함수는 handleMainPop이며 지연 시간은 0.1초이다. 0.1초 후에 해당 함수를 실행하도록 한다.
setTimeout()은 코드를 바로 실행하지 않고 일정 시간을 기다린 후에 실행할 때 사용한다. 첫번째 인자는 실행할 코드를 담은 함수, 두번째 인자는 지연 시간(ms)
❤️🔥 한 줄 요약
setShowMainPop(false) → 팝업창 노출 X
setShowMainPop(true) → 팝업창 노출 O
localStorage를 통해 ‘오늘 하루 안 보기’를 클릭한 시간 저장
참고
[React] 오늘 하루 안보기/ 24시간 동안 안보기 팝업 구현
자바스크립트의 setTimeout()과 setInterval() 함수
React ‘n일 동안 보지 않기’ 팝업 만들기
종합 소감
마켓컬리 클론코딩에 어떤 라이프사이클을 적용할 지 고민을 많이 했다.
그래서 라이프사이클을 통해 팝업창을 띄우기로 했다.
사실 직접 만들어서 해보려고 했지만… 나의 능력 부족으로 인해 ㅎ.. 다른 분의 코드를 참고하여 작성하였다.
대신의 해당 코드를 면밀히 이해하려고 했다. 그래서 내가 작성한 코드는 아니지만 어느정도 나의 지식으로 습득할 수 있었다.
Router 사용하기
router의 적용 순서는 다음과 같다.
BrowserRouter 연결 → 페이지 컴포넌트 만들기 → Route path 연결 → Link 컴포넌트 연결
- BrowserRouter 연결
App.js 파일에 react-router-dom에 내장되어 있는 BrowserRouter 컴포넌트를 불러온다.
- 페이지 컴포넌트 만들기
Market과 Beauty 페이지 컴포넌트를 만들었다.
- Route path 연결
Route 컴포넌트로 해당하는 URL을 지정한다. URL 지정은 path를 통해 지정한다.

- Link 컴포넌트 연결
Link 컴포넌트는 클릭하면 다른 주소로 이동시켜준다.
나는 페이지를 이동할 버튼이 Header 컴포넌트에 존재하기 때문에 Header.js에서 Link 컴포넌트를 연결했다.


문제 및 해결
Link 컴포넌트 사용시 밑줄 제거
- 문제
Link 컴포넌트를 사용하면 link 기본 스타일이 적용된다.
- 해결
Link 컴포넌트에
style=
을 사용하면 Link의 기본적인 스타일 속성이 사라진다.
참고
[React] Link to 밑줄 없애기
종합소감
이번 umc 4주차 워크북 미션은 기존에 만들었던 프로젝트에 라우팅을 적용해보는 것이었다. 이전에 강의로 공부를 한 적이 있긴 하지만… 영상의 도움없이 혼자 적용해 보는 것은 처음이라, 이전에 정리했던 정리글도 다시 확인하고 여러 글들을 서칭했다.
이번에 라우팅을 적용하고 다른 팀원들에게 적용하는 방법을 설명하면서 완벽하게 학습을 할 수 있었다. 혼자 서칭하면서 적용하기에 성공하고, 내가 학습한 내용을 다른 사람에게 설명까지 하니 완벽하게 나의 지식이 되어 만족스러웠다.
Swiper 기능 넣기
기존에 만들었던 함수를 작성하려고 했으나, 너무 복잡해지는 것 같아서 swiper 모듈을 설치하여 사용하기로 했다.


-
구현할 기능
5초 후에 자동으로 다음 배너 이미지로 변경하기,
화살표를 클릭하면 앞, 뒤로 배너 이미지 바꾸기
-
swiper 설치
-
swiper 및 css 불러오기
import { Swiper, SwiperSlide } from 'swiper/react';
import { Autoplay, Navigation, Pagination } from 'swiper';
import 'swiper/css';
import 'swiper/css/navigation';
import 'swiper/css/pagination';
나는 5초 뒤에 자동으로 다음 슬라이드로 변경되게 할 것이기 때문에 Autoplay를 불러왔다.
그리고 화살표를 클릭하여 슬라이드를 이동하게 할 것이기 때문에 Navigation과 Pagination을 불러왔다.
-
swiper 적용하기
export default function BannerContainer() {
...
return (
<div className="banner">
<div className="banner-img">
<Swiper
modules={[Navigation, Pagination, Autoplay]}
spaceBetween={50}
slidesPerView={1}
autoplay=
navigation
pagination=
onSlideChange={() => console.log('slide change')}
onSwiper={(swiper) => console.log(swiper)}
>
<SwiperSlide>
<Banner {...banner1} />
</SwiperSlide>
<SwiperSlide>
<Banner {...banner2} />
</SwiperSlide>
<SwiperSlide>
<Banner {...banner3} />
</SwiperSlide>
<SwiperSlide>
<Banner {...banner4} />
</SwiperSlide>
<SwiperSlide>
<Banner {...banner5} />
</SwiperSlide>
</Swiper>
</div>
</div>
);
}
이전 주차에 만들어뒀던 스타일이 존재했기 때문에 최대한 살리고자 .banner
와 .banner-img
박스는 그대로 두었다. 해당 박스 안에 Swiper 컴포넌트를 부르고 해당 컴포넌트안에 SwiperSilde를 원하는 갯수만큼 생성하면 된다.
Swiper에서 보일 슬라이드의 갯수는 1(sildePerview), 5초 뒤에 자동으로 슬라이드 이동(autoplay), 버튼을 통해 슬라이드를 이동하는 것은 true(navigation, pagination)로 설정했다.
나는 기존에 배너 이미지들의 스타일이 존재했기 때문에 해당 부분은 최대한 살리고, img의 link값만 변경해주기 위해서, SwiperSilde안에 Banner 컴포넌트(내가 만들었던 배너 이미지)를 넣어주었다.
Banner이미지는 img태그만 존재하기 때문에, 결과적으로는 SwiperSlide 컴포넌트 안에는 img태그가 들어있는 것이다.
-
Swiper를 적용하면서 문제점
-
css 파일을 가져올 때, 참고했던 문서들과는 불러오는 것이 달라서.. 에러가 엄청 떠서 약간 애를 먹었다..
그래서 일단, navigation, pagination은 삭제하고 swiper의 css만 불러오니 잘 되길래, 공식 문서처럼 navigation과 pagination의 css를 불러왔더니 잘 적용되었다.
-
img태그(Banner 컴포넌트)를 넣는 위치를 찾느라 시간이 좀 걸렸다.
처음에는 그냥 SwiperSlide 컴포넌트 안에 {…banner1}를 하는 바람에 당연히 에러가 발생했고.. 태그 사이에 넣었더니 또 당연히 에러가 발생했었다.
그러다가 Banner 컴포넌트를 다시 확인하고.. 생각해보니 Banner 컴포넌트를 모두 불러와서 banner1 (props)를 넣어줘야 내가 원하는 이미지의 링크가 잘 들어간 img 태그가 만들어지는 것을 깨닫고..! SwiperSlide 태그 사이에 Banner 컴포넌트를 넣었더니 잘 돌아갔다..!
-
참고자료
Swiper React Components
[React] 리액트에서 Swiper.js 를 사용해보자. Swiper 슬라이드 사용예제, Navigation의 arrow 버튼 커스텀하기
[#. React] React에서 swiper 사용하기, 배너 슬라이드 사용하기
useState를 사용하여, 버튼 클릭시 페이지 변환
useSate를 사용해서 변환하려고 하고 있으나 문제 해결 못함…뭔가 로직을 잘 못짜고 있는 느낌..?!
Header 컴포넌트에서 마켓컬리 버튼을 클릭하면 마켓컬리 페이지(Market 컴포넌트)로, 뷰티컬리 버튼을 클릭하면 뷰티컬리 페이지(Beauty 컴포넌트)만 보이게 하고 싶은데..
Market과 Beauty를 출력하는 것은 App.js에 있고, 버튼은 Header 컴포넌트에 있으니까..? 두개를 어떻게 이어야 할 지 잘 모르겠음…!!!
🚨해결!🚨
이벤트 핸들러를 안 해줘서 적용이 안됐다..! ㅜ..
내가 생각한 방식으로 useState 사용해서 페이지 전환이 되는 것은 맞았다!

App.js에 다음과 같이 코드 작성한다.
Header 컴포넌트에 props를 넘겨준다. onClick 하면 onChange가 실행되고 해당 값에 맞춰 page(setPage)가 변환된다. page의 값이 market이면 Market 컴포넌트 보여주기, beauty라면 Beauty 컴포넌트를 보여준다.
그리고 color에 들어오는 값이 market이라면 activeColor라는 이름의 클래스를 추가해준다. 값이 beauty일때도 마찬갖css에서 activeColor 클래스 추가시, 글자 색상이 보라색으로 작성했다.


종합소감
이전에 만들었던 걸 React로 다시 하느라 애를 먹은 부분이 많았다…
swiper라던가.. 페이지 변환이라던가…
그래도 내가 짰던 코드들을 컴포넌트로 분리하는 작업을 하면서 어떻게 컴포넌트를 나누면 좋을지 생각해보고, 직접 활용하면서 이런게 컴포넌트구나!를 깨달았다. 역시.. 따라하는게 아니라 직접 고심해보고 해야.. 머리에 잘 남는 것 같다.
그리고 state랑 props는 이론은 잘 알겠는데 실 적용을 못하겠었다. 그래서 특별 과외선생님(?)에게 물어봐서 실제 내 코드에 적용해보면서 조금은 이해가 되었다. 앞으로 react 쓸일은 많으니까 계속 만들어보면서 익혀야 겠다.