남의집 사이트를 모티브로 하여 진행한 프로젝트로 자신의 공간에서 모임을 주최하고 이끌어갈 호스트를 중심으로 취향이 맞는 사람들을 연결한다. 연결된 사람들은 가정집, 작업실, 동네가게 등 모임이 진행되는 공간에 모여 공통된 관심사로 대화하며 취향을 나누는 목적으로 만든 커뮤니티 & 예약 사이트이다.
개발기간 : 2022.04.11 - 2022.04.22
Team = {
"Front-end" : ["김재도", "노규현", "박경서"],
"Back-end" : ["이산", "최창환", "황정현"]
}
우리팀은 앞으로 해야 할 모든 티켓들(Backlog), 이번 스프린트에 해야 할 티켓들(This Sprint), 현재 개발중인 티켓들(In Progress), PR 작성 후 리뷰중인 티켓들(In Review), 완료된 티켓들(Done) 으로 탭을 나누었다. 이렇게 해야 할 과제들과 이미 완료된 과제들, 팀 구성원 별로 맡은 업무들과 현재 진행 중인 업무들, 앞으로 해야 할 일들과 이번 주에 당장 해야 할 일들을 보기 좋게 구별하여 업무의 생산성과 효율성을 높일 수 있었다.
또한 앞에서의 몇 번의 프로젝트로 팀원간의 태도와 소통의 중요성을 알았기에 팀원들의 눈에도 나의 진행사항을 쉽게 알릴 수 있도록 작성하려고 노력하였고 기능별로 티켓을 만들 수 있도록 노력하였다. 티켓의 생성도 중요하지만 이 과정에서 나의 해야할 일 과 Blocker를 어떻게 공유할 지, 해야할 일의 우선순위를 정하고 구별하여 팀원에게 잘 전달할 지 고민하였다.
public
├── data
├── images
├── index.html
src
├── components
│ ├── Nav.js
│ ├── Footer.js
├── pages
│ ├── Host
│ ├── Login
│ ├── Main
│ ├── Mypage
│ ├── ProductList
│ ├── Search
├── styles
│ ├── GlobalStyles.js
│ └── Mixin.js
│ └── theme.js
├── index.js
└── Router.js
└── .prettierrc
└── .eslintrc
프로젝트 첫 날, Planning Meeting 에서 호스트 등록 페이지의 결제, 진행관리, 정산 기능을 삭제하면서 마이페이지와 병합하자고 하였지만 프로젝트 도중, 병합하게 되면 마이페이지에서 기능이 생각보다 많아져서 다시 나누는 수정사항이 발생하기도 하였다.
1. 회원가입 및 로그인
- kakaoOAuth(소셜 로그인) 만 구현
- 일반회원가입 로그인(X)
2. 마이페이지
- 후기 리스트, 신청 및 환불 내역, 결제 금액 충전
3. 메인페이지
- 이미지 슬라이드, GNB, FOOTER
4. 카테고리 상품 리스트
- 패스 파라미터를 통한 카테고리별 전체 상품 리스트
5. 상품 디테일 페이지
- 신청예약(예약 기능), 후기
6. 호스트 등록
- 현재의 경우 다른 페이지로 이동 → 마이페이지와 병합될 예정
config.js에서 API를 관리하여 사용하였다.
const BASE_URL = 'http://13.209.8.56:8000';
const API = {
Login: `${BASE_URL}/users/signin`,
Point: `${BASE_URL}/users/point`,
Review: `${BASE_URL}/users/review`,
Aside: `${BASE_URL}/users/userinfo`,
History: `${BASE_URL}/users/reservation`,
Productlist: `${BASE_URL}/places/placelist`,
Product: `${BASE_URL}/places/placeinformation`,
Placehost: `${BASE_URL}/places`,
Placereview: `${BASE_URL}/places`,
Placereservation: `${BASE_URL}/places/reservation`,
Search: `${BASE_URL}/places/search`,
Main: `${BASE_URL}/places/main`,
Hostuser: `${BASE_URL}/users/host`,
Hostcreate: `${BASE_URL}/users/placeregist`,
Hostmain: `${BASE_URL}/places/hostregstlist`,
Userinfo: `${BASE_URL}/users/userinfo`,
Hostinfo: `${BASE_URL}/places/hostinformation`,
};
export default API;
(code=_____)
발급을 요청합니다.카카오 계정으로 로그인
화면이 나타나며 사용자가 직접 입력한 카카오 계정의 자격 정보를 통해 사용자 인증이 이뤄집니다.https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api
카카오 로그인 과정을 이해하기 위해서 위의 카카오 공식 문서를 몇번이나 읽어보고 구글링해서 관련된 kakao REST API 글은 정말 다 읽어본 것 같다. 흐름을 이해한 지금은 남에게 설명할 수 있을 정도지만 처음에는 인가코드, Redirect URI, Access token, Refresh token, id_token 등 생소한 단어들이 너무 많아서 힘들었다. 그리고 인가 코드 발급 시, 정말 많은 인가 코드 관련 에러를 마주쳤는데 대게 아래 3개의 에러를 가장 많이 만났으며, 도대체 어떤 부분을 내가 놓치고 있길래 에러를 잡지 못하는 걸까 답답하여 다시 찬찬히 흐름을 이해해보고, 왜 인가코드를 받지 못하는지? 왜 Redirect URI로 이동하지 못해서 리다이랙션이 안되는지? 이해하기 위해서 공식문서를 읽고 또 읽었다.
KOE101 - 잘못된 앱 키 타입을 사용하거나 앱 키에 오타가 있을 경우
KOE008 - 인가 코드 요청 시 Admin Key를 사용한 경우
KOE006 - 관리자 설정 이슈, 등록되지 않은 Redirect URI를 인가 코드 요청에 사용한 경우
대게 인가코드 관련 에러는 Request URI에서 발생하였다.
카카오 로그인 버튼 클릭 시, https://kauth.kakao.com/oauth/authorize?client_id=${process.env.REACT_APP_CLIENT_ID}&redirect_uri=${process.env.REACT_APP_REDIRECT_URI}&response_type=code
의 주소로 이동한다.
여기서 client_id
는 카카오 앱 REST API 키에서 발급받은 앱키이며 REDIRECT_URI
는 인가 코드가 리다이렉트될 URI 이다. response_type
는 code로 고정이다.
fetch('https://kauth.kakao.com/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;',
},
body: `grant_type=authorization_code&client_id=${process.env.REACT_APP_CLIENT_ID}&code=${code}&redirect_uri=${process.env.REACT_APP_REDIRECT_URI}`,
})
이렇게 필수적인 파라미터들을 포함해서 https://kauth.kakao.com/oauth/token
에 POST로 요청한다. 요청 성공 시 액세스 토큰, 리프레시 토큰과 토큰 정보를 포함한 JSON
객체를 받는다.
{
"token_type": "bearer",
"access_token": "${ACCESS_TOKEN}",
"id_token": "${ID_TOKEN}",
"expires_in": 7199,
"refresh_token": "${REFRESH_TOKEN}",
"refresh_token_expires_in": 86399,
"scope": "profile_image openid profile_nickname"
}
앱 키 같은 경우, 소스코드에 노출이 되어선 보안상 큰 문제이기 때문에 .env
를 root에 만들어서 관리한다. 만들고나면 별거 아니지만 처음 마주친 환경변수 파일이었기 때문에 이 부분도 공부하게 되었다. 꼭 이럴 보안 상황 뿐만 아니라 실제 인증 키와 테스트용 인증 키가 다르게 사용되어야 할 때도, .env
를 이용한다.
Node.js에서 환경변수를 사용할 땐${process.env.REACT_APP_CLIENT_ID}
와 같이 process.env
라는 자바스크립트 내장 전역 객체를 이용하며, 전역 객체이기 때문에 별도로 import 하지 않아도 접근이 가능하다. 환경변수는 아래와 같이 “키=값" 형태로 정의해주면 노드가 실행되는 동안에만 존재하고 프로세스가 종료되면 소멸된다.
REACT_APP_CLIENT_ID = 값
REACT_APP_MAP_KEY = 값
그래서 아래와 같이 운영체제의 명령어를 이용해 노드가 종료되어도 환경변수가 실행될 수 있도록 export 키=값
의 형태로 사용하였다. 하지만 이런 방법은 매우 번거롭고 프로젝트 별 의존성 문제가 발생한다.
export REACT_APP_CLIENT_ID = 값
export REACT_APP_MAP_KEY = 값
그래서 이를 위해 현재는 react-scripts@0.2.3 이상을 사용한다면 환경변수 관리를 위한 라이브러리는 필요없으며, CRA에 포함되있는 react-script
내부 에서 dotenv 라이브러리 처리를 해준다.
dotenv를 사용하는 방법은 다음과 같다.
1.프로젝트 루트에 .env 파일 생성
2.REACT_APP_ 로 시작하는 환경 변수를 거기 에 설정하십시오.
3.구성 요소에서 process.env.REACT_APP_... 로 액세스하십시오.
아, 그리고 당연하지만 주의할 점으로 .env
는 민감한 정보를 담고 있는 파일이기 때문에 꼭 .gitignore
를 통해 스테이징에서 제외시켜 레포에 올라가지 않도록 해야한다.
작성 가능한 후기
에서 작성한 후기는 내가 작성한 후기
탭에서 바로 확인이 가능하며, 놀이터 상세 페이지
에도 바로 반영이 됩니다.작성 가능한 후기
에서 다시 작성 시, 후기 수정이 가능합니다.styled-component를사용해 컴포넌트의 상태를 props로 받아 스타일 적용을 다르게 할 수 있었다.
color: ${props => (props.selectReview === 'First' ? '#000' : '#ddd')};
border-bottom: ${props => props.selectReview === 'First' ? '2px solid #000' : '1px solid #ddd'}; ;
내가 참 useNavigate를 좋아하는 것을 알게되었다. ㅋㅋㅋㅋㅋㅋㅋ
Link
useNavigate
useNavigate
사용Link를 써줘도 충분한 곳에 useNavigate를 남발한 적이 있었다..
styled-components 를 사용할 때 Link 사용은 다음과 같이 쓸 수 있다.
<StyledLink to={`/places/placeinformation/${place_id}`}>
<h2>{title}</h2>
</StyledLink>
const StyledLink = styled(Link)`
margin: 20px auto 0;
height: 50px;
width: 140px;
`;
저번 팀프로젝트 때 가장 고민을 많이 했던 부분들이 응답받은 데이터를 활용하여 어떻게 화면에 그려줄 지, query string이나, path로 동적 라우팅이 어떻게 구현되는지 어려웠는데 그래도 기본적인 것들이 먼저 그려지니까 저번 프로젝트 때보다 더 많은 기능 구현을 할 수 있었던 것 같다. 그냥 쓰는 게 아니라 용도와 흐름을 이해하고 쓰는 useState
와 useEffect
로 로직을 구현하려고 노력하니 며칠전의 나는 어려웠을 이 로직이, 조금씩 구현이 나아진다는 느낌을 스스로 받아서 너무 행복했다. 역시 성장을 스스로 느낀다는 것은 정말 뿌듯쓰...
그리고 정말 좋았던 점은 팀원들 팀워크가 너무 좋았다. 공유 사항이 빨랐고 피드백이 빠르다보니 팀원간의 블로커가 생길 일이 없었던 것 같다. 그만큼 서로의 진행 사항을 인지하고 있었기에 자신이 부딪힌 어려움이 생기면 그 팀원에게 가서 미리 알려주거나 다른 팀원의 분량이더라도 자신이 생각했을 때, 그 로직을 어떻게 구현했을지 궁금하면 가서 물어보거나 서로 서로를 인지하고 챙기는게 보였다. 프로젝트 다 끝나고 짧은 회고시간에 .. 정말 고맙다는 말밖에 할 말이 없었다!!!! 서운한 점..? 없어서 얘기 못했다..
Redux의 사용에 익숙하지 않아서 state를 전달용으로 사용되는 컴포넌트들이 존재한다. 리덕스.. 처음 개념만 이해하면 쓰는 건 어렵지 않다고 하시는데 이번 프로젝트에서 코드 리팩토링을 하면서 리덕스를 적용해볼 시간이 부족하였다. 어서 빨리 리덕스 공부해.........