January 20, 2023 • ☕️☕️☕️ 13 min read
설 앞두고 설렌 맘
nodejs에서 개발을 하기위해선 lint, testing tool, package manager, transpiler 등이 필요하다. Deno는 개발 환경 설정에 필요한 작업들 중 일부분을 해결해준다.
본질적으로 패키지 매니저가 없으며, 외부 모듈은 url로 import해서 가지고온다.
로컬 캐시에 패키지를 저장한다. (remote HTTP imports)
lint도 서브 커맨드로 자체적으로 실행할 수 있다.
Node보다 다양한 빌트인 API를 지원한다. (ex. debounce를 자체적으로 지원)
런타임 version과 표준 라이브러리 version이 독립적이다.
import { copy } from "<[https://deno.land/std@0.172.0/fs/copy.ts](https://deno.land/std@0.172.0/fs/copy.ts)>";
원칙적으로는 ESM만 지원한다.
Node와의 호환성
import express from "npm:express@^4.18";
와 같은 방식 npm package를 가져올 수 있다.한글 유니코드 조합은, 다음 형식으로 구성되어 있다.
0xAC00(처음 한글 시작값) + (초성 인덱스 x 21 x 28 ) + (중성 인덱스 x 28) + 종성 인덱스
종성 인덱스가 0 이상일 경우는 받침이 있는 경우, 그렇지 않은 경우는 받침이 없는 경우다. 따라서 마지막 글자를 가져온 뒤 종성 인덱스를 가지고 있는지 여부를 판단해서 함수를 만들 수 있다.
예시로 작성해보자.
const 조사를붙여줘 = (name, firstValue, secondValue) => {
const lastChar = name.charCodeAt(name.length - 1);
if ((lastChar - 0xac00) % 28) {
return name + firstValue;
}
return name + secondValue;
};
josa라는 이름이 아주 직관적인 라이브러리도 참고해볼 만 하다.
npm은 파일시스템(node_modules
)을 통해서 의존성을 관리한다. 이때 찾고자 하는 모듈이 없다면 상위 폴더의 node_modules
를 참조하기 때문에 불필요한 I/O가 많아질 수 있다.
또한 node_modules
에 패키지가 잘 설치되었는지 확인하기 쉽지않다. 수 백개의 패키지가 서로 의존하고 있는데, 이를 모두 확인해보려면 node_modules
를 느린 I/O작업으로 살펴봐야 한다.
이를 개선하기 위해 Yarn berry에서는 pnp 모드를 지원한다.
해당 모드에서는 node_modules
를 아예 사용하지 않으며, .pnp.cjs
파일을 사용한다.
이 파일을 통해 라이브러리가 실제 어디에 존재하는지 경로가 값으로 써져 있어 어떤 패키지가 무엇을 의존하고 있는지 알 수 있으며,
결과적으로 node가 이미 경로를 알기 때문에 직접 node_modules
를 탐색할 필요가 없다. 그러므로 node_modules
파일 트리 형태를 만들지 않아도 된다.
또한 모든 패키지는 패키지 버젼별로 zip파일로 만들어져 .yarn/cache/
로 저장된다. 패키지 버전마다 하나의 zip파일을 가지고 있어서 중복 설치되지 않으며, zip파일로 저장해서 용량도 아낄 수 있다.
본래 node_modules
는 큰 용량 때문에 git 추적에서 제외하지만 yarn berry에서는 의존성 파일들(.yarn/cache
)도 git 추적을 하기도 한다. 이를 통해 zero-install을 구현할 수 있다. (zip 파일이 작은 용량을 가지기 때문) 그 결과, branch를 바꿨다고 해서 yarn install을 하지 않아도 되며, ci에서 의존성 설치 시간을 줄일 수 있다.
‘package manager manger’, 말 그대로 패키지 매니저를 관리하는 도구다. (volta, nvm의 패키지 매니저 버전)
LTSv16가 아니라면
npm i -g corepack
으로 다운 받고corepack enable
을 실행해야 활성화된다.
package.json
의 packageManager
필드에서 패키지매니저와 패키지매니저 버젼을 명시해서 강제할 수 있다.
예로, 폴더 A에서는 pnpm@6, 폴더 B에서는 pnpm@7을 강제하는 상황을 가정해보자. 폴더 A에 접속하면 pnpm은 버젼이 자동으로 6으로 변경되고, 폴더 B에서는 7로 변경된다.
corepack prepare pnpm@6.24.2 --activate
을 통해서 유동적으로 버젼을 변경할 수도 있다.
String.prototype.replace
의 두 번째 인자String.prototype.replace
의 두 번째 인자에는 함수가 올 수도 있다.
그리고 두번째 인자의 타입이 string
이라면, 특수한 값이 허용된다.
$$
: $
기호를 삽입$&
: 매치된 문자열을 삽입$\’
: 매치된 문자열 이후의 문자열 삽입const sentence = "안녕하세요 저는 지그입니다.";
sentence.replace("지그", "$$");
// 안녕하세요 저는 $입니다.
sentence.replace("지그", "$&지그");
// 안녕하세요 저는 지그지그입니다.
sentence.replace("지그", "$`");
// 안녕하세요 저는 안녕하세요 저는 입니다.
sentence.replace("지그", "$'");
// 안녕하세요 저는 입니다.입니다.
SVG의 fill 속성은 css로 override가 가능하다.
다음과 같은 svg 요소가 있을 때,
<svg>
<path class="icon" fill="#fff" ... />
{/* ... */}
</svg>
다음 CSS로 요소의 fill 속성을 override 할 수 있다.
.icon {
fill: yellow;
}
하지만 그 하위 태그의 fill 속성까지는 override 하지 못한다. 또 fill 속성이 아니라 inline-css로 적용된 fill은 우선순위가 더 높으므로 override 되지 않는다.
Template.bind()
Storybook에서 Story를 만들 때 bind
를 쓰는 이유는 Template
함수를 복제해서 사용하기 위해서다. Template
을 복제하면 각 복제본의 속성을 독립적으로 관리할 수 있다 (또한 속성에 args
를 추가해 여러 버전을 만들 수 있다).
Storybook이 이런 추가적인 조치를 하는 것은 args
를 기반으로 live-edit 기능이 동작하기 때문이다.
cf) Template.bind({})
에서 인자 {}
는 넘겨주지 않아도 된다 (하지만 타입스크립트는 싫어한다.)
시각적 회귀 테스트는 e2e와는 다르다. e2e는 컴포넌트 존재 유무를 판단하지만 시각적 회귀 테스트는 해당 레이아웃이 제대로 보여지는지 혹은 깨졌는지를 파악할 수 있다.
최근에 캡처한 스크린샷과 현재 스크린샷을 비교해 리포트를 작성하는 방식으로 테스트를 한다. 시각적 회귀 테스트 서비스로는 cypress, LOKI 가 있다.
회귀 테스트를 이용하지 않는다면 디자인시스템 라이브러리의 버전이 달라질 때마다 계속 확인해줘야 한다.
에디터에서 많이 사용되는 WEB API다. 예를 들어, 에디터에서 “안녕하세요”에서 “안녕”을 마우스로 드래그하고 cmd+b
하면 “안녕”으로 변경해주는 API다.
document.getSelection()
을 통해 현재 셀렉션을 알 수 있다. selection은 anchorNode(시작)와 focusNode(끝)로 나눠진다.
cf) firefox는 멀티 셀렉션이 된다.
form control에서는 또 다른 형태로 selection API를 제공하며, domElement 자체에서도 메소드를 사용할 수 있다.
input.selectionStart
– input안에 활성화되어있는 selection start 위치input.selectionEnd
– input안에 활성화되어있는 selection end위치input.selectionStart === input.selectionEnd
- 그곳이 커서의 위치이다.input
에 text를 추가하는 예시를 들어보자.
button.onclick = () => {
// setRangeText: election에 포함되어있는 text를 replace하는 메소드
input.setRangeText("HELLO", input.selectionStart, input.selectionEnd, "end");
input.focus();
};
BigInt 값은 TypeScript에서 bigint
타입으로 추론된다.
숫자 뒤에 n
을 붙여 Bigint 리터럴을 사용할 수 있다.
typeof 1n === "bigint"; // true
typeof BigInt("1") === "bigint"; // true
BigInt는 BigInt끼리의 사칙연산이 가능하다. (>>>
를 제외한 비트연산자나 제곱연산자도 사용이 가능하다)
+
단항연산자는 지원하지 않는다.sed
리눅스 쉘 명령어sed
는 stream editor의 준말로, input stream (file이나 pipeline을 통한 input)에서 문자 transformation을 수행한다.
input 파일을 한줄한줄 읽고 명령을 따라서 해당하는 줄(line)을 변경한다. 그리고 그 결과를 standard output으로 반환해준다.
# file.txt에 있는 old를 new로 변경
# s: search와 replace를 하겠다는 명령어
sed 's/old/new/g' file.txt
File 객체
Blob
의 인터페이스를 확장해서 사용하는 객체이다. (Blob: Binary large object)
Blob
을 쓸 수 있다면 File
도 쓸 수 있다.
FileReader
, URL.createObjectURL()
등FileList 객체
item()
메서드로 인덱스를 넘기면, 위의 File
객체를 얻을 수 있다.HTMLCollection.item
[HTMLCollection](https://developer.mozilla.org/ko/docs/Web/API/HTMLCollection)
의 메소드 item()
은 컬렉션 안의 특정 인덱스에 위치한 노드를 반환한다.
var c = document.images; // HTMLCollection입니다
var img0 = c.item(0); // 이렇게 item() 메소드를 이용할 수 있지만
var img1 = c[1]; // 이렇게 표기하는게 쉽고 더 보편적입니다
Ref https://developer.mozilla.org/ko/docs/Web/API/HTMLCollection/item
role="grid"
는 시각적으로는 표 형태이지만, 방향키 등을 통해 탐색하거나 인터랙션이 필요할 때 사용할 수 있는 role이다.
전체 컨테이너 역할을 하는 <table>
요소에 role="grid"
를 삽입하고 각각의 <th>
에role="columnheader"
, <tr>
에 role="row"
, <td>
에 role="gridcell"
을 삽입한다.
주로 날짜를 선택하는 DatePicker 등에 사용한다.
Ref https://aoa.gitbook.io/skymimo/aoa-2018/2018-aria/datepicker
이때는 trailingSlash
를 붙여줘야 한다.
기본적으로 브라우저에서는 URL의 주소 끝에 슬래시가 붙어있으면 디렉토리라는 의미고, 없다면 여기가 끝, 즉 파일이라는 것을 의미한다.
Next.js에서는 기본으로 url 끝에 /
가 있다면, 제거해서 페이지를 이동한다. 이를 바꿔주기 위해 next.config.js에서 trailingSlash: true
를 명시해줘야 한다.
Ref https://nextjs.org/docs/api-reference/next.config.js/trailing-slash
브라우저 캐시에는 두 종류가 있다.
v1.0.0
부터 버전이 시작한다. 그러나 main
브랜치 시작에 v0.0.0
버전으로 시작하게 되면 해당 버저닝을 따라간다. (ex. v0.1.0-beta.1
)window.URL.createObjectURL(file)
을 사용할 수 있다. url을 모두 사용하고 나면 window.URL.revokeObjectURL
메소드로 없애줘야 한다. (메모리 관리를 위해서)
rollup 버전 2까지는 빌드 결과물이 어느 모듈 시스템(esm, cjs)에서 사용되더라도 동작하도록 보조하는 헬퍼를 지원했는데, 버전 3부터는 헬퍼를 디폴트로 제공하지 않는다. 이 때문에 모듈 시스템 관리를 제대로 하지 않으면 에러가 발생할 수도 있다 (rollup 3를 사용하는 vite 4도 마찬가지)pnpm add
: 프로젝트에 새로운 종속성을 추가할 때 사용pnpm install
: lockfile이 존재하는 프로젝트에서 lockfile에 존재하는 종속성을 설치할 때 사용sync
명령어는 없는 데이터에 대해서는 복사를 수행하나, 같은 데이터는 복사하지 않는다. 이때 ‘같은 데이터’의 판단 기준은 수정날짜와 파일 사이즈로 판단한다. (cf. -delete
옵션으로 원본에서 삭제된 데이터를 타겟에서도 삭제할 수 있다.)React.FC
에 children
이 없어서, PropsWithChildren<Props>
으로 prop의 타입을 지정하여 children
이 있는 prop을 사용할 수 있다.tsconfig-path
설정을 추가해주어야 한다. (Ref )gRPC는 Google에서 개발한 RPC(Remote Procedure Call) 시스템이다. 전송을 위해 TCP/IP 프로토콜과 HTTP 2.0 프로토콜을 사용하고 IDL(Interface Definition language)로 protocol buffer를 사용한다.
… 🤷♀️?
배경지식부터 짚고 가자.
그래서 gRPC가 뭐냐면…
gRPC는 구글에서 만든 RPC 플랫폼이며 protocol buffer와 RPC를 사용한다. 최신 버전의 IDL로 proto3를 사용한다. Java, C ++, Python, Java Lite, Ruby, JavaScript, Objective-C 및 C#에서 사용 가능하다.
SSL/TLS를 사용하여 서버를 인증하고 클라이언트와 서버간에 교환되는 모든 데이터를 암호화한다. HTTP 2.0을 사용하여 성능이 뛰어나고 확장 가능한 API를 지원한다.
gRPC에서 클라이언트 응용 프로그램을 서버에서 함수를 바로 호출 할 수 있어 분산 MSA(Micro Service Architecture)를 쉽게 구현 할 수 있다. 서버 측에서는 서버 인터페이스를 구현하고 gRPC 서버를 실행하여 클라이언트 호출을 처리한다.
RPC 플랫폼 + 배경지식에 나온 모든 좋은 기능들을 때려박은 시스템이다!
Ref https://chacha95.github.io/2020-06-15-gRPC1/
SEO가 필요한 사이트가 아니라면, Next.js가 필요없다는 이야기다.
…등등의 수도 없는 악설을 퍼붓고 있다 🤷♀️
그러나 Next.js의 SSG나 ISR을 이용한 렌더링은 꽤나 훌륭한 선택지가 될 수 있으므로, SEO나 OG가 중요한 웹사이트들에서는 사용하는 것을 추천한다고 한다~
Ref https://blog.webf.zone/you-dont-need-next-js-and-ssr-7c6bd27e78d8
민족 대명절 설이다. 🐰 계묘년 새해… 올해는 왠지 설이 너무 빨라서 아쉬워버리기도 하지만 (아직 일도 제대로 안 해서 쉬는 기분이 안 날 줄 알았다.) 막상 또 쉬니까 좋다. 설 연휴 안 끝났으면… 그치만 평상시에 일도 공부도 열심히 해야 또 쉬는 맛이 나는 거겠지 😎
설 연휴 직전엔 오이도 드라이브 갔다왔다. 찬바람 미쳤다. 조개구이는 아주 맛있게 먹고왔다. 배터져부러