ziglog

    Search by

    5월 4주차 기록

    May 27, 2023 • ☕️☕️ 8 min read

    왜 연휴마다 비가 오냐고 🤯


    배워가기

    이벤트 스토밍 Event Storming

    • 목적

      • 도메인 지식의 상향 평준화
    • 여기서 이벤트란?

      • 비즈니스적으로 관심있는 사건. ‘이벤트’
      • 프론트엔드의 클릭 이벤트 같은 것이 아니라, 비즈니스 적으로 의미있는 이벤트
      • 예시) 셀러가 광고를 신청한다.
    • 3가지 종류

      1. 빅픽처 Big Picture
      2. 프로세스 모델링 Process Modeling
      3. 소프트웨어 모델링 Software Modeling

    CSS 이것저것

    • caret-color
      • input cursor의 색상을 지정할 수 있다.
    • invert()
      • 이미지의 색상을 반전시킨다

    Ref

    Form에서 유효성을 처리하는 3가지 타이밍

    • submit
    • typing
    • blur

    React의 input 컨트롤하기

    react의 input은 defaultValue가 지정되어 있지 않다면 uncontrolled 컴포넌트로 판단한다. 이때 input에 값을 입력하기 시작하면 controlled 컴포넌트로 변경된다. 이때 에러 메시지가 발생한다.

    A component is changing an uncontrolled input to be controlled.

    input field의 value가 undefined에서 defined value로 바뀌기 때문이다.

    이에 대한 해결책은 두 가지가 있다.

    1. 빈 값으로 defaultValue를 지정하여 input field의 초기값을 만들어준다.
    Copy
    <input defaultValue="" />
    1. value 속성을 지정하여 렌더링 과정에서 field.value의 값이 undefined일 때도 빈 문자열로 평가되도록 한다.
    Copy
    <input value={field.value || ""} />

    🙄 다만 위 상황은 onChange 핸들러를 사용하지 않은 특수한 경우에 input을 제어하는 방식이다. (블로그 글 참고)

    React에서 일반적인 input의 사용 방식은 👇

    💡 value vs defaultValue

    1. React state값으로 input의 value를 넣고 handler로 제어하는 방식(controlled component) - value
    • <input value={value} onClick={...} />
    1. 컴포넌트 안에 DOM handler를 사용하는 방식(uncontrolled component) - defaultValue
    • <input ref={ref} defaultValue="" />

    Ref

    CSS env vs constant

    iOS 11.2 업데이트에서 CSS constant가 제거되었다. 이후 버전에서는 env를 사용해야한다.

    • iOS 11.0 이상

      • e.g. env(safe-area-inset-bottom);
    • iOS 11.0 이하

      • e.g. constant(safe-area-inset-bottom);

    nextFrame

    Copy
    nextFrame(...args: Parameters<typeof requestAnimationFrame>) {
      // 해당 프레임이 아닌 nextFrame에 실행한다.
      return requestAnimationFrame(() => {
        return requestAnimationFrame(...args)
      })
    }

    🤔 nextFrame은 언제쓸까?

    다음 이미지는 headless-ui의 modal 관련 코드로, 모달이 열리면 포커스를 다음 요소로 이동시킨다.

    01

    문제는 Dialog가 열려야 포커스가 가능한데, Dialog가 열리지도 않으면 Focus가 불가능하다. 그래서 nextFrame같은 함수를 사용한다.

    Error.captureStackTrace

    Error.captureStackTrace는 내부에서 어떤 일이 일어나는지 알려주고, 스택에서 불필요한 프레임을 제거하기 위해 사용한다.

    첫 번째 인자로 object와 두 번째 인자로 function을 선택적으로 넘긴다. 스택 트레이스를 캡처하는 것은 현재의 스택 트레이스를 캡처하고 대상 객체 안에 stack 프로퍼티를 만들어 저장한다.

    Copy
    const myObj = {};
    
    function c() {}
    
    function b() {
      // myObj에 현재의 스택 트레이스를 저장한다.
      Error.captureStackTrace(myObj);
      c();
    }
    
    function a() {
      b();
    }
    
    a();
    
    console.log(myObj.stack);

    콘솔로 출력한 스택에는 함수 ab만 확인할 수 있다.

    Ref https://ui.toast.com/weekly-pick/ko_20170306

    Error.captureStackTrace 함수에 두 번째 인자로 함수를 전달하면 어떻게 될까?

    Copy
    const myObj = {};
    
    function d() {
      // myObj에 현재의 스택 트레이스를 저장한다.
      // 이번에는 `b`와 `b` 이후의 프레임들을 모두 숨길 것이다.
      Error.captureStackTrace(myObj, b);
    }
    
    function c() {
      d();
    }
    
    function b() {
      c();
    }
    
    function a() {
      b();
    }
    
    a();
    
    console.log(myObj.stack);

    콘솔로 출력하면 스택 트레이스에 a만 출력된다. Error.captureStackTraceFunction에 함수 b를 전달하면 b와 그 위의 모든 프레임들을 숨기기 때문이다.

    이러한 스택 조작 방법을 사용해 사용자와 관련된 스택 트레이스를 사용자와 관련성 있게 만들 수 있다.

    nest.js winston logger

    Nest.js에서 logging 작업을 도와주는 툴이다.

    로그 레벨을 지정하여 지정된 로그 레벨 이상의 레벨만 출력할 수 있으며, 레벨별 색상을 적용할 수도 있다. 02

    로그를 파일로 남기려면 winston-daily-rotate-file 을 추가 설치한다

    Ref https://velog.io/@wngud4950/NestJS-Winston-Logger-적용기

    axios cacheAdapter

    axios에 다음과 같이 adapter 옵션을 추가할 수 있다.

    Copy
    import axios from "axios";
    import { cacheAdapterEnhancer } from "axios-extensions";
    
    const axiosInstance: AxiosInstance = axios.create({
      adapter: cacheAdapterEnhancer(axios.defaults.adapter, {
        // 캐시 기본 사용 여부
        enabledByDefault: false,
      }),
    });

    adapter를 사용하면 커스텀 핸들링 요청을 처리할 수 있어 테스트가 쉬워진다. 이때 커스텀 핸들러는 유효한 Promise 응답을 반환해야 한다.

    axios-extension의 cacheAdapterEnhancer를 사용할 수도 있다

    Ref

    온/오프라인 상태를 감지하는 이벤트

    window event에는 온/오프라인 상태를 감지하는 이벤트도 있다

    Copy
    window.addEventListener("online", handleOnline);
    window.addEventListener("offline", handleOffline);

    와이파이를 껐다켰다 해보면 이벤트 핸들러가 실행된다.


    이것저것

    • 자바스크립트에서 속성 기반 테스트를 도와주는 fast-check 라이브러리
    • PerformanceAPI - 현재 페이지의 성능 관련 정보를 정밀한 타임스탬프(milliseconds)로 보여준다. (ex. performance.now)(Ref)

    기타공유

    버스 지수(Bus factor)

    03

    🥲

    React-Query가 필요하지 않을 수도 있다

    React Query의 메인테이너가 작성한 글이다.

    React Server Components가 등장하면서, React Query의 필요성에 대한 의문이 많이 제기되었나보다.

    기술의 많은 발전이 있었지만, 아무튼 React Query의 첫 번째 주요 기능은 클라이언트에서 비동기 상태를 관리하는 것이다. 그런데 서버 컴포넌트 등의 등장으로 data fetching이 서버에서 단독으로 이루어진다면 - React Query는 필요하지 않을 수도 있다. (그땐 원하는 걸 쓰면 된다!)

    하지만 React Query도 서버 컴포넌트와 함께 사용할 수 있는 여지가 얼마든지 있다. 처음 프로젝트를 시작할 때 몇몇 컴포넌트만을 서버로 옮길 수도 있으며, 서버 컴포넌트에서 캐시를 prefetch한 후 그 결과를 클라이언트 컴포넌트로 전달하여 그때 useQuery를 사요할 수도 있다. SSR에서 React Query를 사용하는 방식은 이미 문서에 잘 나와있다.

    더 복잡한 케이스로 가보자면, 인피니트 스크롤 등을 만들 때 첫 번째 페이지만 서버에서 prefetch하고, 스크롤 이벤트로 발생하는 추가 페이지 요청은 클라이언트에서 실행할 수 있다.

    React Query는 이렇게 서버 컴포넌트와도 통합될 수 있으며, data fetching이 아닌 다른 목적으로도 얼마든지 사용될 수 있다. React Query는 당장 서버 컴포넌트로 이전할 계획은 없지만, 그 중간 다리로 많은 역할을 할 수 있을 것이다. ‘React Query의 종말’은 너무 부풀려진 소문이다!

    Ref https://tkdodo.eu/blog/you-might-not-need-react-query

    토스 simplicity-23

    홈페이지에 엄청 공을 들인 것 같다. 화면과 오디오 싱크를 맞춘 것도 신박하다.

    개인적으로는 조금 정신없긴 하지만 🤷‍♀️ 처음에 어떻게 스크롤 넘기는지도 몰랐다…

    개발자 컨퍼런스 slash-23도 준비중인 것 같다.

    Ref https://simplicity-23.toss.im/

    GirlfriendGPT

    결국 이런게 나오고 마는구나…

    • 목소리 커스텀
    • 텔레그램에 연결
    • 선호가 반영된 개인 커스텀
    • 셀피 지원

    등까지 갖췄다고 한다. 🥲

    Ref https://github.com/EniasCailliau/GirlfriendGPT


    마무리

    이번주엔 새벽 3시 배포도 있었고, 워킹그룹 온보딩도 있었고… 꽤나 일을 열심히 한(?) 기분이다.

    그래서 부처님오신날 연휴 껴서 놀러가려고 했는데, 왜 연휴마다 비가 오냐고~~ ☔️🔫


    Relative Posts:

    6월 첫주차 기록

    June 3, 2023

    5월 3주차 기록

    May 20, 2023

    zigsong

    지그의 개발 블로그

    RotateLinkImg-iconRotateLinkImg-iconRotateLinkImg-icon