ziglog

    Search by

    3월 4주차 기록

    March 25, 2022 • ☕️☕️☕️ 13 min read

    첫 판교 드라이브


    배워가기

    React 18의 상태 변경 Batching

    React 18 미만에서 사용자 이벤트에 대한 상태 변경은 일괄처리(Batching)되었다. 즉 일반적인 핸들러 내에서는 setState를 여러번 호출하더라도 일괄적으로 처리되어 리렌더링이 한번만 발생했다.

    그러나 PromisesetTimeout으로 발생하는 상태 변경은 일괄처리되지 않았다. setTimeout에서 setState를 두 번 호출하면 두 번 렌더링되었던 것이다.

    React 18에서는 상태 변경이 발생한 원인에 상관없이 모든 상태 변경은 일괄처리된다.이때, 의도적으로 일괄처리하지 않으려면 flushSync를 사용하면 된다.

    Ref https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html#automatic-batching

    useImperativeHandle

    useImperativeHandleref를 사용할 때 부모 컴포넌트에 노출되는 인스턴스 값을 사용자화(customizes)합니다. forwardRef와 함께 쓸 수 있는 hook이다.

    부모 컴포넌트가 자식 컴포넌트 내의 DOM에 접근하고 싶을 때, 자식 컴포넌트에서 forwardRef를 통해 넘겨받은 ref를 특정 DOM에 지정할 수 있다. 이때, 자식 컴포넌트에서 부모 컴포넌트에 노출하고 싶은 ref에 대한 인스턴스를 커스터마이징하고 싶다면 useImperativeHandle hook을 통해 정의할 수 있다. 즉 부모 컴포넌트로부터 forwarding된 ref를 재정의하는 것이다.

    Copy
    // 자식 컴포넌트
    function FancyInput(props, ref) {
      // 자식 컴포넌트의 ref를 새롭게 생성한 뒤,
      // useImperativeHandle의 두 번째 인자로 들어가는 함수 바디에서 사용한다.
      const inputRef = useRef();
      useImperativeHandle(ref, () => ({
        focus: () => {
          inputRef.current.focus();
        }
      }));
      return <input ref={inputRef} ... />;
    }
    FancyInput = forwardRef(FancyInput);

    부모 컴포넌트는 자식의 DOM에 직접 접근하는 것이 아니라, useImperativeHandle로 전달된 메서드에만 접근이 가능해진다. 이로써 더욱 컴포넌트 간의 독립성을 보장할 수 있게 된다.

    ‘imperative’는 ‘반드시 해야 하는’, ‘긴요한’이라는 뜻이라고 한다. 뭐가 그렇게 긴요했을까. 이름만 봐서는 예측하기가 어렵다. 토스의 김 모 개발자에 의하면, ‘명령적이다’라는 뜻도 있다고 한다. 😑

    Ref https://ko.reactjs.org/docs/hooks-reference.html#useimperativehandle https://kelly-kh-woo.medium.com/react-hook-useimperativehandle-89fee716d80

    enum vs const enum vs as const

    TypeScript의 enum은 서로 연관된 상수들을 하나로 관리하기 위해 사용한다.

    Copy
    enum COLOR {
      RED,
      BLUE,
      GREEN,
    }
    
    let red = COLOR.RED;

    위 코드를 babel로 컴파일하면 결과는 아래와 같다.

    Copy
    var COLOR;
    
    (function (COLOR) {
      COLOR[(COLOR["RED"] = 0)] = "RED";
      COLOR[(COLOR["BLUE"] = 1)] = "BLUE";
      COLOR[(COLOR["GREEN"] = 2)] = "GREEN";
    })(COLOR || (COLOR = {}));
    
    var red = COLOR.RED;

    enum은 즉시 실행 함수 ((function())()의 형태)로 컴파일된다. 따라서 트리셰이킹(tree-shaking)이 불가능하다.

    enumconst를 붙인 const enum은 그냥 enum과 조금 다르게 동작한다.

    Copy
    const enum COLOR {
      RED,
      BLUE,
      GREEN,
    }
    
    let red = COLOR.RED;

    const enum을 babel로 컴파일하면 결과는 아래와 같다.

    Copy
    let red = 0;

    const enum은 일반적인 enum과 달리 컴파일 과정에서 완전히 제거되고, 값에 해당하는 상수만 남는다. 트리셰이킹이 되기 때문에 용량 측면에서 그냥 enum보다 낫다고 할 수 있지만, TypeScript 사용 시 패키지 등에서 const enum을 사용한다면 값이 상수로 치환되어버리기 때문에 타이핑이 불가능해진다는 단점이 있다.

    이때는 일반 객체에 as const를 사용하는 방식으로 enum을 대체할 수 있다.

    Copy
    const COLOR = {
      RED: 0,
      BLUE: 1,
      GREEN: 2,
    } as const;

    as const는 타입 단언(type assertion)의 한 종류로써 리터럴 타입의 추론 범위를 줄이고 값의 재할당을 막아준다. enum을 흉내낼 수 있으며, 컴파일 후에 용량도 enum보다 작은 편이다.

    Ref https://velog.io/@logqwerty/Enum-vs-as-const https://engineering.linecorp.com/ko/blog/typescript-enum-tree-shaking/ https://darrengwon.tistory.com/1310

    docker container와 VM

    docker는 linux 기반의 가상환경으로, VM(virtual machine)과는 뚜렷한 차이점이 있다.

    VM은 일종의 x86 하드웨어를 가상화한 형태다. VM 위에 다양한 종류의 OS를 설치할 수 있다.

    docker container는 하드웨어를 가상화하지 않고, Host OS에서 Guest OS를 isolation해주는 형태다. 다양한 종류의 OS에서 사용 가능한 VM과 달리, docker container는 linux 기반 OS에서만 수행할 수 있다.

    이는 docker container 자체에는 kernel 등의 OS 이미지가 들어가 있지 않기 때문이다. kernel은 host OS의 kernel을 그대로 사용하기 때문에 container에서 명령어를 수행하면 실제로는 host OS에서 수행된다. host OS와 container OS에의 diff만 container에 같이 패키징하는 개념이다.

    Ref https://bcho.tistory.com/805

    datalist 태그

    datalist 태그는 다른 컨트롤에서 고를 수 있는 가능한, 혹은 추천하는 선택지를 나타내는 <option> 요소들을 담는다.

    select 태그와 유사한 기능을 제공하지만, option으로 지정된 값 외에도 직접 타이핑하여 값을 입력할 수 있다는 점에서 특징적이다. 그래서 주로 input 태그와 함께 많이 쓰인다.

    Copy
    <label for="ice-cream-choice">Choose a flavor:</label>
    <input list="ice-cream-flavors" id="ice-cream-choice" name="ice-cream-choice" />
    
    <datalist id="ice-cream-flavors">
      <option value="Chocolate">
      <option value="Coconut">
      <option value="Mint">
      <option value="Strawberry">
      <option value="Vanilla">
    </datalist>

    타이핑 중에 자동완성 기능을 통해 option list에 존재하는 매칭되는 결과를 보여주기 때문에 더욱 멋지다!

    Ref https://developer.mozilla.org/ko/docs/Web/HTML/Element/datalist

    .toPrecision(number)

    .toPrecision(number)은 JavaScript의 내장 메서드로, 앞에서부터 센 number의 자릿수 기준으로 반올림을 한다.

    Copy
    const num = 185;
    num.toPrecision(1); // '2e+2'
    num.toPrecision(2); // '1.9e+2'

    반환값의 타입이 number가 아닌 string임에 주의하자!

    그리고 소수점을 위한 .이 들어갈 수 있기 때문에, 넘버 리터럴의 메소드 호출엔 .을 두 개 사용해야 한다.

    Copy
    185.toPrecision(1) =2e+2; // 🚨 SyntaxError: Identifier directly after number.
    185..toPrecision(1) =2e+2

    git switch

    Git 2.23 버전에서 checkout 명령어를 대신하는 switch, restore가 새로 나왔다. (꽤 됐다..)

    변경한 이유는 checkout 명령어가 가진 기능이 너무 많기 때문에 switch, restore로 분리했다.

    • checkout: Switch branches or restore working tree files
    • switch: Switch branches
    • restore: Restore working tree files

    mouseover vs mouseenter

    mouseover는 직접 이벤트를 걸지않은 자식요소에 마우스 포인터가 와도 발생하지만 mouseenter는 오로지 자기 자신에게 마우스 포인터가 와야만 발생한다.

    mouseovermouseout과 짝꿍, mouseentermouseleave와 짝꿍이다.

    setState에 함수를 넣으면

    리액트의 함수 컴포넌트에서 state를 다루는 법은 조금 특별하다.

    constructor()에서 state의 초기값을 지정해주는 클래스 컴포넌트는, 컴포넌트 리렌더링 시 기존 컴포넌트의 인스턴스를 재활용하기 때문에 state가 무분별하게 재계산되지 않는다. 반면 함수 hook을 사용하는 함수 컴포넌트에서는 컴포넌트가 리렌더링될 때마다 함수를 새롭게 렌더링하기 때문에 불필요한 state 값이 재계산된다.

    특히 state의 초기값이 복잡한 계산의 결과이거나, props를 바탕으로 한 값이라면 더욱 곤란해진다. 아래는 state의 초기값으로 복잡한 계산(expensiveCalculation)과 props를 넣은 극단적인 예시다.

    Copy
    function NaiveHooksComponent(props) {
      const [result, setResult] = useState(expensiveCalculation(props.arg));
      // ...
    }

    이럴 때는 useState()의 초기값에 함수를 넣어주는 방법을 사용해볼 수 있다!

    Copy
    function FunctionHooksComponent(props) {
      const [result] = useState(() => expensiveCalculation(props.arg));
      // ...
    }

    useState()의 초기값으로 들어간 함수는 컴포넌트의 오직 첫 번째 렌더링에만 계산될 것이다.

    Ref https://medium.com/@_m1010j_/how-to-avoid-this-react-hooks-performance-pitfall-28770ad9abe0


    이것저것

    • 정규식은 좌에서 우로 해석되기 때문에 부분집합이 선택 중 앞에 오게 되면 뒤에 있는 내용은 선택되지 않는다. 따라서, 가장 큰 집합부터 좌측에 두는게 좋다.
    • 아이콘 트리셰이킹 - 아이콘을 웹폰트로 받아오면 사용하지 않는 것도 가져오는 단점이 있다.
    • JSX 조건부 렌더링에서는 표현식을 사용하기보다는 삼항연산자로 일관되게 사용하는 것이 좋다(는 의견) (Ref)
    • 브라우저에서 사용자가 select 태그를 클릭했을 때 option 리스트들이 보여지는데, 이를 event로 직접 컨트롤 할 수 있는 방법은 없다. 즉 focus, click 등과 같이 이벤트를 직접 적용해서 select 태그의 리스트를 열 수 있는 방법은 없다.
    • 비동기 로딩이나, 동적 페이지에서 anchor의 사용은 부정확한 동작을 일으킨다.
    • Lerna는 모노 레포를 위한 CLI 도구이다. 모노 레포란 분리된 패키지를 하나의 리파지토리로 합쳐 관리해준다. (Ref)
    • Java와 TypeScript는 다중상속을 지원하지 않는다. 자신이 가지고 있지 않은 메소드를 부모로부터 가져올 때, 두 부모가 모두 같은 메소드를 가지고 있다면 어느 것을 선택해야 할지 꼬여버리는 문제가 발생하기 때문이다. (Ref)
    • Sentry transaction URL이 파라미터가 포함되어 있어 그루핑하기 어렵다면, transaction 그루핑을 통해 파라미터를 하나의 이름으로 통일해서 볼 수 있다. (Ref)

    기타

    명확한 리액트 파일/디렉터리 구조

    미디엄 유료회원이 아니라 못 읽는다 ㅡㅡ

    Ref https://junghan92.medium.com/번역-명확한-리액트-파일-디렉터리-구조-a5f03a174b9e

    CSS peeper

    요소간 간격을 디테일하게 보여주는 크롬 익스텐션이다. 대박 짱 좋다. 스물 여섯 먹고 할 수 있는 최대의 감탄 표현이 ‘대박 짱’이라니 정말 한심스럽다. 아무튼 이걸 보고 디자이너 분들의 QA가 조금이나마 수월해지길 바란다!

    Ref https://chrome.google.com/webstore/detail/css-peeper/mbnbehikldjhnfehhnaidhjhoofhpehk

    Partytown

    이름부터 벌써 신난다. 내용이랑 무슨 상관이 있는지는 모르겠다.

    JavaScript는 싱글 스레드라 서드파티 라이브러리의 로드로 인해 성능이 저하될 수밖에 없는 문제가 있었는데. 이를 Web Worker를 통해 불러올 수 있게 하여 웹 앱의 로딩 성능을 올려줄 수 있는 라이브러리라고 한다.

    Ref https://github.com/BuilderIO/partytown

    배포 전에 보면 좋을 프론트엔드 체크리스트

    별게 다 있다. 유용하게 사용해볼 만한 것들은 아래와 같다.

    • 조건부 주석: Internet Explorer 를 위한 조건부 주석을 사용한다.
    • Critical CSS - 페이지가 로딩되는 즉시(펼쳐지는 그 순간) 컨텐츠에 영향을 끼치는 CSS를 Critical CSS라고 한다. 이는 당신의 실질적인 어플리케이션의 CSS 가 로딩되기 이전에 <style></style> 태그 사이에 최소화 된 상태로 한 줄로 추가되어 임베딩 된다.
    • W3C 규격 - 페이지 내의 모든 HTML 이 표준에 맞게 정상적으로 작성되었는지 W3C 의 validator를 이용하여 테스트 한다.
    • 자바스크립트 보안 - 자바스크립트를 활용하여 보안에 안전한 어플리케이션 개발 가이드라인
    • 서드 파티 컴포넌트 - 공유하기 버튼처럼 외부 자바스크립트 파일에 의존하는 서드파티 iframe이나 컴포넌트의 경우, 가급적 정적인 컴포넌트로 교체하여서 외부 API 호출을 제한하고 사용자들의 활동들을 외부로 유출되지 않도록 한다. (간단한 공유하기 버튼 생성하기)
    • Progressive enhancement - 메인 네비게이션이나 검색과 같은 대다수의 기능들이 자바스크립트가 작동하지 않고도 동작해야 한다.

    포스팅에 참고 링크도 엄청 많다! 시간 내어 차근차근 읽어보기로.

    Ref https://github.com/kesuskim/Front-End-Checklist

    && 대신 삼항 연산자

    Dodds 형님은 예기치 못한 falsy값 (예: 0)이 렌더링되는 걸 방지하고자 일관되게 삼항 연산자를 사용하는 방법을 추천하고 있다. 하지만 나는 그냥 falsy값을 명확하게 boolean으로 치환한 후 (!!) && 연산자를 사용하고 싶다.

    Ref https://kentcdodds.com/blog/use-ternaries-rather-than-and-and-in-jsx

    React18이 온다

    그러하다. 드디어 올 것이 온다!

    Ref https://twitter.com/reactjs/status/1506720582200705033?cxt=HHwWkoC-3d6Y-egpAAAA

    노션 API 정식 출시

    우선 똥💩 느린 노션 code snippet부터 개선해줬으면 좋겠다~ 불편한 건 불편한 대로 그냥 사는 나조차도 노션을 대체할 도구가 나온다면 그걸 쓰리라 마음 먹었는데, 뭐가 더 화려해지고 있다. 졸업한 주제에 학교에서 주는 노션 무료 계정을 잘 써먹고 있는데, 돈 내라 하는 거 아닌지 몰라~

    아무튼, Jira와 Slack 쓰레드가 노션과 연결된다는 건 정말 신기하다. 이렇게 얽히고설켜 하나가 망하면 우르르 망해버리는.. 어떤 CASCADING..의 효과가 나타나지 않을까. 하여간 나와 라포를 잘못 형성한 모든 것은 내게 부정적인 인상을 남긴다. 하지만 나는 그래도 노션을 좋아하는 편이다. (?)

    01

    오~ 대박짱신기~

    Ref https://www.notion.so/ko-kr/integrations?utm_campaign=March+release+email+Personal&utm_campaigntype=newsletter&utm_content=March+release+email+Personal&utm_medium=email&utm_source=customer.io

    Storybook for Vite

    스토리북도 정말 똥느렸는데~ 맥북에서는 램이 8GB만 되어도 때려쳐야 한다. 아니 M1 맥은 다르려나? 아무튼 스토리북은 딱 보기에도 느릴 수밖에 없어 보였다.

    이번에 내놓은 새로운 builder를 도입하면 HMR(Hot Module Replacement)이 엄청나진다! 어머 이건 한번 해봐야 돼

    Ref https://storybook.js.org/blog/storybook-for-vite/


    마무리

    월요일에는 새벽배포를 해봤다. 정말 얼마만에 새벽 5시 전에 일어난 건지… 그리고 다시 못잘 줄 알았는데, 비몽사몽하다가 조금 평화로워졌을 때 잠깐 눕는다는게 그대로 잠들었다. 꿀잠잤다. 쪽팔리다 🤷‍♀️

    한 달에 한 권 책 읽기(개발서적 X) 실천 중이다. 이번 달 책, <불편한 편의점>도 완독! 가볍게 읽을 수 있는 내용이었다. 백엔드 크루였던 조이와 항상 존경하는 크루 하루가 추천해준 책도 한 권씩 샀다. 우리회사 갓복지

    미장은 금리 인상에 대한 불확실성이 줄어들어서, 국내장은 새롭게 출범할 정부가 플랫폼 사업에 대한 규제를 풀어줄 예정이라 그런지 내 주식창도 웬일로 쭉쭉 오르고 있다. 정말 처음 보는 현상이라 오히려 더 불안하다. 역시 가진 자가 더 무섭다. 사실 아직 가진 돈도 아닌데. 까불지 말고 적당한 때에 팔아야겠다.

    우테코 코치님을 만나러 판교까지 갔다왔다. 운전연습이 하고 싶어서 판교까지 간다 그랬다. 처음으로 쏘카를 빌려서 무사히 잘 다녀왔고, 차를 사고 싶어졌다… 🤦‍♀️ 아니 아무튼, 2개월 차 (ㅋㅋ) 개발자로서 여기서 내가 할 수 있는 일들을 적극적으로 찾아 해 나가야겠다는 생각을 했다. 평화로운 울타리 안에서 조금씩 nagaboza


    Relative Posts:

    4월 첫주차 기록

    April 1, 2022

    3월 3주차 기록

    March 19, 2022

    zigsong

    지그의 개발 블로그

    RotateLinkImg-iconRotateLinkImg-iconRotateLinkImg-icon