ziglog

    Search by

    5월 첫주차 기록

    May 6, 2024 • ☕️☕️ 12 min read

    배워가기


    package.json의 packageManager

    패키지가 특정 패키지 매니저를 사용해야 할 경우 특정 패키지와 버전을 지정할 수 있는 필드로, 아래와 같이 작성한다.

    Copy
    {
      "packageManager": "yarn@3.2.4"
    }

    Ref https://beomy.github.io/tech/etc/package-json/#packagemanager-node

    MobX-State-Tree

    MobX boilerplate 없이 반응형 상태 관리를 제공한다.

    MobX는 상태 관리 ‘엔진’으로 사용되고, MobX-State-Tree는 거기에 더해 앱에 필요한 설계와 도구들을 제공한다. 작은 앱의 사이즈에서 빠른 속도로 확장할 때 유용하다.

    Copy
    import { types, onSnapshot } from "mobx-state-tree"
    
    const Tweet = types
      .model("Tweet", {
        body: types.string,
        read: false 
      })
      .actions((tweet) => ({
        toggle() {
          tweet.read = !tweet.read
        }
      }))
    
    const TwitterStore = types.model("TwitterStore", {
      tweets: types.array(Tweet)
    })
    
    const twitterStore = TwitterStore.create({
      tweets: [
        {
          body: "Anyone tried MST?"
        }
      ]
    })
    
    onSnapshot(twitterStore, (snapshot) => {
      console.log(snapshot)
    })
    
    twitterStore.tweets[0].toggle()
    

    모양새를 보니 recoil 같은 느낌도 들고(안 써봄 ㅎㅎ), reactive한 상태관리를 제공한다니 신기하다!

    Ref https://mobx-state-tree.js.org/intro/welcome

    자바스크립트 RegExp

    Copy
    new RegExp({}).test('mom') // true
    new RegExp({}).test('dad') // false

    RegExp 생성자에 객체를 넘겨주면 정규 표현식 /[object Object]/이 생성된다. 그렇기 때문에 new RegExp({}).test(str)/[object Object]/.test(str)로 평가된다. 따라서 test('mom')은 true를, test('dad') 는 false를 반환한다.

    (objectmom의 스펠링이 겹쳐서 true가 나온다는 뜻이었다…)

    ffmpeg

    ffmpeg는 널리 사용되는 미디어 포맷 변환 도구 중 하나다.

    Copy
    brew install ffmpeg

    예를 들어 jfif 이미지를 jpg로 변환한다면, ffmpeg -i input.jfif output.jpg 와 실행할 수 있다.

    RHF의 get

    react-hook-form에는 공식문서에는 없는 get 이라는 함수가 있다. 이는 RHF key를 기반으로 에러 객체를 찾아내는대 용이하다.

    Copy
    import { useForm, get } from 'react-hook-form'
    ...
    const { formState } = useForm()
    const nestedError = get(formState.errors, 'nested.name')

    하지만, 공식적으로 지원하는 함수는 아니어서 필요하다면 lodash의 get을 사용하는것을 권장한다고..

    Ref https://github.com/react-hook-form/react-hook-form/issues/3422

    CSS flex 요리조리

    CSS flex 속성에 값을 하나만 넣어서 적용하면 다음과 같은 특징이 있다.

    • flex: 1 => 일반 숫자를 넣으면 flex-grow로 적용
    • flex: 100px => 숫자에 단위를 붙이면 flex-basis로 적용 (vh, vw 등의 값도 가능하다)
    • flex에 일반 숫자가 적용될 경우 flex-basis는 0이 된다 (default 값은 auto)

    overflow: scroll 잘 쓰기

    • overflow: scroll을 설정하고 마우스를 연결하면 항상 스크롤바가 보인다.
    • scrollbarWidth: 'thin'을 적용하면 조금 더 얇은 스크롤바를 사용할 수 있다.
    • media 쿼리를 이용해서 pc일때만 적용해주면 더 좋다.

    CSS order 속성

    flex 혹은 grid의 하위 요소를 수동으로 정렬할 때 사용하는 속성이다. 마치 z-index 같은 느낌이다.

    브라우저 호환성은 상당히 좋은 편이다.

    order 속성은 시각적인 배치에만 영향을 주기 때문에 접근성을 고려해야 하는 상황에는 사용을 주의해야 한다. 예를 들어, 스크린 리더를 이용할 경우에는 order의 영향을 받지 않기 때문에, 시각적으로 보았을 때와 비시각적으로 보았을 때의 순서가 다르게 보일 수 있다.

    MSW 2.0에서의 bypasspassthrough

    • passthrough는 모킹 동작을 수행하지 않고, 실제 API 서버로 요청하도록 할 수 있다.
    • bypass는 실제 API 서버로 요청하고, 응답 값을 가로채올 수 있다.

    둘의 차이는?

    • bypass와 passthrough는 실제 API 서버로 요청할 수 있도록 하는 것은 동일하다.
    • bypass는 API 서버 요청을 조작 및 응답 값을 가로채는 등 전/후처리를 추가할 수 있다.
      • 조금 추한점은 bypass를 사용할 시, 네트워크 요청을 2번 발생시킨다.
      • 서비스워커로 1번, API 서버로 1번 => 네트워크 추적 도구에 두번 찍혀서 조금 불편하다.
    • 네트워크 요청 헤더에 x-msw-intention: bypass라고 붙어있는 것으로 구분하면 된다.

    과거의 유산들

    • window.history.replaceStatepushState의 두번째 인자는 title인데, 현재 대부분의 브라우저에서는 더 이상 이를 처리하지 않는다. 하지만, 기존에 작성된 코드와의 호환성 문제 때문에 해당 파라미터는 여전히 존재하며 보통 빈 string을 넘긴다.

    • document.all은 HTML 문서의 모든 요소에 대한 참조를 배열 형태로 반환한다. 그러나 더 이상 사용되지 않으며, 특이한 점은 객체를 반환하는데도 불구하고 자바스크립트에서 document.all은 특별하게 falsy로 처리된다. 이는 과거 코드 패턴 때문이라고 하는데, document.all은 IE에서만 지원했고 넷스케이프에선 document.getElementById를 지원했었다. 이 차이를 처리하기 위해 아래와 같은 코드패턴을 많이 사용했었다. 그러나 웹이 발전하면서 document.all은 구식이 되었고 이에 대한 지원을 갑자기 끊는 대신 제공은 하되, ToBoolean에서는 falsy로 처리하면서 자연스럽게 현대 버전의 코드를 사용하도록 유도하는 것이라고 한다.

    Copy
    if (document.all) {
      // code that uses `document.all`
    } else if (document.getElementById) {
      // code that uses `document.getElementById`
    }

    Ref https://stackoverflow.com/questions/10350142/why-is-document-all-falsy

    input type checkbox의 이벤트

    <input type='checkbox' />에서 value가 지정되지 않을 때 이벤트가 발생하면 value 값은 'on'으로 전달된다.

    click, change 등의 이벤트에서는 checked 값에 관계없이 항상 같은 값을 전달하며,

    form의 서버 전송 또는 form 요소로 formData 생성 시 checked 값에 따라 전달 여부가 나뉜다.

    HTML과 CSS 이모저모

    HTML과 CSS는 보통 웹 브라우저에서 사용되지만, 웹 브라우저 이외의 경우에도 사용될 때가 있다. 예를 들어, Spring Boot 환경에서 Thymeleaf 템플릿 엔진을 이용하여 PDF를 생성할 때 HTML과 CSS를 사용한다. 하지만 모든 CSS 문법을 지원하지 않기 때문에, 퍼블리싱할 때 지원되지 않는 CSS를 사용하지 않도록 주의가 필요하다.

    팁이 있다면 비교적 최신 문법이 아니라 예전에 많이 사용되던 문법을 사용하여 퍼블리싱하는 것이 시행착오를 줄일 수 있는 방법이 될 것이다. 예를 들어, 좌우로 요소를 배치하고자 할 때, flexbox의 space-between 이 아니라 float: leftfloat: right 를 이용하는 것이다.

    Node.js v22의 ESM 동기 불러오기

    Node.js 22버전부터 require로 ESM을 동기식으로 가져오는 실험적인 기능이 추가되었다.

    --experimental-require-module 플래그를 사용해서 접근할 수 있다. 하지만 아래 조건이 충족되어야 한다.

    1. package.json에 "type": "module" 추가
    2. 모듈이 완전히 동기적이어야 한다. (top-level await 사용 X)

    vite의 Native ESM 구멍

    <script type="module"> (Native ESM)을 사용할 수 있는 버전은 크롬 61이상, Safari 11 이상이지만, import.meta.env, async generator function, dynamic import를 사용할 수 있는 버전은 크롬 64이상, Safari 12이상이다.

    따라서, Vite Legacy 플러그인을 사용할 때 크롬 6164 버전과 Safari 1112 사이에 구멍이 생긴다. (ESM을 불러올 순 있지만, 모듈에서 에러가 발생할 수 있다).

    Legacy 플러그인은 이를 감지해서 레거시 번들을 불러오도록 fallback 처리를 하고 있다.

    index.html에 환경변수 주입하기

    리액트 앱에서 public 디렉토리의 있는 index.html에서도 환경변수를 쓸 수 있다.

    %REACT_APP_환경변수_이름% 형식으로 사용하며, 빌드타임에 주입된다.

    Ref https://create-react-app.dev/docs/adding-custom-environment-variables/#referencing-environment-variables-in-the-html

    RTL로 hook 테스트하기

    React-Testing-Library를 사용하여 커스텀 훅을 테스트하기 위해서는 act 함수를 알아야 한다.

    렌더링과 같은 작업, 유저 이벤트, 데이터 가져오기와 같은 동작을 유저 인터페이스와의 상호작용하는 “단위”로 간주한다.

    rerender 함수와 다른 점

    • rerender - 렌더링 촉발 원인이 “부모”에 있음
    • act - 렌더링 촉발 원인이 “자신”에게 있음

    vitest의 environment 옵션

    테스트에 사용할 다른 환경을 지정하는 옵션으로, 다음 옵션을 사용할 수 있다.

    • node: default 옵션
    • jsdom: 브라우저를 유사하게 구현
    • happy-dom: jsdom와 비슷, jsdom보다 빠르지만 몇가지 부족한 API
    • edge-runtime: vercel의 edge-runtime을 유사하게 구현

    App Scheme 이모저모

    • shouldKeepPresentedView - 현재 웹뷰를 닫지 않고 다음 웹뷰를 여는 것에 관한 파라미터
    • webview_navButtonType=back을 하면 현재 웹뷰 이후의 웹뷰부터 히스토리가 차곡차곡 쌓여서 들르는 페이지마다 뒤로가기를 할 수 있다.

    ky

    fetch API 기반으로 동작하는 HTTP 요청 라이브러리. fetch API를 좀 더 편하게 사용할 수 있도록 래핑한 모던 브라우저향 라이브러리다.

    axios에 비해서 기능은 적지만 실사용에는 문제 없을 정도로 충분한 기능을 제공한다. axios보다 용량도 훨씬 가볍다는 것도 장점. retry, timeout handling와 같이 axios에는 없는 기능도 있다. 다만 React 환경에서 보통 같이 사용되는 tanstack query도 retry 기능을 가지고 있기 때문에, 두 기능이 충돌하지 않도록 기능을 잘 꺼두는 것이 좋다. 그렇지 않으면 중첩 retry 지옥을 맛볼 수 있다. 😈

    Ref https://github.com/sindresorhus/ky

    삭제한 원격 브랜치 복구하기

    삭제한 원격 브랜치에 커밋을 한 이력이 있어야만 복구가 가능하다(git reflog에 남아 있어야만 복구 가능)

    • git reflog를 통해 삭제한 브랜치의 마지막 커밋 해시값을 알아온다.
    • git checkout -b 브랜치명 {commit hash} 를 통해 삭제한 브랜치를 복구/이동한다

    React 19의 Remove layout effect warning during SSR

    SSR 환경에서 useLayoutEffect를 사용할 때 발생할 수 있는 잠재 이슈를 알리기 위한 경고 로그였지만 대부분의 사용처는 아래와 같은 분기 처리로 우회하고 있다.

    Copy
    const useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect

    이제는 이렇게 하지 않아도 되도록 경고를 제거했다.

    ECMA 2024의 새 문법 이모저모

    Pipeline Operator

    무분별한 함수 감싸기를 조금은 편하게 볼 수 있을까?

    Copy
    // Without pipeline operator
    const calculatedValue = Math.ceil(Math.pow(Math.max(0, -10), 1/3));
    
    // With pipeline operator
    const calculatedValue = -10
      |> (n => Math.max(0, n)) // Replacing Math.max
      |> (n => Math.pow(n, 1/3)) // Replacing Math.pow
      |> Math.ceil; // Using Math.ceil

    Records and Tuples

    데이터를 일부만 수정해서 새로운 배열을 빠르게 만들어 낼 수 있다.

    Copy
    // Creating an immutable record
    const userProfile = #{
      username: "IgorKomolov",
      age: 39,
    };
    
    // Creating an immutable tuple
    const numberSequence = #[10, 20, 30];
    
    // Updating these structures creates new instances
    const updatedProfile = userProfile.with({ age: 40});
    console.log(updatedProfile); // #{ username: "IgorKomolov", age: 40 }
    console.log(userProfile); // #{ username: "IgorKomolov", age: 39 } (remains the same)
    
    const newNumberSequence = numberSequence.with(1, 25);
    console.log(newNumberSequence); // #[10, 25, 30]
    console.log(numberSequence); // #[10, 20, 30] (remains the same)

    Object.groupBy()

    enum별로 분류해서 써야하는 상황에서 유용할 것 같다.

    Copy
    const inventory = [
      { name: "asparagus", type: "vegetables", quantity: 5 },
      { name: "bananas", type: "fruit", quantity: 0 },
      { name: "goat", type: "meat", quantity: 23 },
      { name: "cherries", type: "fruit", quantity: 5 },
      { name: "fish", type: "meat", quantity: 22 },
    ];
    
    const result = Object.groupBy(inventory, ({ type }) => type);
    
    /* Result is:
    {
      vegetables: [
        { name: 'asparagus', type: 'vegetables', quantity: 5 },
      ],
      fruit: [
        { name: "bananas", type: "fruit", quantity: 0 },
        { name: "cherries", type: "fruit", quantity: 5 }
      ],
      meat: [
        { name: "goat", type: "meat", quantity: 23 },
        { name: "fish", type: "meat", quantity: 22 }
      ]
    }
    */

    Ref https://github.com/tc39/proposal-pipeline-operator

    이것저것 모음집


    • syncpack - 큰 자바스크립트 모노레포 프로젝트에서 디펜던시의 버전을 관리해준다. (Ref)
    • iOS 13 이상부터는 navigator.userAgent 값이 iPad가 아닌 Macintosh로 내려올 수 있다. 아이패드의 사파리 디폴트 값이 데스크톱 모드로 변경되어 그렇다고 한다.
    • HTML Popover가 베이스라인이 됐다. (Ref)
    • 자바스크립트에서 집합 요소의 unique함을 보장하기 위해 Set 자료구조를 제공하는데, Set으로 선언한 집합을 다시 배열로 변환 시 insertion order를 보장해준다.
    • fnm을 사용하면 워크스페이스 단위로 엄청 편하게 node version을 바꿀 수 있다. (.zshrc에 eval "$(fnm env --use-on-cd)"만 추가하면 된다.) vscode를 켜면 자동으로 .node-version에 맞게 버전이 변경된다.
    • VSCode 기능 중 devcontainer라는 것이 있다. 컨테이너에 개발 환경을 구성할 수 있다 (cf. 범용으로 런타임 버전을 관리해주는 도구도 있다 (asdf-vm))
    • styled-components에 전달하는 prop에 $를 프리픽스로 붙이면 transient props가 되고 실제 리액트 컴포넌트나 돔 요소까지 해당 prop이 전달되는 것을 방지할 수 있다.
    • redux-persist를 사용하면 redux-toolkit으로 전역 관리하는 상태들을 로컬스토리지에 저장하면서 새로고침을 해도 전역 상태를 관리할 수 있다.
    • vite의 설정파일에서는 기본적으로 .env파일을 로드하지 않는다. 그래서 만약 환경변수 접근이 필요하면 loadEnv 헬퍼를 사용하여 env 파일에 접근할 수 있다. (Ref)
    • Node.js v16.13 버전부터 Corepack 을 따로 설치하지 않아도 지원한다.

    기타공유


    테스트 피라미드

    좋은 테스트 코드를 작성하기 위한 가이드라인

    Ref https://www.integer.blog/practical-test-pyramid/?ref=linkedin.com

    asdf

    nvm, node, 등 여러 툴, 환경의 버전을 모두 매니지먼트 할 수 있는 시스템

    Ref https://github.com/asdf-vm/asdf

    마무리


    사흘 반 동안 연휴였는데, 농땡이 부리다가 부랴부랴 마지막 날 잠들기 전 쓰는 블로그.

    사내 TIL 챌린지가 있었어서 갑자기 양이 확 늘었다 🫠

    내~내 비만 쏟아지던 연휴도 이제 끝 ☔️


    Relative Posts:

    5월 2주차 기록

    May 11, 2024

    4월 4주차 기록

    April 27, 2024

    zigsong

    지그의 개발 블로그

    RotateLinkImg-iconRotateLinkImg-iconRotateLinkImg-icon