본문 바로가기

프론트엔드/React

Pagination Component를 선언형으로 구현하기 키워드: 선언형 프로그래밍, Pagination, React상황기존 Pagination UI 로직이 절차형으로 되어있었다.코드를 이해하기 어렵고 유지보수가 힘들어질거란 걱정이 들어 코드를 선언형으로 리팩토링하고자 한다.아래는 기존 코드의 예시이다. (코드의 일부이기 때문에 이해가 되진 않을 것이다.) ...const searchSiblings = (page: number, dist: number) => { const left = page - dist; const right = page + dist; if (right >= MAX_PAGE && left = _pagerCount) { return; } } if (left > MIN_PAGE) { leftSiblings.push.. 더보기
React 18 useDeferredValue로 성능 최적화하기 프로젝트: tracking map키워드: react v18, useDeferredValue, interruptible rendering, rendering blocking상황react 18에서 새로 나온 useDeferredValue hook을 사용해보고 장점을 알아본다.실제 프로젝트에 적용하여 렌더링 성능 최적화를 확인한다.해결 과정 1먼저 useDeferredValue hook을 체험해보기 위해 간단한 코드를 작성한다.아래 코드는 input element에 value를 입력할 때마다, boxes를 새로 연산하여 렌더링하는 코드이다. // Test.tsximport React, { useState, useDeferredValue, useMemo } from 'react';function Test() .. 더보기
React 18 Suspense 기능 알아보기(feat. SWR, msw) 키워드: react v18, suspense, ErrorBoundary, SWR, msw, mock API 상황 React 18에 새로 추가된 Suspense와 기존의 ErrorBoundary 기능을 조합하여 사용해보고, 그 장점을 파악한다. 해결과정 Suspense를 사용하기 앞서, data fetching과 렌더링을 수행하는 Block 컴포넌트를 작성한다. // Block.tsx import useSWR from 'swr'; import React from 'react'; const fetcher = (url: string) => fetch(url).then((res) => res.json()); function Block({ label }: { label: string }) { const { dat.. 더보기
react-window로 렌더링 성능 최적화하기 프로젝트: 채식 지도 키워드: react-window, rendering optimization 상황 매장 목록을 보여주는 UI를 구현하였는데, 매장 Row마다 각각 'button' DOM으로 구현되어있다. Next.js 프레임워크 덕분에 이미지()는 자동으로 lazy loading 되고 있어서 image 최적화 문제는 없을 것이다. 하지만 훗날 매장이 점점 많아지고 리스트가 길어짐에 따라 DOM 렌더링 성능에 문제가 생기고 화면이 끊겨보일 가능성이 있다. 그래서 사용자에게 보이는 DOM만 실제로 렌더링하는 'windowing 기법'을 써보기로 한다. 해결 방법 react 라이브러리 중 react-window라는 라이브러리를 설치한다. yarn add react-window yarn add -D @typ.. 더보기
UI library에서 spacing system props 구현하기 프로젝트: loplat UI 키워드: system props, spacing props, typescript 상황 컴포넌트 종류와 상관없이 모든 컴포넌트가 공유하면 좋은 prop이 있다. UI component에 margin이나 padding 값만 추가하고 싶은 경우가 많은데, 사소한 spacing css 때문에 class를 부여하거나 styled API를 사용하는 것은 수고롭다. loplat UI를 사내 프로젝트에 적용하면서 spacing(margin, padding) prop이 필요함을 느꼈기 때문에 spacing system prop을 만들고 적용하고자 한다. 해결방법 spacing system prop은 아래와 같이 사용 가능하다. // margin-top: 8px; margin-bottom: 8.. 더보기
스탬프 투어 미션 구현하기(feat. firestore, redux saga) 프로젝트: SNU FESTIVAL 키워드: firestore, redux saga 상황 축제 사이트를 구현할 때 미션 기능을 추가해달라는 요청이 들어왔다. 페이지 곳곳에 5개의 미션이 나누어져 있고 특정 미션을 클리어하면 미션 카드에 그림 스탬프가 채워지는 형식이었다. 웹사이트 전체에 걸쳐 미션 진행 상태를 다뤄야 해야하기 때문에 redux를 이용하여 브라우저 내 상태 관리를 하는 것이 좋다고 생각했다. firebase auth 로그인을 한 상태로 미션이 이루어지기 때문에 firestore에 uid(사용자 계정의 unique id)를 문서 이름(key)으로 하고, 미션 진행 상태를 value로 저장하는 방식으로 미션 데이터를 관리하기로 했다.(GET/SET을 할 때 대상 문서를 쉽게 찾을 수 있다.) 해.. 더보기
노래맞히기 게임 구현하기(feat. holwer.js, classList) 프로젝트: SNU FESTIVAL키워드: trigger css animation, classList, svg, holwer.js, Web Audio API상황:페스월드 축제의 미니게임인 '노래 맞히기'는 노래의 아주 짧은 부분만 듣고 제목을 맞히는 게임이다.키보드 조작이나 화면 터치를 통해 음악이 재생되도록 하고, 시각적인 재미를 줄 수 있도록 애니메이션도 곁들이고자 한다. 해결 과정페이지 단에서 addEventListener로 키보드 조작을 감지하고, A를 눌렀다면 'KeyA'에 해당하는 음악과 애니메이션을 재생하면 된다. function reducer(state, action) { if (action.type === 'toggle') { const { key } = action; ret.. 더보기
선언형 Portal, Modal 컴포넌트 구현하기 프로젝트: loplat UI 키워드: portal, createPortal, modal, createElement 상황 여러 프로젝트에서 Modal을 사용할 일이 많아 loplat UI에서 컴포넌트를 제공해주고자 한다. 렌더링부에서 container DOM과 children content만 선언하여 쉽게 react portal 기능을 사용할 수 있도록 하고자 한다. // 원하는 형태 children children 해결 과정 먼저 container와 chlidren을 prop으로 받아 createPortal을 실행하는 Portal 컴포넌트를 만든다. import React from 'react'; import ReactDOM from 'react-dom'; export interface PortalPro.. 더보기