돌멩이 하나/셀프 크리틱 13

1-2년 차에 공부해야 할 키워드

작년 12월 무렵 한 해 동안 공부해야 할 키워드 목록을 다음과 같이 뽑았었다.  ✅ 디자인 패턴✅ TypeScript 클린 코드 ✅ Git✅ 예외 처리 및 에러 핸들링 프론트엔드의 테스트 전략 및 테스트 코드 작성 방식아키텍처✅ 렌더링 패턴: CSR, SSR 등 ✅ Next.js✅ JavaScript Deep Dive✅ 팀, 협업  공부하면서 도움이 되었던 자료들은 다음과 같다.  1. 디자인 패턴https://www.patterns.dev/ Patterns.devLearn JavaScript design and performance patterns for building more powerful web applications.www.patterns.devhttps://refactoring.guru/k..

불필요한 useEffect 없애기

지난 5월 원티드 프리온보딩 FE 챌린지에서 데이터 / 계산 / 액션을 구분하는 것이 복잡도와 의존도를 낮추는 방법 중 하나라는 걸 배웠다.  1. 데이터: 이벤트에 대한 사실. 문자열, 객체 등 단순한 값 그 자체     예) 사용자가 입력한 이메일 주소, 은행 API로 가져온 달러 수량 2. 계산: 입력으로 얻은 출력. 순수 함수라고 부르기도 함.     예) 최댓값 찾기, 이메일 주소가 올바른지 확인하기  3. 액션: 외부 세계와 소통하므로 실행 시점과 횟수에 의존. 부수효과를 일으킴.    예) 이메일 보내기, 데이터베이스 읽기   이번주 티켓 중에 antd Table을 사용해 Weekly 캘린더를 구현해야 하는 작업이 있었다. (antd Calendar는 yearly, monthly만 제공한다...

무한 스크롤과의 사투 (2) - tanstack/react-virtual 적용

앞의 포스팅에서 언급했던 것처럼 무한스크롤 관련 이슈를 해결하고 나니 성능 이슈가 부각되었다. 원문과 번역문을 두고 사용자가 편집할 수 있는 서비스인데 아이템이 500개 정도만 되어도 키보드 입력 이벤트가 발생하면 사용자가 키보드를 누르고 화면에 해당 글자가 뜨는 시간 사이에 지연이 체감되는 정도였다.  list virtualization 또는 windowing 기법을 적용해서 뷰포트에 보이는 아이템만 DOM 노드에 가지게 하면 성능 면에서 큰 개선을 할 수 있을 거라고 생각했다. react-virtualized가 대표적인 windowing 라이브러리로 지금은 legacy가 된 이전 버전 react 공식 문서의 성능 최적화 파트에서도 추천하는 라이브러리를 먼저 고려했다.  프로젝트의 요구 사항 중 목록 ..

무한 스크롤과의 사투 (1)

딱 1년 전 이맘때 부트캠프 파이널 프로젝트를 마친 후 회고를 작성하면서 아쉬운 점으로 "무한스크롤도 써보고 싶었던 ui인데 시간 문제로 도입하지 못했다"고 꼽은 적이 있다. 그리고 그로부터 약 10개월 뒤 무한 스크롤을 원없이 사용하게 된다 😇 지난달 다른 팀원이 맡았던 파트를 인계 받았는데 그 중 메인 feature가 무한 스크롤이었다. 인계 받을 당시 프로젝트의 가장 큰 이슈는 다음과 같았다. 1. 스크롤을 위아래로 이동함에 따라 nextPage와 previousPage를 fetch하고, 서버에서 응답으로 받은 데이터를 UI를 그리는데 사용하는 배열 안에 순서에 맞게 삽입하는 게 때때로 올바르게 동작하지 않고 있었다. 가령 [... 6, 7, 8, ...] 페이지가 렌더링되어야 하는데, [... 7..

id는 숫자여야 할까, 문자열이어야 할까?

프로젝트 요구사항 중 수천~수만 개의 문장이 담긴 문서(document)에 문장 별로 책갈피(bookmark)한 문장을 별도 조회할 수 있는 기능이 추가되었고, 이에 대한 화면을 구현하는 중이었다. 서버에서는 다음과 같은 모양의 bookmark 데이터들이 담긴 배열을 보내준다. (참고로 데이터 필드명이나 구조는 프로젝트 코드와 정확히 일치하는 것이 아닌 포스팅을 읽는 이의 이해를 돕기 위한 예시이다.) { id: 1, source: 'Before we begin.', target: '시작하기 전에.', memo: '', document: { id: 3, name: 'Dance with Chance #1', }, } 위와 같은 데이터가 담긴 배열(이하 bookmarks라고 통칭)을 GET 요청으로 받아온 ..

다크 모드 - 화면 깜빡임(FOUC) 이슈 해결 및 시스템 설정과 연동

온라인 셀러 계산기 사이트: https://seller-calculator.vercel.app/ 개인 프로젝트로 마진, 판매가, 행사가 환원 등을 구할 수 있는 온라인 셀러 계산기를 뚝딱 만들어 보았다. 요구사항에는 없었지만 지난주 기능 구현 챌린지에서 만들었던 다크 모드 토글 컴포넌트를 가져와서 적용해 보았다. 그 과정에서 생긴 이슈와 해결책을 정리해 보기로 한다. 1. useEffect hook tailwind css를 사용하면 다크 모드를 굉장히 손쉽게 구현할 수 있다. 새로고침 시에도 테마가 유지될 수 있도록 사용자가 선택한 테마를 로컬 스토리지에 저장하기로 했다. 그리고 공식문서에서 알려준 대로 시스템 설정도 체크할 수 있도록 window.matchMedia() api를 사용했다. if ( lo..

[기능 구현 챌린지] Chart Component

Frontend Mentor | Expenses chart component coding challenge In this challenge, you'll create a bar chart component from scratch. We provide a local JSON file, so you can add the chart data dynamically if you choose. www.frontendmentor.io 💡 기능 구현 목표: - Bar 차트를 보고 개별 Bar 위로 마우스를 가져가면 일별 정확한 금액을 볼 수 있습니다. - 오늘 요일의 Bar는 다른 요일의 Bar와 색상이 다릅니다. - 기기의 화면 크기에 따라 콘텐츠에 대한 최적의 레이아웃을 작성합니다. (데스크탑/모바일) - hove..

to do list를 만들면서 한 고민들

1. 데이터와 상태 다루기 처음에는 더미 데이터로 화면을 만들고, 기본적인 CRUD 기능을 어설프게나마 구현을 했다. 그다음 더미 데이터를 json-server로 바꿔서 axios로 fetch하는 걸로 코드를 수정했다. 그러다보니 처음에 더미 데이터를 가지고 기능을 만들 때는 전체 to do 데이터를 하나의 상태로 관리했었는데, 이 부분을 서버와 데이터를 주고 받는 걸로 바꿔야했다. 그 과정에서 fetch로 요청을 할 때마다 페이지 새로고침을 해주지 않으면 갱신된 데이터가 화면에 반영이 되지 않았다. crud 요청이 있을 때마다 window.location.reload() 로 새로고침을 해주자니 매번 모든 컴포넌트들이 새로 리렌더링이 되면서 화면이 번쩍거리는 게 사용자 관점에서 요란스럽게 느껴졌다. 특히..

[알고리즘] 인접 행렬(adjacency matrix) 길찾기

지난 목요일부터 4일째 자료구조(스택, 큐, 트리, 그래프)를 배우면서 아침부터 밤까지 내내 알고리즘 문제만 들여보고 있으니 머리가 과포화 상태다 ㅋㅋㅋ 금요일 정규 시간에 못 푼 문제들(태반...)을 주말 동안 붙잡고 늘어지느라 주말에 해야 할 다른 일들을 하나도 못했다. 😭 아직 열어보지도 못한 advanced 문제들이 남아있다는 것이 함정... 지금 본다고 알 것 같지도 않은 게 더 함정... 이번 포스팅에서는 그래프를 이용한 알고리즘 문제 중 하나였던 길찾기 문제를 셀프 크리틱해보려 한다. 알고리즘 문제에서 많이 등장하는 길찾기 패턴 문제를 처음으로 어떻게 다뤄야 하는지 알게 된 것이 이번 자료구조/알고리즘 유닛의 최대 성과였다. 💡 그래프의 각 정점을 순회할 수 있는 DFS, BFS 두 가지 방..

[알고리즘] 괄호쌍 문제

워낙 유명한 문제라 간략하게 입출력만 써보자면, 입력: string 타입의 문자열 출력: 입력의 문자열 내의 모든 괄호가 짝이 맞는지 여부에 대한 boolean 타입 🔽 입출력 예시 let output = balancedBrackets('[](){}'); console.log(output); // --> true output = balancedBrackets('[({})]'); console.log(output); // --> true let output3 = balancedBrackets('[(]{)}'); console.log(output3); // --> false 🔽 첫번째 문제 풀이 - switch 문으로 개별 케이스 나눔 switch 문으로 써서 풀긴 했는데, 사실 위의 3가지 경우는 여는 괄..