ai 덕분에 코드 생산에 미친듯한 속도로 달리다 보니 나도 모르게 위임한 것들을 다시 살펴보느라 아주 오래간만에 재미있는 작업을 했습니다. 나도 모르게 위임한 것 첫 번째는 캐시 헤더입니다. 인터렉션 가능한 화면을 빠르게 마운트 시키기 위해 js청크 최적화 작업을 했습니다. 근데 어제는 분명히 304 응답받는 걸 봤는데 오늘은 모든 청크가 disk cache를 사용해서 네트워크 왕복 지연이 발생하지 않고 있었습니다. 관찰하는 시간에 따라 캐시 사용상태가 달랐습니다. 막연히 vite로 빌드하여 cache busting의 목적으로 정적파일에 해시값이 들어가서 배포된 파일은 유일하게 구분되어 캐싱된다고 알고 있었는데, 실제로 보니 간헐적으로 304와 캐시가 번갈아 적용되는 것 같았습니다. 헤더를 보니 위와 같..
클라이언트에서 왜 DB를 사용했을까요?총 세번의 리팩토링을 거쳤고, 각 단계마다 실패를 경험했습니다. 간단하게 기능을 설명드리자면 5개의 엔티티가 매우 자유도 높게 생성, 편집되는 기능을 구현했습니다.상태를 클라이언트 측에서 오랜 기간 끌고가며 편집해야 했습니다. 첫번째 구현"엔티티도 많고 관계도 복잡하기 때문에 각 상태를 정규화하고 key를 기반으로 참조하도록 작성하자"복잡한 상태간의 관계가 핵심입니다. 만약 객체간의 관계를 중첩으로 표현하면 깊은 객체의 약간의 수정에도 코드가 굉장히 많아집니다. 게다가 리랜더링 촉발을 위해 불변성을 유지하기 위해 중첩된 Copy on Write, 의도하지 않은 참조까지 생각하다보면 분명히 에러가 발생할겁니다. 첫번째 구현에서는 다행이 이런 상황을 예상하고 정규화된..
1. 문제발견: 느린 point-in-polygon 검사!위와 같이 각 지역 권역 폴리곤 내부에 포함되는 마커의 개수를 출력하는 기능이 있다.위 상태를 예롤 들자면 서울에 669개의 마커가 있다는 뜻이다. 지역에 마우스를 hover 할 때마다 계산이 되는데, 지역을 옮겨다닐때마다 스택이 blocking 되어서 반응성이 매우 떨어지고 있었다! 처음에는 마우스를 hover 할 때마다 변경되는 district 데이터가 변경됨에 따라 테이블 같은 dom이 많은 곳에 리랜더링이 발생하는지 의심했지만, 리랜더링은 꽤 잘 최적화되어 있었다.문제는 전국 마커 중에 서울에 포함되는 마커 개수 계산 함수가 스택을 꽉 막아버린 것이었다.2. Ray-Casting알고리즘 간단한 이해기존코드를 보면const count = ()..
몇 개월 전 만해도 업로드 progress를 구현하려면 fetch로는 방법이 없었다. 웹소켓을 사용하든 폴링을 하든 서버에서 응답을 받아서 보여주거나 xml을 사용해서 업로드용 api request를 만들어야 했다. 근데 얼마 전에 ky에 onUploadProgress가 추가되었다!onDownloadProgress는 있었지만 분명히 fetch기반 라이브러리의 한계로 onUploadProgress는 없었다.분명히 fetch의 한계라고 했는데 어떻게 구현한걸까?1. ky의 onDownloadProgress는 어떻게 구현했을까ky는 fetch api기반의 http 클라이언트 라이브러리이다. 이 라이브러리에는 이미 onDownloadProgress 옵션이 구현되어 있었다.얼마나 다운로드가 완료되었는지 진행률을 ..
https://www.slash.page/ko/libraries/react/use-overlay/src/useOverlay.i18n useOverlay | Slash librariesuseOverlay는 Overlay를 선언적으로 다루기 위한 유틸리티입니다.www.slash.page이것은 토스에서 만든 오버레이를 선언적으로 다룰 수 있는 훅이다.useOverlay훅은 ui를 제공하지 않고 호출시점에 오버레이가 보이는(isOpen) 상태를 주입해 주고, 보이지 않게 해주는 함수를 제공하는 훅이다. 즉, useOverlay를 사용하더라도 ui는 직접 만들어야 한다. 그 ui를 모달로 할지, 바텀시트로 할지는 개발자가 결정하면 된다. 이 글은 useOverlay를 사용하는 방법을 소개하는 글이나 코드를 읽어보..
1. clsx 분석clsx의 테스트 코드를 보면 다형성이 뛰어나다. 다양한 입력을 적절히 처리하고 있음을 알 수 있다.전부는 아니지만 몇 가지만 확인해 보자면// 가변 인자중에 truty한 값으로 클래스명을 만듦test("(compat) joins arrays of class names and ignore falsy values", () => { const out = clsx("a", 0, null, undefined, true, 1, "b"); assert.is(out, "a 1 b");});// 리터럴객체가 입력되면 값이 truty한 key로 클래스명을 만듦test("(compat) keeps object keys with truthy values", () => { const out = clsx({ ..
Demo page: http://mock-pilot-demo.s3-website.ap-northeast-2.amazonaws.com/github: https://github.com/kiwonbyun/mockpilot개발 동기 내가 좋아하는 몇몇 라이브러리 소스코드를 보다 보니 라이브러리라고 대단한 게 아니고 나도 할 수 있겠다는 자신감이 들었다. 그래서 뭔가 만들어봐야겠다는 생각이 있었다. 하지만 내가 가장 싫어하는 것은 행동에 이유가 없는 것이다. 정체를 알 수 없는 뭔가(?) 개발하기 위해 행동할 순 없다. 개발에 나서기 위해서는 이유(해결하고자 하는 불편함)가 있어야 했다. 뜬금없이 예전에 읽었던 뉴타입의 시대라는 책이 떠올랐다. 문제를 해결하는 사람이 아니라 문제를 문제라고 말하고 정의하는 사람이..
빠르게 성장하는 스타트업에게 빠르게 만들고, 배포하고, 유저의 반응을 체크하고, 빠르게 개선하는 게 중요하다는 것은 당연하다.그 순환 사이에 시행착오를 겪으면서 이런 비즈니스를 하는 사람들에게는 이런 기능이 중요하구나, 아 이런 부분은 옵션으로 제공하면 다양한 사용자가 만족할 수 있겠구나, 이런 부분은 추상화가 되어 모듈화 할 수 있겠구나, 같은 깨달음이 생긴다.스타트업의 개발자로서 성장하는 회사를 만들기 위해 중요한 것은 바로 이 시행착오를 통해 얻은 깨달음을 내 머리에만 넣어두는게 아니라, 코드에 적절히 녹여놔야 한다는 것이다.입사 후 첫 프로젝트를 하며 물류업계, 특히 의약품 물류업계에 대한 지식이 생겼다. 그리고 TMS, OMS, WMS를 만들면서 이것들을 어느 부분에서 모듈화 해야 하는지 시행착..