개발기간: 06/07 ~ 07/03
깃허브의 이슈와 비슷한 기능을 하는 이슈관리하는 제품이다. 생각보다 필요한 기능이 많았고 디테일한 부분까지 신경써야 됐었다.
이번 프로젝트를 하면서 몇몇 고민사항들이 있었다.
지난번 에어비앤비 미션 때 공용컴포넌트로 묶지 않아서 반복적인 작업을 했던 기억이 있다.
이번에는 최대한 재사용할 수 있는 부분은 재사용하자고 생각했다.
하지만.. 역시나 이번 나름의 문제도 발생했다.
모양 즉, 렌더링되는 View는 같지만 각각의 기능, 위치가 달랐다.
아래 예시에 같은 모양이 같은 모달이 각각 다른 화면에서 사용된다.
-> className을 Props로 전달해 위치를 조절해 줬다.
-> 상위 컴포넌트에서 useEffect
로 업데이트가 되야 되는 시점을 dependency에 넣어서 관리했다.
위처럼 간단한 것들은 해결할 수 있겠지만 정말 비슷한데 조금씩 다른 것들이 있을 때...
그냥 따로만드는 것이 더 효율적일까?
근데 비슷한 기능이니까 코드를 반복한다는 것은 너무 귀찮은데...
이 부분에 대한 정답은 모르겠다. 이번에 느낀건 조금 많이 다르다 싶으면 그냥 하나더 만들자!
why? 그걸 해결하는 과정에서 너무 복잡스럽다
이번에도 TS로 프로젝트를 진행했다.
아직 기본적인 것만 사용하고 있지만 지금 느낀점은 좋다!
이 장점이 생각보다 큰 것 같다. 말로 표현하기는 좀 쉽지 않지만... 뭔가 확실하다..?
타입이 정해지면서 내가 코드를 작성하는 방식도 타입 방면으로 고민하면서 작성하게 되고 코드를 파악하기에도 너무 유용하다.
모든 객체의 key-value타입을 지정해 주니 이 객체가 서버에서 어떻게 들어오지하고 콘솔을 찍어보는게 아니라 type
을 확인하면 된다. 이것도 정말 편하다. (처음 설정이 귀찮을 뿐...)
제일 고민이다 공통적으로 사용하는 타입이 많아지는데 어느 디렉토리, 파일에 둬야될지 고민이다.
type만 모은 디렉토리를 두기에는 잘 관리하지 않는 이상 찾기가 더 힘들어질 것 같고... 이 부분에 대해서는 고민이 많이 된다.
아래의 코드가 왜 에러가 나는지 생각해보자. 그리고 해결할 수 있는 방법은?
let key = 'name';
type ObjType = {name:string}
const obj = {name:'kyle'}
console.log(obj[key]) //error
//string literal type으로 설정
const key = 'name';
type ObjType = {name:string}
const obj = {name:'kyle'}
console.log(obj[key]) // ok
//또는
let key = 'name';
type ObjType = { [key:string]:string }
const obj = {name:'kyle'}
console.log(obj[key]) // ok
즉, let이나 다른 값이 들어올 가능성이 있는 변수는 Object의 key값으로 사용하기 위해서는 index signiture를 설정해줘야한다.
JS에 익숙해져있어서 그런지 이런 부분이 참 어색했다.
이번에도 리코일을 활용해서 상태를 관리했다. 항상 그렇듯 장단점이 느껴졌다.
상태가 있는 컴포넌트를 찾기 보다 따로 분리돼 있기 때문에 상태를 관리하기 수월했다.
페이지별로 사용하는 주요 상태를 나눠서 관리했는데 되게 편리했다고 생각한다. 하지만 규모가 커지면 어떻게 관리할지는 고민해 봐야 될 부분인 것 같다.
selector는 서버요청을 할 때 캐시를 해놓기 때문에 POST
, PATCH
, DELETE
등의 서버요청을 할 때는 trigger를 두고 다시 GET 해오게 만들어야한다.
이에 관련된 내용은 다른 포스팅에 작성했다.
지금까지 단순히 개발자도구를 켰을 때 깜빡이는 것을 막기 위해서 React.memo
를 사용해온 느낌이 있다.
React.memo를 읽고 어떤 경우에 사용하는 것이 좋을지 알게 됐다.
이번에 주나미와 이곳 저곳 사용하면서 React.memo
에 대해 학습할 수 있는 기회를 얻었다.
핵심은
React.memo
는 props를 비교해서 리렌더링 하는 것을 결정하기 때문에
props가 자주 변경이 되지 않는 컴포넌트에 적용해야된다.혹은 props가 같아도 내부에서
useState
,useReducer
,useContext
를 사용하면 리렌더링 된다.
const add1 = () => (num) => num+1;
const addFn1 = add1();
const addFn2 = add1();
위 코드에서 addFn1 !== addFn2
인건 모두 알고 있을 것이다.
즉, 함수를 props로 넘겨줄 때는 useCallback()
을 활용해서 같은 함수임을 인지시켜야 된다.
아래보면 InputField
와 PrimaryButton
에 React.memo
를 적용한 것을 볼 수 있다. 하지만 입력할 때마다 props가 변경이되는 InputField
는 계속 리렌더링이 되기 때문에 React.memo
를 적용할 이유가 없다.
결국 노란색 부분만 props가 변경되지 않고 항상 같은 값을 렌더링하기 때문에 Did not render된다.
PrimaryButton
에만 React.memo
를 적용하는 것이 가장 좋은 방안이라고 생각한다.
이슈트래커는 로그인을 한 후에 모든 서비스를 이용할 수 있다. 그렇기 때문에 JWT token의 기간이 만료 됐거나, 로그인 하지 않고 서비스에 접속할 경우 등에 에러처리를 해줘야 됐다.
사실 목표기간인 4주안에 에러처리는 완성하지는 못하고 시도만 했다. 지금 상황은 서버에 잘못된 JWT token을 가지고 user정보 요청, 상세페이지 접근할 경우 null을 반환해 에러처리를 했다.
하지만 더욱 각각 상황이 다른 에러를 처리해야 되기 때문에 위와 같은 코드는 좋지 않다고 생각한다.
각 error객체의 statusCode에 따른 처리를 해줘야 된다고 생각한다. ErrorBoundary
라는 것을 알게 됐는데 getDerivedStateFromError
를 활용해서 간단하고 보기 좋게 각 statusCode에 맞는 에러처리를 할 수 있을 것 같다는 생각이 들었다.
그 부분을 자세히 학습해서 적용해볼 계획이다.
항상 고민이다 수 많은 소스들을 어떻게 관리해야 될까?
이번에는 지난 번과 다르게 pages 디렉토리에 pages에 필요한 컴포넌트들을 넣어봤다.
하지만 규모가 커질 수록 모든 컴포넌트는 pages 하위에 들어가게 됐고 pages라는 디렉토리의 의미가 무색해지는 느낌을 받았다.
pages에는 각 페이지의 최상단 컴포넌트만 있고, components 디렉토리 하위에 잘 정리하는 것이 더 낫다고 생각한다.
components 하위에 어떻게 정리하는지는 계속 고민해봐야될 부분이다.
코드스쿼드의 마지막 프로젝트를 진행했다.
3주 기간 외에도 모두들 동의해주셔서 1주일 더 진행하며 완성도를 조금 더 올릴 수 있었다. 처음 계획에 비해 못한 부분은 많았지만 정말 만족했던 프로젝트였다. 아직 못한 부분은 잊지 않고 하나씩 학습할 계획이다.
모든 팀원들이 함께 WIKI에 프로젝트 마무리 회고를 작성했다.
BE
, FE
, iOS
모두 실력있는 분들과 함께해서 많은 점을 배울 수 있었다. 말 뿐이 아닌 원활한 소통을 위해서 다들 노력해 주신 덕분에 프로젝트하는 내내 편하게 작업에 집중할 수 있었다.
코드스쿼드에서 첫 페어와 마지막 페어 프로그래밍을 주나미와 함께 했는데 처음 했을 때에 비해 서로의 실력이 향상됐다는 것을 느꼈다.
3달 전과는 보다 깊은 고민을 하고 있고 문제를
코드스쿼드의 마지막 프로젝트에서 개발하는 부분 외적으로도 많은 것을 배우고 느낄 수 있어서 아쉬운 부분 보다는 만족감이 더 큰 프로젝트였다.
카일!! 정말 꾸준히 열심히시네요... 대단하세요!!!