프로젝트가 끝난 이후, 이제서야 제 현생을 살아가는 느낌이 들어요. 머리도 자르고.. 수선을 맡겨야했던 옷들도 맡기고.. 프로젝트 내내 타이트하게 코드를 짜느라 정신이 없었습니다.. 약 한달이라는 시간동안 메인프로젝트에 많은 것을 정말 집중해서 쏟았던 만큼, 블로그를 많이 적지못했었는데요, 이제서야 자세히 회고록을 써보려합니다.
● 프리 프로젝트에서 적용하고 싶었던 것 -> 메인프로젝트에 적용
프리프로젝트 때, 프로젝트를 진행하면서 많이 느낀 것이 '기획 및 준비단계를 탄탄하게' 해야한다는 점이었습니다. 프리프로젝트에서는 깃컨벤션 및 브렌치 명정도 정하고 시작했었는데요, 시간이 많이 없었던터라 백엔드분들과는 PR컨벤션, 이슈컨벤션, 브렌치 컨벤션, 커밋 컨벤션만 정하게 되었고 프론트엔드분들과는 코드컨벤션, 마일스톤 컨벤션, 폴더 구조까지 함께 정하게 되었습니다.
- 커밋 컨벤션
아래와 같이 커밋 템플릿을 만들어, 매 커밋마다 아래 템플릿을 준수하며 커밋을 기입하였습니다.
# <[type]>: <subject>
##### Subject 50 characters ################# ->
# Body Message
######## Body 72 characters ####################################### ->
# Issue Tracker Number or URL (optional) ->
# --- COMMIT END ---
# Type can be
# feat : 새로운 기능 추가
# fix : 버그/오타(typo)/로직 등 코드를 수정한 경우
# refactor: 코드 리팩토링
# style : 코드 포맷팅, 세미콜론 누락 수정 등 내부 로직 변경이 없이 코드를 수정한 경우
# docs : README 문서 수정
# test : 테스트 코드, 리팩토링 테스트 코드 추가
# chore : 빌드 업무 수정, 패키지 매니저 수정
# remove : 코드/파일 삭제
# dep : 패키지 설치/삭제 등 의존성 관련 수정
# etc : 기타
# ------------------
# Remember me ~
# Capitalize the subject line
# 제목줄은 대문자로 시작한다.
# Use the imperative mood in the subject line
# 제목줄은 명령어로 작성한다.
# Do not end the subject line with a period
# 제목줄은 마침표로 끝내지 않는다.
# Separate subject from body with a blank line
# 본문과 제목에는 빈줄을 넣어서 구분한다.
# Use the body to explain what and why vs. how
# 본문에는 "어떻게" 보다는 "왜"와 "무엇을" 설명한다.
# Can use multiple lines with "-" for bullet points in body
# 본문에 목록을 나타낼때는 "-"로 시작한다.
# ------------------
# <꼬리말>
# 필수가 아닌 optioanl
# Fixes : 이슈 수정중 (아직 해결되지 않은 경우)
# Resolves : 이슈 해결했을 때 사용
# Ref : 참고할 이슈가 있을 때 사용
# Related to : 해당 커밋에 관련된 이슈번호 (아직 해결되지 않은 경우)
# ex) Fixes: #47 Related to: #32, #21
- PR 컨벤션
- 이슈 컨벤션
이슈 컨벤션 같은경우는 깃허브의 템플릿을 활용하여 이슈 컨벤션을 정해, 프론트 및 백 모두 동일하게 작성할 수 있게 하였습니다.
아래는 저희의 PR컨벤션을 지킨 모습입니다.
프로젝트가 마무리 된 후, 이슈의 Assignees와 Label을 활용해 PR컨벤션을 준수하니 굉장히 뿌듯했습니다 ㅠ.. 이게 통일감이지..하면서 가장 뿌듯했던 것 중 하나였던 것 같습니다.
이외에 프론트엔드에서 각자의 코드 취향을 타협하여 Prettier, ESLint 설정을 하였고, git hook인 husky를 활용하여 커밋에 lint 적용 후 코드 컨벤션을 지킬 수 있어서 좋았습니다.
이전 프리프로젝트 이후에 저는 이런 컨벤션을 더욱 엄격히 도입하고 준수하고 싶다고 회고하였었습니다.
[Pre-Project] 프리프로젝트 회고
드디어 프리프로젝트가 종료되었습니다..! 정말 다사다난했고.. 실제로 배포하는 과정까지 거치면서 너무 힘들었던.. 일주일이었습니다. 막상 처음에 기획을 하려니, 어떻게 해야할지 막막해서
ddaeunbb.tistory.com
이번 메인 프로젝트 마무리를 짓고 회고를 하면서, 이전 프로젝트에서 적용하고 싶었던 점을 메인에서 적용했다는 것 자체만으로도 저의 프로젝트가 한단계 한단계씩 더욱 성장할거라는 확신을 얻을 수 있었습니다.
이렇듯 초기에 많은 컨벤션을 정하고, 기초를 만든 뒤에 프로젝트를 진행하면서 코드를 짜는 것이 훨씬 편하고 좋았습니다. 코드에 통일감을 느끼면서 제 코드뿐만 아니라 다른 팀원들의 코드를 읽는것이 훨씬 더 쉬움을 확실하게 체감할 수 있었습니다.
● 메인 프로젝트에서 적용했던 기술스택 (리덕스를 사용하지 않은 이유)
저희팀은 아래와 같이 툴을 적용했었습니다.
이번 프로젝트에서는 정말 거의 모든 기술이 처음 사용해보아서, 툴의 공부와 구현을 동시에 해야했다는 점이 메인 프로젝트에서 가장 어려웠던 것 같습니다. 기본적으로 사용한 기술 제외하고, 제가 맡았던 부분에서 사용해봐야했던 기술은 React-Query, Swiper, React Hook Form이었습니다. 그리고 모두 처음 사용해보는 스택이었습니다. 또한 이전 솔로 프로젝트에서 사용해보았던 타입스크립트는 연습느낌이 들었었는데, 이번 프로젝트에서는 확실하게 타입스크립트를 사용해볼 수 있었던 것 같습니다.
❍ 기술스택을 사용한 이유
- swiper같은 경우는 캐러샐을 구현해야하는 부분이 많았어서 적용해 사용하게 되었습니다.
- 단순히 데이터를 받아오고 보여줘야하는 부분만있었다면 axios만 사용했을테지만, 저희팀은 CRUD해야하는 부분이 많았기때문에 데이터를 가변시키고 그리고 가변적인 데이터를 쉽게 가져오기 위해 react-query를 사용하게 되었습니다.
- 처음에는 React Hook Form을 사용하지 않았는데, 저희팀 멘토님께서 현업에서 가장 많이 쓰이기도 하고 최근 카카오도 react hook form을 도입하였다는 조언을 주셔서 react hook form을 사용하였습니다.
- 그리고 저희 팀은 전역상태를 관리하는 기술을 사용하지 않았습니다. 팀내에서 Redux나 RTK를 써볼까에 대한 깊은 토의가 있었는데요, 전역으로 관리해야할 상태가 많지 않았기 때문에 결과적으로 사용하지 않았습니다. 대신 context API를 사용하였습니다.
- eslint, prettier, husky는 코드 컨벤션을 위해 사용하게 되었습니다. 협업을 위해선 필수적이라고 느껴 도입하였습니다.
- 추가적으로 가벼운 라이브러리인 emotion을 사용하려고 했으나, tailwind를 사용해보고 싶다는 내부적인 논의를 통해 tailwind + styled-components를 사용하였습니다.
- vite의 많은 플러그인을 사용할 계획이 없었기 때문에 CRA대신 vite를 사용해 프로젝트를 생성하였습니다.
+ 추가적으로, 멘토님께서 전역으로 관리해야할 상태가 많아보이지 않기 때문에 전역상태 관리 툴은 사용하지 않는게 좋겠다고 말씀을 주셨습니다.
● 메인 프로젝트에서 마주 했던 에러
저는 저희 프로젝트에서 아래와 같은 기능 구현을 맡게 되었습니다.
- 이미지 업로드 시, 미리보기 구현
- 이미지 업로드 CRUD
- 리액트 인피니트 쿼리로 무한스크롤 구현
- react hook form 을 사용한 회원가입 구현
- 스와이퍼를 활용한 이미지 캐러샐 및 스크롤 구현
주로 제가 맡았던 부분은 이미지 업로드 시, 미리보기 구현과 이미지 업로드 CRUD, 쿼리로 무한스크롤 구현, 스와이퍼를 활용한 이미지 캐러샐 및 스크롤 구현이었습니다. 따라서 아래는 제가 주로 맡은 기능 구현에서 마주했던 에러들을 기술하고자 합니다.
❍ 첫 번째 에러
위 과정을 구현하면서 제가 마주했던 에러는 유저가 input으로 파일을 올렸을 경우, 이미지 미리보기를 구현해야하는데 이미지가 보이지 않는 에러를 마주하게 되었습니다. 제가 마주한 에러는 아래에 정리하여 해결과정까지 포스팅을 하였습니다.
● Swiper 라이브러리를 활용해 이미지 업로드 후, 이미지 미리보기 구현하기
오전9시부터-24시 회의하는.. 요즘.. 회의가 끝나면 늘 리액트 쿼리를 공부하고 있습니다.. 저는 정말 자고 싶었지만 지금 정리하지 않으면 하지 않을 것 같아 자리에 앉아 스타벅스 핑크 드링크
ddaeunbb.tistory.com
● [Main-Project] base 64, Blob, File 형식 (리액트 이미지 미리보기 업로드 기능)
대략 코드작성 및 배포를 마치고, 제가 코드 작성 시 마주했던 문제점들에 대해 하나씩 정리해볼까 합니다.. 저는 이미지 미리보기를 구현해야했는데, type이 file인 input을 클릭 후 이미지를 올리
ddaeunbb.tistory.com
❍ 두 번째 에러
저희 팀은 게시물 피드를 올리고, 그 게시물을 공유할 수 있는 기능을 만들었습니다. 공유버튼 클릭 시, ClipBoard API를 사용해 URL이 복사되게끔 구현하였습니다.
이후, github Action을 사용하여, AWS S3로 배포를 하였는데, 배포 이후에 클립보드 API가 사용되지 않는 에러를 마주하였습니다. 코드의 문제인가했더니.. 클립보드 API는 로컬과 https에서만 지원을 해준다는 것을 발견하였습니다... 따라서 AWS S3에서 배포에서 netlify로 배포방식을 바꾸고 https로 배포하였습니다. 이후, 정상적으로 작동하는 것을 확인할 수 있었습니다.
❍ 세 번째 에러
이후 공유버튼 클릭 후 저장된 URL을 브라우저에 다시 복붙하면 해당 URL이 보이지 않는 문제를 경험했습니다. 아래 블로그와 비슷한 문제같았고, 아무리 해결점을 찾아보려해도 찾을 수가 없었습니다..
[REACT] Netlify로 빌드한 웹사이트에 URL parameter를 붙여 접속하면 404가 뜰 때 해결법 (how to connect clien
react app gets 404 when fetching url parameter 이 글을 쓰게 만든 문제 상황 자체는 위 키워드와 같았다. 자꾸 404가 뜨는 것. 아래에서 자세히 쓸 거지만... 원인이 서버가 없기 때문이라는 걸 몰라서 더 헤
velog.io
프로젝트가 어느정도 마무리된 이후, 타팀에서 공유기능을 구현해내신 팀이 있어 타팀의 코드를 보며 해결점을 찾아나갔습니다. netlify.toml에서 프록시를 설정해준 문제때문이었을까 했습니다ㅏ.. 하지만 그게 아니라 다른 문제였습니다!
아래는 vite.config.ts 파일인데요. PWA를 위해 base를 기입하고 있었습니다.
// https://vitejs.dev/config/
export default defineConfig({
// base: './', 이 부분을 차후, 지웠습니다. //
plugins: [react(), svgr()],
server: {
proxy: {
'/api': {
target: 'http://43.202.86.53:8080',
changeOrigin: true,
secure: false,
rewrite: path => path.replace(/^\/api/, ''),
},
},
},
});
하지만 base부분을 지우니,, 공유가 매우 잘되는 걸 확인할 수 있었습니다..! 우리 팀..!! 공유기능 된다..!!
❍ 네 번째 에러
리액트 무한 쿼리구현 이후, 처음 home 페이지에서 팝업 페이지를 보고 난뒤 뒤로 돌아오면 데이터가 멈춰있지않고 새로운 데이터를 받아오는 문제를 마주하였습니다.(랜덤으로 데이터가 주어지기때문에) 이 과정 속에서 저는 staleTime과 cacheTime 개념을 공부하게 되었습니다.
기본적으로 staleTime이 0이며, cacheTime은 5분입니다. cacheTime은 컴포넌트가 언마운트되면 자동적으로 inactive한 상태로 변하게 됩니다. 그리고 비활성화된 데이터이기때문에 캐시에서 삭제됩니다.
기본 설정일 경우에는, 데이터의 상태는 반환되자마자 stale로 판단되므로 늘 stale한 데이터라고 할 수 있습니다. 따라서 쿼리를 요청할 때마다 API 요청을 하게 됩니다. 따라서 제가 home 페이지를 보다가 (데이터를 받아오는 즉시, stale한 상태) 다른 페이지를 보다가 다시 돌아오면 다시 API요청을 해 기존의 데이터가 아닌 새로운 데이터가 보이게 되는 것이었습니다.
그리고 API요청에 있어서는 cacheTime보다 staleTime이 더 우선순위라는 것을 알게 되었습니다.
리액트 쿼리의 StaleTime과 CacheTime
리액트 쿼리를 처음 사용할 때 헷갈릴 수 있는 개념 중 하나인 staleTime과 cacheTime에 대해 알아보도록 하겠습니다. ✎ staleTime stale의 사전적 정의는 [신선하지 않은, (만든 지) 오래된]입니다. 말 그
ttaerrim.tistory.com
따라서 저는, staleTime을 3분으로 설정한 뒤, 문제를 해결할 수 있었습니다.
아래는 해결한 상황입니다.
● 메인 프로젝트에서 다른 팀원에게 배웠던 점
husky를 다루는 법을 알게 되었고, 다른 프론트엔드 팀원 두분께서 eslint와 prettier을 잘 다루시는 것 같아 그 부분도 배울 수 있었습니다. 이외에도 라우터 설정하는 방법을 타팀원에게 배울 수 있었습니다.
- createBrowserRouter를 사용한 라우팅 설정
저는 BrowserRouter와 Routes, Route 태그로만 활용해 라우터 설정방법을 알고 있었는데요. 아래와 같이 createBrowserRouter를 사용하여 라우팅을 설정하였습니다. 또한 lazy를 적용하여 마운트될 때 파일을 불러오게 설정하였습니다.
import { createBrowserRouter } from 'react-router-dom';
import App from '../App.tsx';
import Login from '../pages/login/Login.tsx';
import NotFound from '../pages/notFound/NotFound.tsx';
import Path from './paths.ts';
export const router = createBrowserRouter([
{
path: '/',
element: <App />,
errorElement: <NotFound />,
children: [
{
path: Path.Login,
element: <Login />,
},
{
path: Path.Info,
lazy: () => import('../pages/info/Info'),
},
{...
],
},
]);
- 단축키
넘겨줘야할 prop가 뭔지 일일이 확인해야했는데요, command + 마침표 단축키를 통해 쉽게 이 props들을 가져오는 것이 매우 편리하였습니다... 정말 저에게는 신세계 였습니다.. WOW.. 정말 감사합니다.. 재린님..
- 리액트 쿼리 관련 개념
저는 리액트 쿼리를 처음 써보는 상황이었기때문에, 이전에 사용해보셨던 재린님과 준석님께 지속적으로 쿼리관련 개념을 여쭤보았던.. 하지만 늘 친절하게 답변주셔서 너무 감사했습니다. 이외에도 내장객체인 fileReader 사용법도 준석님께서 공유해주셔서 쉽게 에러를 해결할 수 있었던 것 같습니다.. 또한 api폴더를 만들고, mutationfn.ts 파일과 queryfn.ts 파일로 저장하여 함수를 나눠 관리하시는 방법도 알려주셨습니다. 감사합니다..
● 메인 프로젝트에서 느낀점
- 저는 평소에 본받고 싶었던 팀원들을 직접 섭외해 프론트엔드 팀원을 꾸리게 되었습니다. 본받을 점이 많았다고 생각했던 팀원들의 코드를 직접적으로 볼 수 있었던 점이 정말 좋았습니다. 남의 코드를 본다는게.. 쉽지 않다..!
- 백엔분들의 코드를 읽지는 못하지만, spring boot나 redis, docker같은 기술이 어떤 용도를 위해 활용하시는 건지 목적정도는 알아두는 것이 좋다는 생각이 들었습니다. (분야를 너무 선긋지는 않아도 좋다. 알면알수록 좋다..ㅠ)
- 새로운 툴을 공부하면서 실제 프로젝트에 적용했을 때, 확실히 기억에 훨씬 잘 남는다는 것을 더 실감할 수 있었습니다.
- 계획과 기획의 탄탄함이 프로젝트의 전부일 수도 있겠다라는 생각이 들었습니다.
- 웹 디자인이 생각이상으로 많은 부분을 차지한다는 점을 느꼈습니다.
- 코드를 잘치는 것도 중요하지만, 개발직군에서 같이 협업하고 싶은 사람은 어떤 사람인지 좀 더 고민하게 되었습니다.
- 체력관리의 중요성을 많이 느꼈습니다..
- 프로젝트에서 사용할 라이브러리 등 결정할 많은 것들이 있는데, 끝난 이후에도 실제 현업에서 QA과정은 정말 어떻게 이뤄지는걸까 상당히 궁금점이 높아졌습니다.. (성능테스트 관련...)
● 메인 프로젝트에서 아쉬웠던 점
- 백엔드분들과의 소통이 정말 잘되서 좋았지만, 또 한편으로는 문제가 터졌을 때 바로 논의하는 분위기라 코드를 짜는 몰입도를 깰 수 있다고 느꼈습니다.
- 시간이 부족해 기능 구현 및 안정화에 신경을 많이 써서 디자인에 많이 신경을 쓰지 못한게 아쉬웠습니다. 개인적으로 디자인에 대해 욕심이 많은 편인데, 디자인 관련된 라이브러리를 많이 활용하지 못해 참 아쉬웠습니다.
- 코드 최적화에 신경을 많이 쓰지 못했습니다. 시맨틱 태그를 준수하지 못했습니다.. 그래서 lighthouse의 점수가 많이 낮았던 것이 아쉽습니다.
● 마무리
약 한달간 정말 메인 프로젝트에만 많은 시간을 쏟다보니, 실제 현업에서도 이렇게 일을 하시지 않을까? 란 생각이 많이 들었습니다. 프로젝트에 참여하면서 다른 팀원분들보다 제가 부족함이 많이 있다고 느껴 가끔은 시무룩해지곤 했지만, 다른 분들을 쫓아가려고 프로젝트 작업 후에도 저녁마다 리액트 쿼리 사용법을 찾아보고 공부하였습니다. 제 걱정과는 다르게, 마무리에는 새로운 기술을 잘 적용을 하고 배운점이 정말 많았습니다. 마지막에 팀끼리 모여 회고를 할 때, 프론트엔드 분들께서 한분한분이 제 자신이 다른사람들보다 부족하다고 느꼈다고 생각했다고 말씀하셨는데요, 사실 각자의 실력이 부족하지 않음에도 불구하고 그렇게 느끼는건가? 싶기도했습니다. 그래도 서로 자신의 부족함을 채워나가기 위해 열심히 임했던 것이 확실했던 팀원들이었다고 생각합니다.(제자신도요.) 아쉬움이 남는 프로젝트이기도 했지만, 그만큼 다음 프로젝트 및 현업에서도 채워나갈 부분이 확실히 생기는 것이기 때문에, 제 자신에 대한 발전의 가능성이라고 생각이 들었던 프로젝트였습니다. :)