ziglog

    Search by

    9월 5주차 기록

    October 1, 2022 • ☕️☕️ 11 min read

    호주 가보자고


    배워가기

    Vue.js 이모저모

    • Vercel로 배포를 진행할 때 Project Name은 도메인이 된다.(변경 가능하다.)
    • Vue는 기본적으로 다음과 같은 3가지 모드가 있다. 새로운 모드를 정의해서 사용할 수도 있다.
      • development: 프로토타이핑 및 개발 용도. npm run serve 명령어로 실행할 때의 모드
      • production: 상용화 및 배포 용도. npm run build 명령어로 실행할 때의 모드
      • test: 테스트 용도. npm run test:unit 명령어로 실행할 때의 모드
    • 현재 Vue는 3.x 대의 메이저 버전을 가지고 있다.
      • Vue.js를 검색해서 나오는 페이지에 들어가면 3 버전을 기준으로 문서가 나와있다.
      • 본인이 2.x 버전의 Vue를 사용하고 있다면 아래 문서를 보자.
      • https://v2.vuejs.org/

    인증(Authentication) vs 인가(Authorization)

    인증과 인가는 엄연히 서로 다른 프로세스이므로 각 용어에 따른 개념을 각각 이해하는 것이 중요하다.

    • 인증
      • 자격 증명 확인 (ID/PW, Pin, 생체인식, OTP 등)
      • 쉽게말해, “너 누구냐?”
    • 인가
      • 권한 허가/거부
      • 인증 완료된 유저가 무엇을 할 수 있는지 없는지 허가/거부를 내림

    Oauth 2.1 의 인증/인가 흐름은 다음과 같다.

    1. 클라이언트가 리소스에 인가 요청을 보낸다.
    2. 리소스는 클라이언트에 인가를 허용한다.
    3. 인가 받은 클라이언트가 서버에 인가를 포함한 요청을 보낸다.
    4. 서버는 클라이언트에 Access Token을 보낸다.
    5. 클라이언트는 4에서 받은 Access Token으로 다시 리소스에 요청을 보낸다.
    6. 리소스는 클라이언트에 보안 리소스를 보낸다.

    Ref https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-05#section-1.2

    stale closure

    클로저를 사용할 때 stale closure 문제를 주의해야 한다.

    다음 코드를 살펴보자. WatchCount 컴포넌트의 useEffect hook에서는 매 2초마다 count 값을 콘솔에 로깅한다. 그리고 button을 통해 count의 값을 증가시킬 수 있다.

    Copy
    function WatchCount() {
      const [count, setCount] = useState(0);
    
      useEffect(function () {
        setInterval(function log() {
          console.log(`Count is: ${count}`);
        }, 2000);
      }, []);
    
      return (
        <div>
          {count}
          <button onClick={() => setCount(count + 1)}>Increase</button>
        </div>
      );
    }

    실행해보면, button으로 count의 값을 여러 번 증가시켜도, useEffect hook 내부에서 출력되는 count의 값을 계속 0이다.

    컴포넌트가 마운트된 후, useEffectsetInterval 함수를 호출하고, setIntervalconsole.log()를 2초마다 출력하기로 스케쥴링했는데, 이때 클로저가 된 console.log() 함수가 count 변수의 초기값 0을 계속 물고 있기 때문이다. 즉 console.log9)가 stale closure가 된 것이다.

    해결 방안은 useEffect에게 console.log()count의 값에 의존하고 있음을 알려주는 것이다.

    Copy
    function WatchCount() {
      const [count, setCount] = useState(0);
    
      useEffect(
        function () {
          const id = setInterval(function log() {
            console.log(`Count is: ${count}`);
          }, 2000);
          return function () {
            clearInterval(id);
          };
        },
        [count]
      );
    
      // ...
    }

    useEffect의 dependency에 count를 넣어, count가 변할 때마다 클로저를 업데이트하게끔 한다.

    Ref https://dmitripavlutin.com/react-hooks-stale-closures/#3-stale-closures-of-hooks

    env-cmd 활용하기

    env-cmd 를 사용할 때 공통으로 사용하는 환경변수를 두고 특정 상황마다 분기를 주고 싶다면 아래와 같이 사용하면 된다.

    Copy
    // .env-cmdrc
    {
      "dev": {
        "ENV1": "Thanks",
        "ENV2": "For All"
      },
      "dev02": {
        "ENV1": "The Fish"
      }
    }
    Copy
    // package.json
    
    "scripts": {
       "build:dev02": "env-cmd -e dev,dev02 react-scripts build",
    }

    이렇게 사용하게 되면 dev에 있는 환경변수를 사용하면서 dev와 dev02에 모두 존재하는 환경변수의 경우 dev02의 값으로 사용한다.(dev의 값을 덮어씌운다.)

    이 때 주의할 점은 dev, dev02 처럼 띄어쓰면 안 되고 dev,dev02 처럼 붙여서 사용해야 한다.

    npm ci의 실행순서

    “prepare”에 스크립트를 추가하면 npm ci만 실행해도 install 후에 자동으로 실행된다. npm ci의 실행 순서가 다음과 같기 때문이다.

    • preinstall
    • install
    • postinstall
    • prepublish
    • preprepare
    • prepare
    • postprepare

    Ref

    CSS 이모저모

    • text-underline-offset: 2px;
      • 텍스트 언더라인 위치를 픽셀단위로 조정할 수 있다. (기본 1px)
    • position: absolute
      • top, bottom 둘다 정의하면 top이 우선한다.
      • left, right 둘다 정의하면 (ltr 환경이면) left가 우선한다.

    타입스크립트 as

    타입스크립트에서 as는 그냥 타입 단언(type assertion)용으로만 쓰는 줄 알았다..!

    그런데 as를 활용해서 key remapping도 할 수 있다고 한다.

    Copy
    type MappedTypeWithNewProperties<Type> = {
      [Properties in keyof Type as NewKeyType]: Type[Properties];
    };

    template literal type 등의 기능을 활용해서, 새로운 프로퍼티 이름을 정의할 수도 있다.

    Copy
    type Getters<Type> = {
      [Property in keyof Type as `get${Capitalize<
        string & Property
      >}`]: () => Type[Property];
    };
    
    interface Person {
      name: string;
      age: number;
      location: string;
    }
    
    type LazyPerson = Getters<Person>;
    // type LazyPerson = {
    //     getName: () => string;
    //     getAge: () => number;
    //     getLocation: () => string;
    // }

    이밖에 또 여러 가지로 활용할 수 있는 길들이 있으니 참고하자~!

    Ref https://www.typescriptlang.org/docs/handbook/2/mapped-types.html#key-remapping-via-as

    히트맵으로 사용자 행동 분석하기

    웹사이트의 방문자를 분석하는 웹로그 분석에 많이 사용하는 분석 기법으로, 웹페이지에서 발생하는 마우스 클릭을 열분포 형태의 이미지로 변환하여 보여준다.

    근데 hitmap인지 heatmap인지 모르겠다… 🙄 사용자가 특정 요소를 선택했다면(클릭했다면) hit가 맞는 것 같기도, 어떤 곳을 ‘많이’ 클릭했는지를 알고 싶다면 ‘열’을 뜻하는 ‘heat’가 맞는 것 같기도 하다. 둘 다 사용하고 있는 것 같다.

    Ref


    이것저것


    기타

    LDAP(Lightweight-Directory-Access-Protocol)

    LDAP은 네트워크상에서 조직이나 개인, 파일, 디바이스등을 찾아볼 수 있도록 하는 소프트웨어 프로토콜이다.

    예전부터 이름을 통해 쉽게 찾아낼 수 있는 시스템을 구축하는데 많은 고민과 시간을 쏟았다. (e.g. DNS) 이러한 것들을 전자 디렉토리 서비스라고 부른다.

    그러한 표준 (X.500)을 만들고, 이 표준을 기반으로 클라이언트가 디렉토리 시스템과 상호작용하는 방식인 DAP(Directory Access Protocol)가 탄생했다.

    DAP는 OSI Model을 기반으로 만들었기 때문에, 흔히 쓰이던 TCP/IP Model에서도 동작할 수 있도록 만들어야 했다. 그래서 나온게 LDAP(Lightweight Directory Access Protocol)다.

    DAP는 OSI의 모든 계층을 사용하기 때문에 무겁고 네트워크 트래픽을 많이 소요했다. 그래서 계층이 적은 TCP/IP Model을 사용하면서 이러한 부분을 함께 개선하고자 했고, TCP/UDP로 해결할 수 있도록 경량화 시켰다. 이것이 LDAP에 ‘Lightweight’가 붙는 이유이며, 지금도 많이 쓰이는 표준이다.

    LDAP는 이름 기반으로 찾아내는 특성상 RDN(Relative Distinguished Name) 값을 각 Entity 별로 갖고 있으며, 이어붙여 트리상에서 Entity를 쉽게 검색할 수 있다는 점이 특징이다.

    Ref https://vallista.kr/LDAP-(Lightweight-Directory-Access-Protocol)/

    TypeScript 4.9 Beta

    타입스크립트 4.9 베타 버전이 올라왔다.

    • satisfies 연산자 표현식이 어떤 타입에 매칭됨을 보장하면서도, 가장 구체적인 타입을 작성하고자 할 때 사용한다. 표현식의 타입을 바꾸지 않으면서, 표현식의 타입이 어떤 타입과 매칭되는지 검증해주는 것이다.

      Copy
      type Colors = "red" | "green" | "blue";
      type RGB = [red: number, green: number, blue: number];
      
      const palette = {
        red: [255, 0, 0],
        green: "#00ff00",
        bleu: [0, 0, 255]
        // ~~~~ The typo is now caught!
      } satisfies Record<Colors, string | RGB>;
      
      // Both of these methods are still accessible!
      const redComponent = palette.red.at(0);
      const greenNormalized = palette.green.toUpperCase();

      palette의 타입을 Record<Colors, string | RGB>로 제한하는 대신, satisfies 연산자를 사용함으로써 bleu의 typo도 찾아낼 수 있음은 물론, palette의 모든 프로퍼티가 string | number[] 타입임을 검증하여 redgreen에서 프로토타입 메서드 (at(), toUpperCase())를 사용할 수 있게 되었다.

    • in 연산자로 list되지 않은 프로퍼티 좁히기 런타임에 특정 프로퍼티가 존재하는지 여부를 알기 위해 타입스크립트는 (자바스크립트 문법인) in 연산자를 사용한다. 하지만 주어진 프로퍼티에 타이핑이 되어있지 않다면 도움이 되지 않는다.

      Copy
      interface Context {
        packageJSON: unknown;
      }
      
      function tryGetPackageName(context: Context) {
        const packageJSON = context.packageJSON;
        // Check to see if we have an object.
        if (packageJSON && typeof packageJSON === "object") {
          // Check to see if it has a string name property.
          if ("name" in packageJSON && typeof packageJSON.name === "string") {
            // ~~~~
            // error! Property 'name' does not exist on type 'object.
            return packageJSON.name;
            // ~~~~
            // error! Property 'name' does not exist on type 'object.
          }
        }
      
        return undefined;
      }

      packageJSON의 타입이 unknown에서 object로 좁혀졌지만, in 연산자는 타입을 엄격하게 확인하기 때문에 packageJSONname 프로퍼티가 있다는 것을 보장할 수 없다.

      타입스크립트 4.9에서부터 in 연산자는 프로퍼티를 전혀 기재하지 않아도 타입을 추론하는 방식으로 변경되었다. 이제 packageJSONobject & Record<"name", unknown> 타입이 되어, packageJSON.name을 직접적으로, 그리고 독립적으로 사용할 수 있게 된다.

    • NaN의 동일성 체크 자바스크립트에서 NaN은 특수한 숫자형 값으로, NaNNaN은 서로 동일하지 않다. 타입스크립트 신규 버전에서는 NaN과 직접적으로 비교 연산을 수행하는 것을 금지한다. (대신 Number.isNaN의 사용을 권장한다.)

      Copy
      function validate(someValue: number) {
        return someValue !== NaN;
        //     ~~~~~~~~~~~~~~~~~
        // error: This condition will always return 'true'.
        //        Did you mean '!Number.isNaN(someValue)'?
      }
    • File System Events에 기반한 File-Watching 이전 버전에서 타입스크립트는 개별 파일을 watching하는 데 polling 방식을 사용했다. polling은 정해진 시간마다 업데이트를 확인하는 것으로, CPU가 계속해서 방해받게 된다. 타입스크립트 4.9에서는 특정 파일의 업데이트 시 콜백을 실행하는 파일 시스템 이벤트를 활용한다.

    • 기타 오류 수정 및 Breaking Changes

      • lib.d.ts 업데이트
      • Promise.resolve의 더 나은 타이핑
      • JavaScript 변환 시 Elides Imports를 허용하지 않음
      • exportstypesVersions보다 우선시됨
      • substituteSubstitutionTypesconstraint로 대체

    Ref https://devblogs.microsoft.com/typescript/announcing-typescript-4-9-beta/

    구글에서 사용하는 코드 스타일 사본

    React Global Online Summit

    Ref https://events.geekle.us/react3/

    VSCode pet

    펫의 종류가 더 다채로워진 것 같다! 클립이 있다니 ㅋㅋㅋ

    Ref https://github.com/tonybaloney/vscode-pets

    마무리

    여러 가지 비밀(?)스러운 소식들이 있었고… 인생 첫 사회인으로써 청첩장을 받아봤다! 좀 늦은 것 같기도..? 내가 다 기대되고 설렌당. 결혼식을 아직 많이 안 가봐서 그런지, 결혼식 넘 재밌당. 주변에 결혼하시는 분들이 점점 많아지는 것 같다.

    내년 호주 같이 갈 회사 친구들(ㅋㅋ)을 만났다. 새로 알게 된 언니는 정말 텐션이 장난 아니다. 무사히 갔다올 수 있겠지?

    이제 개천절까지 연휴다! 너무너무 좋당. 주4.5일제를 하고 있긴 하지만, 주4일제 소취… (국가적으로)


    Relative Posts:

    10월 1주차 기록

    October 8, 2022

    9월 4주차 기록

    September 24, 2022

    zigsong

    지그의 개발 블로그

    RotateLinkImg-iconRotateLinkImg-iconRotateLinkImg-icon