개발기간: 05/17 ~ 06/04
이번 프로젝트에서는 기존에 사용했던 자바스크립트 대신 타입스크립트를 활용해서 프로젝트를 진행했다. 상태관리는 recoil을 활용해서 전역에서 상태를 관리했다.
이번 프로젝트를 통해 타입스크립트의 힘들었었지만 확실한 장점, recoil의 편리함 등 느낀 부분이 많다.
간단하게 새로운 기술을 적용해보면서 내가 느낀점과 3달전에 똑같은 에어비엔비 프로젝트를 했을 때와의 다른 느낀점을 작성할 예정이다.
3달전에도 같은 에어비엔비 프로젝트에서 달력을 만들어 봤다. 링크에 들어가서 결과물을 보면 알겠지만 지금의 비하면 많이 아쉬운 달력이다.
이번 프로젝트에서 포커스 된 탭에 따른 로직처리, hover
됐을 때 이벤트, transition
등을 추가로 구현했다.
그때 프로젝트 코드를 보면서 제일 좋았던 점은 그때의 함수를 재사용했다. 그 당시에 코드를 잘게 나눠놓은 덕분에 1달의 날짜를 2차원 배열로 구하는 함수를 그대로 가져와 적용시켰는데 잘 됐다. 함수 분리를 잘 해놨을 때 필요한 함수를 가져와서 재사용이 가능하구나를 느끼면서 앞으로도 그 부분에서는 관심있게 생각하고 코드를 작성해야겠다.
이번 프로젝트는 타입스크립트를 이용했다. 처음 사용해보는 단계여서 제네릭은 제대로 활용하지 못했다. 어떤 상황에 써야 좋을지 best practice나 프로젝트를 하면서 계속 고민해 봐야 할 것 같다.
타입스트립트의 장점은 확실했다. 잔 실수가 확실히 줄어 들었다.
일단 자동완성이 되지 않으면 뭔가 문제가 있구나하고 사전에 파악을 하게 된다.
undefined
, null
같은 자잘한 오류등은 더이상 만나 볼 수 없었다.
기존에는 자유롭게 여러 타입을 받아서 사용했다면 모든 인자값, 반환값을 컨트롤 하다보니 보다 정확한? 함수를 만들게 됐다.
이외에도 규모가 커지면 커질 수록 타입스크립트는 괜찮겠구나라는 생각을 하면서 앞으로의 프로젝트에 타입스크립트로 구현할 것같다.
힘들었던점은 너무 많았다. 지금에서야 조금은 익숙해졌지만,
처음에는 Props
, styled-components
, event 객체
등등 예상치 못한 구간에 상태를 모두 입력해줘야됐다. 상태를 입력해 줄때도 event 객체
와 같은 어떤 타입인지 모르는 애들한테는 시간이 더 오래걸렸던 것 같다.
children
의 타입 children
을 정해주는게 너무 귀찮고 아직도 정확하게는 이해가 안된다. JSXElement | JSXElement[] 등 또는을 이용해 지정해줬다.
=> 프로젝트가 끝나고 배운 사실인데 함수 선언형으로 컴포넌트를 작성하면 알아서 children
타입을 이해한다고 한다. React.FunctionalComponent
에 대해서도 좀 더 알아봐야될 필요성을 느꼈다.
recoil - selectorFamily
selectorFamily
를 사용하면서 타입오류가 자꾸 났는데 그 이유를 알게 됐다. 그 이유는 나중에 다른 포스팅으로 작성할 예정이다. 결과적으로는 SerializableParam
이라는 타입이 필요했다.
unknown
타입은 뭐지?!?!이게 뭘까 프로젝트 마지막에 as unknown
으로 해결한 타입이 2가지 정도 있었다. 아직까지 정확하게는 모르겠다. 이 부분에 대해서는 좀 알아봐야 할 것 같다.
| null
을 했을 때의 피곤함구현하면서 타입을 ~~~ | null
로 설정한 적이 있었다. 이 부분 때문에 이것을 사용하는 모든 곳에서 타입에 | null
혹은 null
처리를 해줘야 되는 귀찮음을 겪었다. 타입을 선언할 때 신중히 꼭 필요한 것만 적용하자..!
이외에도 자잘한 힘들점이 많았다. 타입스크립트 때문에 미션이 더디게 진행됐는데 그 과정을 통해서 타입스크립트와 조금이나마 친해졌다고 생각한다.
이번에 recoil을 사용해서 여러 컴포넌트에서 사용하는 상태는 전역에서 관리했다.
컨텍스트와 비교해서도 Provider
처럼 보일러 플레이트 없이 활용할 수 있다. 기본적인 atom, selector는 금방 활용할 수 있게 됐었다.
selector
를 이용한 상태 가공?selector
를 이용해서 흩어져 있는 atom의 state
를 get
해와서 가공해서 받아올 수 있다. 덕분에 컴포넌트가 조금 간결해 보이는 효과를 준다.
selector
에서의 비동기 처리selector에서의 비동기 처리 포스팅을 한만큼 나는 너무 편리하게 사용할 수 있었다.
selector
에서 비동기 처리를할 때 주의할 점?selector
에서 비동기 처리를 할 경우 참조하고 있는 atom-state
이 변경된다면 다시 서버에 요청을 한다. 즉, 상태가 변경할 때마다 서버에 요청을 하게 되는 것이다. 이는 편할 수도 있지만 불필요하게 많은 요청을 보내고 있다고 생각된다.
=> 그렇다면 이 문제는 보내는 것은 confirm해주는 또 다른 상태를 둬서 관리해야될까? 이번 프로젝트에서 한 부분에 검색 버튼을 클릭할 때만 요청을 하도록 처리해놨다.
하지만 이게 좋은 방법인지는 모르겠다. recoil의 비동기처리 best practice를 보면서 학습해 봐야겠다!
mouseMove
이벤트를 적용해서 차트아래 버튼을 이동시키도록 구현했다. 하지만 mouseMove
이벤트가 너무 많이 발생한 바람에 성능상의 이슈가 발생했다.
문제를 해결하기 위해 쓰로틀링 을 적용시키켰다.
const throttle = (fn, time) => {
let timer = null;
return (e) => {
if (!timer) {
timer = setTimeout(function () {
timer = null;
fn(e);
}, time);
}
};
};
위의 쓰로틀링 함수 적용 전과 후를 비교하기 위해 간단하게 프로파일링을 해봤다. 아래의 결과처럼 이벤트가 연속해서 발생하지 않기 때문에 렌더링에도 부담이 줄어든 것 같다.
하지만 mouseMove
이벤트가 발생할 때마다 차트가 불필요하게 리렌더링이 발생했다. 이를 방지하기 위해서 차트에 React.memo
를 적용시켰다.
하지만 큰 컴포넌트가 아니어서 그런지 그렇게 큰 차이는 발생하지 않았다. (거의 차이가 없는 것 같기도...?) 그래도 개발자 도구를 켰을 때 highlight가 차트에는 발생하지 않기 때문에 리렌더링은 되지 않는 것 같다.
이번에 비슷하게 생겼지만 각각 클릭했을 때 나오는 모달창이 다르다는 생각에 다 다른 컴포넌트로 구현했다. 하지만 5개모두 대부분 공통적인 부분이었고 기능 하나하나 추가할 때마다 엄~~청나게 번거로움이 있었다. 정말 다시는 이런 행위를 하고 싶지 않다. 꼭 신경써서 공통으로 된 부분은 분리하자.
커스텀 훅을 사용해서 편리한 부분도 있었다. 뭔가 나만의 미니 라이브러리를 만들어서 사용한 느낌이랄까?? 하지만 공통으로 사용하는 곳 중에서 예외적으로 처리해야 되는 부분에서 당황했다.
그 결과 처음에 간결하던 커스텀 훅이.. 덕지덕지 이상한 것들이 추가됐다.
그래도 나름 구현하는 동안 잘 활용해서 편했지만 다음에는 조금 더 기능을 분리하던지 해서 구현해 봐야겠다.
이번에 hover시 색깔을 변하게하는 하는 공용 컴포넌트를 만들어봤다. 단순히 위에 씌우는 것 만으로도 작동하게 만들었더니 편했다. 공통으로 사용되는 기능이나 스타일을 공용 컴포넌트로 빼네는 연습을 하면 좋을 것 같다.
컴포넌트 디렉토리 관리만 잘해도 내 프로젝트 구조를 한눈에 파악할 수 있다고 생각한다. 그렇다면 어떤 구조가 좋은 구조일까? 이건 너무 어려운 문제인 것 같다. 계속 고민해 봐야 될듯!
오랜만에 프론트를 혼자 담당한 프로젝트였다. 내 컨디션과 스케쥴에 맞게 프로젝트를 진행할 수 있어서 편하게 진행할 수 있었다.
또 기존에 학습해보고 싶었던 로딩 처리시 스켈레톤 UI와 스피너 같은 것을 적용해 볼 수 있어서 내 기준에서는 만족스럽다.
타입스크립트나 리코일 같이 처음으로 학습해서 프로젝트에 바로 적용시키니 힘든 부분도 있었지만 되게 재밌게 3주를 보낸 것 같다.
위에 작성한 것 외에도 많은 문제가 있었지만 조금 늦게 작성하려니 기억이 잘 나지 않는다... 회고나 발생한 문제를 기록해 놓는 습관이 꼭 필요하다고 생각된다.