돌멩이 하나 39

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

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

React Query를 활용한 테이블에서 데이터 정렬하기

기존 테이블 컴포넌트에 정렬 API를 연동하는 작업을 하던 중 다음과 같은 상황을 만났다. (간단한 예제 코드를 만들어 보고자 했으나 공개 API로 같은 현상을 재현하기가 어려웠다 😢) 먼저 테이블은 antd의 table 컴포넌트로 테이블의 각 열마다 정렬 버튼이 있다. 정렬 버튼을 처음 누르면 오름차순 정렬(ascend), 두번째로 누르면 내림차순 정렬(descend), 세번째로 누르면 정렬 취소 순서로 동작하고, 사용자가 특정 열의 정렬 버튼을 누를 때마다 해당 열이 ascend인지 descend인지 알 수 있다. 이 정보를 바탕으로 서버에 쿼리 스트링으로 정렬된 데이터를 요청한다. 그러자 특정 열의 정렬 버튼을 누를 때마다 화면이 full refresh가 되었다...! 😰 정렬 버튼을 한번씩 눌러서..

React ErrorBoundary와 react-query를 사용하여 예외 처리 설계하기

예외 처리를 설계하며 고민한 내용들을 간략하게 정리해 보았다. 프로젝트마다 필요한 예외 처리가 다르고, 구현 방식도 여러 가지가 있기에 개발의 많은 부분이 그렇듯 정답이 없는 것 같다. 나중에 시간이 흐른 뒤 이 포스팅을 보면 분명 '왜 이렇게 했지?'라고 생각할 것 같다. 😇 하지만 같은 고민을 하는 누군가에게 조금이나마 도움이 될 수 있기를 바란다. 1. 에러의 분류 먼저 위의 도식을 참고하여 프로젝트 상황에 맞게 에러를 분류해 보았다. 사용자에게 에러가 발생한 이유를 설명하고 사용자의 액션을 유도하는 장치를 제공하는 것을 예외 처리의 핵심으로 두었다. 1. 예상 가능한 에러 a. 사용자 입력 값에 대한 에러 - 에러 발생 상황 예시: 로그인 시 틀린 비밀번호를 입력하거나 회원가입시 중복 아이디 또는..

React의 key에 index를 사용하면 안 되는 이유 (feat. 무한스크롤)

지난주부터 회사 프로젝트에서 다른 팀원 분이 담당하던 feature를 내가 맡게 되었다. 인계를 받으면서 이슈 중 하나가 무한스크롤 기능 중 스크롤을 위로 올려 이전 페이지 아이템을 가져올 때 사용자가 현재 보고 있는 아이템이 화면에 유지되지 않고 새로 받아온 페이지의 첫번째 아이템으로 화면이 튀는 현상이었다. 반면 스크롤을 아래쪽으로 내려서 다음 페이지 아이템을 가져올 때는 현재 보고 있는 아이템이 화면에 그대로 유지되었다. 인계를 해준 팀원 분은 이 이슈를 스크롤 앵커링 문제라고 생각했고, 바닐라 JS를 사용하거나 React에서도 useRef를 사용해서 직접 DOM 조작을 할 때는 위쪽이나 아래쪽 어디로 스크롤을 하든지 스크롤 앵커링이 정상적으로 동작하며, React의 상태를 UI에 렌더링하는 경우 ..

2023년 한 해를 돌아보며

여러 가지 변화가 많은 한 해였다. 6년 간 프리랜서 통번역사로 일하던 생활을 정리하고, 작년 하반기부터 시작한 부트캠프를 수료했다. 수료식 바로 다음날 포르투갈행 비행길에 올라 3주 간 여행을 하고 돌아와 휴식과 충전의 시간을 가졌다. 이후 한 달여의 취직 준비 기간을 거쳐 웹 프론트엔드 개발자로 입사했다. 감사하게도 1개월 만에 수습 기간을 끝내고 정규직이 되었다. 입사 이후 개인적으로는 1년 동안 두 집 살림을 하던 생활 역시 정리하고, 한 곳에 제대로 둥지를 틀었다. 4년 동안 살던 집을 빼고 이사를 했고, 짐 정리를 전부 마치는데 거의 두 달 반 정도가 걸렸다. 평일에는 여유가 나지 않아 주말 밖에 시간이 없었던 데다가 개인 일정이 있거나 컨디션이 좋지 않아 휴식을 취하거나 하면 한두 주가 그냥..

돌멩이 하나 2023.12.23

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

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

더닝 크루거 효과

달력을 보니 딱 1년 전 오늘, 2022년 10월 20일이 6개월 과정 부트캠프의 개강일이었다. 추석 연휴가 끝나고 지난 보름 가량 내내 씨름하고 있는 기능이 있다. 아직까지 해결하지 못했고, 근 시일 내에 해결할 수 있을 것 같지 않다. 뭐가 문제인지 파악하는 데에만 몇날 며칠의 시간을 보냈다. 이런 시간을 보내면서 부트캠프 과정이 끝나고 취업 준비를 하며 프론트엔드 기능 구현 챌린지를 할 때 시간이 걸릴 뿐 찾아보면 구현하지 못할 기능이 없을 것 같다고 자신만만해 하던 나 녀석이 떠올랐다. 유명한 더닝 크루거 곡선의 우매함의 봉우리를 향해 등반하고 있던 시절이었다고 할 수 있다. 그리고 두세 달이 지난 지금은 문제의 봉우리를 지나 절망의 계곡의 내리막길에 들어선 시간이라고 할 수 있다. 예전 글을 뒤..

돌멩이 하나 2023.10.20

ant design과 tailwind css 충돌 이슈 해결

UI 라이브러리를 처음 사용해 보고 있다. 개발의 많은 부분이 트레이드 오프인데 UI 라이브러리 도입도 이러한 부분이 있는 것 같다. pros. - 직관적이고 깔끔한 UX 컴포넌트 지원 - 빠른 개발 속도 - 웹 접근성 준수 cons. - 커스터마이징의 한계 - 이슈가 생기면 내가 코드를 잘못 작성한 탓인지 라이브러리 자체의 이슈인지 매번 찾아봐야함 antd 도입을 결정하고 난 후 매일 antd 레포의 이슈를 뒤지는 삶을 살고 있다 해도 과언이 아니다. 그 첫 시작은 tailwind와의 충돌이었다. tailwind가 설치된 프로젝트에 antd를 추가로 설치하고 버튼 컴포넌트를 불러왔더니 버튼이 보이지 않았다 😱 개발자 도구를 보면 antd primary button의 배경색 #1677ff 가 tailwi..

비전공자로서 FE 개발자로 취업하기까지의 여정 - 2탄

1탄을 작성할 때까지만 해도 이 포스팅이 시리즈물이 될 줄은 몰랐다. (이 앞의 이야기가 궁금하신 분들은 이곳에서 확인할 수 있습니다.) 결론부터 이야기하면 한 달 전 첫 출근을 했던 회사는 1주일 만에 퇴사하고 나왔다. 회사를 나온 가장 큰 이유는 회사의 커뮤니케이션 방식이 불투명했기 때문이었다. 첫날 출근을 했을 때부터 면접 때 얘기했던 개발팀 내부 구조와 주요 업무 등이 달랐다. 그래서 출근을 하자마자 바로 퇴사를 고민했으나 신입 취업 시장이 어떤지 잘 알기 때문에 지금 상황을 받아들이고 내가 해나갈 수 있는 부분을 잘 해보자고 생각하고 다니기로 했으나.. 결국은 일주일만에 그만두기로 결정했다. 그리고 바로 재구직을 준비했다. 퇴사한 날 곧바로 여러 곳에 서류 지원을 했고, 그 중 총 네 곳에 서류..

돌멩이 하나 2023.08.13

styled-components에서 custom props 사용하기

기술 과제를 진행하면서 styled-components를 사용해 공통 ui 컴포넌트를 만들던 중 input 입력란의 텍스트 정렬을 다르게 가져가야 할 필요가 생겼다. 아래의 화면 이미지와 같이 우편번호 input은 중앙정렬, 그 외에 input은 일반적인 좌측 정렬로 화면 디자인이 구성되어 있었다. 이를 위해 input ui 컴포넌트에서 prop으로 textAlign 값을 줘서 제어하려고 시도했다. // 공통 ui 컴포넌트 선언부 export const Input = styled.input` box-sizing: border-box; width: ${(props) => props.width || 'inherit'}; height: 40px; padding: 9px 13px; border: 1px soli..