[오픈소스코드리뷰] cookie
들어가며
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]+$/;
// 생략 ...
- 사용자가 많은 오픈소스일수록 JSDoc 을 잘 작성합니다.
JSDoc 작성 시 @example 도 추가로 작성하면 타입 스크립트를 사용하지 않는 환경에서도 협업하기 좋습니다.
최근 프론트엔드 개발 입사 지원 시 과제를 주는 기업이 상당히 많아졌는데,
JSDoc 작성 가산점이 있을 정도로 개발 문서화에 대한 관심이 많아지고 있습니다. - 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;
}
- ;(Semicolon) 을 기준으로 split 하여 배열로 만든 후에
- =(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