ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [오픈소스코드리뷰] cookie
    카테고리 없음 2022. 8. 12. 09:28

    들어가며

    Cookie는 대부분의 웹사이트에서 사용되는 강력한 브라우저 API 이며
    key=value로 쌍을 이루고 ;(Semicolon)으로 구분합니다.
    브라우저마다 조금씩 다르지만 한 사이트 당 20개 정도로 한정되어 있고,
    key=value 를 인코딩 이후 4kb 가 넘지 않아야 하고,
    모든 문자가 허용되기 때문에 저장할 때는 반드시 encode 하여 저장하는 것이 좋습니다.
    작은 단위 정보로만 사용할 수 있기 때문에, 주로 사용자 정보, 통계 수치, 토큰 저장과 같은 기능 개발에 사용됩니다.

    현재 리뷰 버전은 0.4.1 입니다.

    리뷰

    ...
    .travis.yml
    eslintrc.yml
    ...

    특별한 설정은 없네요. Dayjs와 마찬가지로 Travis CI를 사용하고 있습니다.

    rules:
      eol-last: error
      indent: ["error", 2, { "SwitchCase": 1 }]
      no-trailing-spaces: error
    

    eslint 설정 역시 특별한 것은 없습니다..

    {
      "scripts": {
        "bench": "node benchmark/index.js",
        "lint": "eslint --plugin markdown --ext js,md .",
        "test": "mocha --reporter spec --bail --check-leaks --ui qunit test/",
        "test-ci": "nyc --reporter=text npm test",
        "test-cov": "nyc --reporter=html --reporter=text npm test",
        "version": "node scripts/version-history.js && git add HISTORY.md"
      }
    }

    Mocha 로 테스트를 하고 있으며, 퍼포먼스 테스트 도구인 benchmark 도 사용하는 것을 확인할 수 있네요.

    본격적으로 index.js 를 살펴볼까요?
    주석을 제외하면 약 100여줄 정도밖에 되지 않는데,
    정말 많은 사람들이 사용을 하고 있는 라이브러리입니다.

    // index.js
    // 생략 ...
    // 1)
    /**
     * RegExp to match field-content in RFC 7230 sec 3.2
     *
     * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
     * field-vchar   = VCHAR / obs-text
     * obs-text      = %x80-FF
     */
     
     // 2)
     var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;
     // 생략 ...
    1. 사용자가 많은 오픈소스일수록 JSDoc 을 잘 작성합니다.
      JSDoc 작성 시 @example 도 추가로 작성하면 타입 스크립트를 사용하지 않는 환경에서도 협업하기 좋습니다.

      최근 프론트엔드 개발 입사 지원 시 과제를 주는 기업이 상당히 많아졌는데,
      JSDoc 작성 가산점이 있을 정도로 개발 문서화에 대한 관심이 많아지고 있습니다.
    2. Unicode 로 작성된 내용은 \u0009(탭), \u0020(공백), 그 뒤에는 특정한 라틴/특수 문자에 대한 내용이 포함되어 있는지를 확인 하는 정규식입니다.

      https://www.fileformat.info/info/unicode/char/a.htm 사이트에서 Unicode의 대한 내용을 확인 할 수 있습니다.

    // index.js
    // 생략 ...
    function parse(str, options) {
      // 생략 ...
      // 1)
      var pairs = str.split(pairSplitRegExp);
    
      // 생략 ...
      for (var i = 0; i < pairs.length; i++) {
        // 2
        var pair = pairs[i];
        var eq_idx = pair.indexOf('=');
    
        // skip things that don't look like key=value
        if (eq_idx < 0) {
          continue;
        }
    
        var key = pair.substr(0, eq_idx).trim()
        var val = pair.substr(++eq_idx, pair.length).trim();
    
        // quoted values
        if ('"' == val[0]) {
          val = val.slice(1, -1);
        }
    
        // only assign once
        if (undefined == obj[key]) {
          obj[key] = tryDecode(val, dec);
        }
      }
    
      return obj;
    }
    1. ;(Semicolon) 을 기준으로 split 하여 배열로 만든 후에
    2. =(Equal)의 포함 여부로 { key: value } 와 같은 Object 만들기 위한 반복문인데,
      이 부분을 정규식으로 만들면 더 간결하게 할 수 있을 것 같네요..
    // e.g
    const params = arr.map(str => /^(\S+)=(\S+)$/g.exec(str)).reduce((a,b) => {
        const [,key, value] = b;
        return !!key && !!value ? {...a, [key]:value} : a;
    }, {});

    참고로 \S 는 공백을 제외한 문자에만 해당되는 표현식입니다..

    // index.js
    // ...생략
    switch (sameSite) {
      case true:
        str += '; SameSite=Strict';
        break;
      case 'lax':
        str += '; SameSite=Lax';
        break;
      case 'strict':
        str += '; SameSite=Strict';
        break;
      case 'none':
        str += '; SameSite=None';
        break;
      default:
      throw new TypeError('option sameSite is invalid');
    }


    이렇게 Case 별로 문자열을 만드는 경우 object 형식으로 개발을 하는 방법도 괜찮을 것 같습니다.

    // e.g
    let sameSite = 'none';
    let str = '';
    const mode = {
        "true": "Strict",
        "strict": "Strict",
        "lax": "Lax",
        "none": "None",
    }[String(sameSite).toLowerCase()] || null;
    
    str += !!mode ? `SameSite=${mode}` : '';
    console.log(str);

    쿠키의 사용이 어렵지 않아 코드가 길지 않은 것 같습니다.


    마치며

    en/de code 방법으로 encodeURIComponent, decodeURIComponent 이 외에
    base64 API인 atob, btoa 많이 사용 하니 참고 하시면 좋습니다.

    https://github.com/jshttp/cookie

    jshttp/cookie

    HTTP server cookie parsing and serialization. Contribute to jshttp/cookie development by creating an account on GitHub.

    github.com

    댓글

uznam8x