ziglog

    Search by

    11월 3주차 기록

    November 19, 2022 • ☕️☕️ 9 min read

    Everything, Everywhere, All at once


    배워가기

    자바스크립트 나누기 부동소수점 이슈

    자바스크립트에서 소수를 12.34 -> 0.1234 형태로 변환하고 싶다면 소수부에 있는 값을 정수부로 올린 후에 나누기 하면 된다.

    그냥 나누기만 하면…

    Copy
    77.77 / 10000 -> 0.007776999999999999

    부동소수점 이슈가 발생하기 때문이다. 😩

    따라서 이렇게 해준다.

    Copy
    77.77 * 100 / 10000 -> 0.7777

    자바스크립트의 부동소수점 이슈 해결을 위해 decimal.js, bignumber.js, big.js 등의 라이브러리도 탄생했다.

    passive event

    브라우저는 기본적으로 이벤트의 preventDefault가 실행될지 여부를 항상 확인해야 하기 때문에 성능 상 약간 손해다. preventDefault를 호출할 필요가 없다면, addEventListener의 세 번째 인자로 { passive: true } 를 넣으면 preventDefault를 확인하지 않기 때문에 성능 상 약간의 개선이 이루어진다.

    스크롤 이벤트나 터치 이벤트에 유용하게 사용할 수 있다.

    .npmrc

    .npmrc는 npm 환경설정을 할 수 있는 파일이다. 프로젝트 < 유저 < 전역 < 빌트인 범위가 존재한다.

    사내 패키지를 다운받을 때는 .npmrc에 registry를 등록해줘야한다. 다음 명령어로 등록할 수도 있다.

    Copy
    npm config set <registry> --location <global|user|project>

    npm config에 key-value 값을 저장하거나 삭제하는 명령어는 다음과 같다.

    Copy
    npm config set <key>=<value> [<key>=<value> ...]
    npm config get [<key> [<key> ...]]
    npm config delete <key> [<key> ...]
    npm config list [--json] // 모든 config 항목을 볼 수 있다.
    npm config edit

    .npmrc 에 engine-strict=true 를 추가할 수 있다. 이 필드가 true라면 사용하는 node, npm이 package.json에 명시한 버전이 아닐 때 npm install 등의 명령어를 실행하지 못하게 한다.

    react-helmet

    document의 head를 변경할 수 있게 해주는 react component다. Helmet을 쓴 자식이 선언한 head가 부모 컴포넌트의 head를 덮어버린다.

    헤더를 변경할 수 있기 때문에 title, og값 등을 적어넣어 SEO에 도움이 된다.

    어차피 빌드파일은 하나이므로, react-helmet을 사용하는 것만으로 크롤러에게 정보를 제공할 수는 없다. 이때는 react-snap 같이 pre-rendering을 해주는 라이브러리를 사용하거나 SSR을 구축해야 한다.

    react-router useLocation()

    react-router v6를 사용할 때 페이지가 변경될 때마다 특정 동작을 실행하고 싶다면 useLocation() 을 사용하면 된다.

    Copy
    import * as React from 'react';
    import { useLocation } from 'react-router-dom';
    
    function App() {
      let location = useLocation();
    
      React.useEffect(() => {
        // Google Analytics
        ga('send', 'pageview');
      }, [location]);
    
      return (
        // ...
      );
    }

    number input의 step 이동

    아래와 같이 input 태그를 사용할 때 5.34를 입력하고 up 버튼을 누르면 6이 되고, down 버튼을 누르면 5가 된다.

    Copy
    <input type="number" />

    5.34가 input에 들어간 상태에서 up을 누르면 6.34, down을 누르면 6.34가 되길 원한다면 아래와 step="any"를 넣고 사용하면 된다.

    Copy
    <input type="number" step="any" />

    Ref https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/step#:~:text=or%20the%20special%20value%20any

    #region으로 폴딩하기

    Copy
    // anything.tsx
    
    // #region 접을 수 있어요
       ...
    // #endregion

    // #region을 사용하면 vscode에서 해당 구간을 폴드할 수 있다! 😲

    CRA의 tsconfig 참조

    CRA 웹팩 설정에는 tsconfig를 참조하는 코드가 있다. tsconfig를 기반으로 baseurl을 결정한다.

    Copy
    // config/modules.js
    config = ts.readConfigFile(paths.appTsConfig, ts.sys.readFile).config;
    // Otherwise we'll check if there is jsconfig.json
    // for non TS projects.

    baseUrl 항목이 없으면 '' 가 default다.

    pointer-events

    position: absolute 밑에 있는 요소에 hover effect를 주고 싶다면, position: absolute인 요소들에 pointer-events: none 을 주면 된다

    그런데 pointer-events: none을 먹인 요소의 일부 자식 요소들에 다시 pointer-events를 주고 싶다면?!

    pointer-events: initial을 주면 살아난다 😎

    Ref https://stackoverflow.com/questions/65970609/trying-to-use-hover-on-a-element-below-an-absolute-positioned-element

    타입스크립트 Extract

    타입스크립트의 유틸 타입인 Extract<Type, Union>은 타입에서 뽑을 수 있는 애들만 union으로 뽑아준다.

    👩‍🏫 Pick과의 차이?

    • Pick 은 객체 형태의 타입에서 key(프로퍼티)로 뽑는다.

    Ref https://www.typescriptlang.org/docs/handbook/utility-types.html#extracttype-union

    class-transformer

    plain JS object (리터럴 객체)를 class 인스턴스로 바꾸고 싶을 때 사용한다.

    ex) API 응답값을 json으로 받아 JSON.parse() 한 후

    그냥 모든 프로퍼티들을 다 복사해도 되지만, 계층이 복잡할 경우에는 작업이 비싸다.

    → 이때 class-transformer 를 사용한다!

    cf) NestJS에서는 class-transformer를 글로벌 설정으로 Controller에서 받는 Request Dto로 변환할 수 있도록 지원하고 있다.

    Ref https://github.com/typestack/class-transformer#what-is-class-transformer


    이것저것

    • gap의 단축속성: {row-gap}(상하간격) {column-gap}(좌우간격)

    기타

    craco v7.0.0 릴리즈

    현재 Create React App 에 포함된 react-script는 v5 버전인데, craco에서 드디어 지원할 수 있게 되었다.

    Ref https://github.com/dilanx/craco

    WASM을 위한 자바스크립트

    WebAssembly에서 돌릴 수 있는 Javy라는 도구가 등장했다.

    자바스크립트 코드를 작성하고,

    Copy
    function foo(input) {
      return { foo: input.n + 1, newBar: input.bar + "!" };
    }
    
    Shopify = {
      main: foo,
    };

    아래와 같이 WebAssembly 바이너리를 생성한다.

    Copy
    javy index.js -o destination/index.wasm

    그리고 WebAssembly 엔진을 이용하여 실행한다.

    Copy
    $ echo '{ "n": 2, "bar": "baz" }' | wasmtime index.wasm
    {"foo":3,"new_bar":"baz!"}%

    아아… 이제 정말 피할 수 없게 된 것인가.

    전 깃허브 CTO의 MSA 회고

    MSA 전환 시 우려사항

    • (특이하게 IT출신 CEO가 이끌지 않는 한) 인프라는 항상 우선순위에서 밀려남(get the short end of priority stick)
    • 서비스가 너무 많으면 일반적으로 소유권 문제 및 경계 문제가 생김
    • 수많은 마이크로서비스를 처리하기 위해 더 많은 도구를 도입함
    • 가장 중요한 것은 라이브러리나 SDK가 되었어야할 각 마이크로서비스들이 프로덕션에 위험을 초래함

    그래서 다음과 같이 추천한다고 한다.

    • 가능하면 최대한 오래 Monolith를 유지
    • 서비스는 인프라에 필요한 것에서 시작하고, 앱 개발쪽에서 시작하지 말 것
    • Mono를 쪼개야 한다면, 작은 서비스들이 아닌 큰 앱들로 분해할 것
    • 각 새로운 앱은 회사내의 가상 벽이라고 생각할 것
    • 가능하다면 마이크로서비스 대신 라이브러리를 선호

    Ref https://news.hada.io/topic?id=7839

    What’s New in TypeScript 4.9?

    💡 The satisfies Operator

    satisfies 키워드를 이용하면 객체의 key-value 타입을 잃지 않을 수 있다.

    Copy
    const foo = {
        a: 255,
        b: 255,
        c: 255,
        // ❌ We get the error Type 'string' is not assignable to type 'number'
        d: 'bar'
    } satisfies Record<string, number>;
    
    // ✅ We are not losing any type inferance information
    // typeof foo is
    // const foo: {
    //    a: number;
    //    b: number;
    //    c: number;
    //    d: string;
    // }

    💡 Support for auto-accessor fields 자바스크립트 데코레이터가 stage 3에 올라옴에 따라, 프로퍼티 자동 접근자가 추가될 예정이다.

    타입스크립트에서도 이를 지원한다.

    Copy
    class Foo {
      accessor a: string = 'a';
    }
    
    const instance = new Foo();
    
    // ✅ it works and prints 'a'
    console.log(instance.a);

    이제 a 프로퍼티를 별도의 boilerplate 없이 사용할 수 있다.

    💡 Improve checking of in operator

    typeof 연산자와 함께 in 연산자를 활용하여 타입을 좁힐 수 있다.

    typeof을 사용하면, 객체의 프로퍼티 값의 타입까지 체크해줘야 했다.

    Copy
    function log(vehicle: {}) {
      // ✅ Works, item.wheels is now of type number
      if ("wheels" in vehicle && typeof vehicle.wheels === "number") {
        console.log(`the entity has ${vehicle.wheels} wheels`);
      }
    }
    
    log({ wheels: 4, topSpeed: 20 });

    새로운 in 연산자는 typeof을 대체할 수 있다!

    Copy
    function log(vehicle: {}) {
      // ✅ Works, item.wheels is now of type unknown
      if ("wheels" in vehicle) {
        console.log(`the entity has ${vehicle.wheels} wheels`);
      }
    }
    
    log({ wheels: 4, topSpeed: 20 });

    또, key in obj는 이제 string | number | symbol로 추론된다!

    💡 Disallow comparison against NaN

    IEEE 754에 따르면 NaNNaN은 같지 않다.

    Copy
    NaN === NaN; // false
    NaN !== NaN; // false

    타입스크립트 4.9부터는, NaN 값을 비교할 경우 컴파일러가 에러를 뱉는다.

    Copy
    function logValue(value: Number | NaN) {
      // ❌ Error: This condition will always return 'true'
      // Did you mean '!Number.isNaN(value)'
      if (value !== NaN) {
        console.log("It is NaN");
      }
      console.log(value);
    }

    Ref https://betterprogramming.pub/whats-new-in-typescript-4-9-6bce2387aa31


    마무리

    거의 뭐 인생에서 가장 큰 이벤트 중 하나라고 할 수 있는 사건이 지났다… 아니 진행중… 그치만 잘 지내는중 😎👍


    Relative Posts:

    11월 4주차 기록

    November 26, 2022

    11월 2주차 기록

    November 13, 2022

    zigsong

    지그의 개발 블로그

    RotateLinkImg-iconRotateLinkImg-iconRotateLinkImg-icon