본문 바로가기

프론트엔드

모바일 기기에서 scroll 관련 버그 대응하기 프로젝트: 채식 지도 키워드: viewport height, window.innerHeight, scrollbar, pull-to-refresh, overscroll-behavior 상황 스크롤이 가능한 웹페이지를 moblie 기기에서 보면 예상치 못한 상황이 많이 일어난다. 그 중에서 1) vh가 viewport 보다 크게 잡히는 버그 2) scrollbar를 숨기고 싶은 상황 3) 안드로이드 기기의 pull-to-refresh 기능을 막고 싶은 상황을 대응하고자 한다. 해결 방법 height: 100vh에서 'vh' 단위는 'viewport height'를 의미하기 때문에 100vh는 브라우저 viewport의 높이와 일치해야한다. 하지만 모바일 기기의 경우는 주소창(top bar)과 navigati.. 더보기
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.. 더보기
Storybook에서 user interactions 테스트하기 프로젝트: loplat UI키워드: storybook addon interactions, Storybook test runner, mdx story, csf story, jest상황loplat UI에 있던 기존 jest test file들은 cli를 통해서 동작하며 테스트의 진행 과정을 눈으로 확인하기 힘들다는 단점이 있다.loplat UI는 비지니스 로직보다는 ui 중심이므로, 스토리북과 연동된 테스트를 실행하면서 테스트 진행 상황을 스토리북에서도 확인할 수 있으면 좋을 것이다.새로 알게된 'Storybook Addon Interactions'와 'Storybook Test Runner'를 도입하는 과정을 소개하고자한다.해결 과정 1 (storybook addon interactions)interact.. 더보기
JS library에서 cjs, esm format 모두 지원하기 프로젝트: loplat UI키워드: CommonJS, ES Modules, loplat UI, package.json, npm, babel, jest, rollup상황loplat UI는 tree shaking을 지원하기 위해 cjs format을 버리고 esm format의 빌드 결과를 채택했었다.(번들링 최적화를 통해 import cost 줄이기(1))때문에 es6 문법을 기본적으로 이해하지 못하는 환경(Jest test, Next/SSR build)에서는 라이브러리를 transpile해야하는 번거로움이 있다.(Next.js는 'next-transpile-modules' https://www.npmjs.com/package/next-transpile-modules를 사용해야하고, jest도 추가 opt.. 더보기
스탬프 투어 미션 구현하기(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.. 더보기
이미지 용량 최적화하기(feat. picture tag, sprite image) 프로젝트: loplat UI, 채식 지도 키워드: picture tag, source tag, WebP, sprite image, naver map marker, image optimization 상황 1 loplat UI의 Spinner 컴포넌트는 용량이 큰 sprite image와 css 애니메이션을 통해 구현했다. (참고: css animation steps로 Spinner 구현하기) gif를 사용하지 않고 png로 구현했음에도 아직 이미지 용량이 크다는 생각이 들었다. WebP 형식을 사용하려다가 safari 브라우저에서 지원하지않아 보류했는데, 크롬에서라도 WebP 이미지를 지원하고자 한다. 해결방법 1 picture tag를 사용하면 browser/display마다 최적의 이미지를 제공할 수 .. 더보기