May 28, 2022 • ☕️☕️☕️ 15 min read
오랜만에 프론트 정기밋업을 했다!
mock service worker API를 사용해서 network 요청을 중간에 가로채서 대신 응답할 수 있다. 따라서 API url을 mock 전용으로 따로 구분할 필요 없으며, 서버 개발이 완료 됐거나 production 모드일 때 msw 기능을 끄면 이후 로직을 변경할 필요가 없다.
(단, 조건은 msw로 제공하는 응답 스키마가 서버와 차이가 없어야 한다.)
msw는 클라이언트에서 mock 서버처럼 동작하여, 클라이언트/서버 개발이 병렬로 진행될 때 서버의 데이터 스키마를 무작정 기다리지 않고 클라이언트에서 모델링을 진행할 수 있다.
as
속성을 제대로 명시하지 않으면 브라우저가 두번 fetch 해온다.Ref https://web.dev/i18n/en/preload-critical-assets/ https://medium.com/reloading/preload-prefetch-and-priorities-in-chrome-776165961bbf
첫째, HTTP 캐시가 있다. HTTP 통신에 Cache-Control
헤더를 사용했을 때 캐시된다.
둘째, 메모리 캐시가 있다. RAM 메모리에 저장되는 캐시로, 빠르지만 지속적이지 않다. max-age
와 같은 유효한 Cache-Control
이 없으면 이곳에 캐시된다.
크롬 개발자 도구의 Network 탭에서 Size 컬럼에 memory cache로 표시된다.
셋째, 서비스워커 캐시가 있다.
서비스 워커는 웹 응용 프로그램, 브라우저, 그리고 네트워크 사이의 프록시 서버 역할을 한다. 서비스 워커는 연관된 웹 페이지/사이트를 통제하여 탐색과 리소스 요청을 가로채 수정하고, 리소스를 굉장히 세부적으로 캐싱할 수 있다. 이를 통해 웹 앱이 어떤 상황에서 어떻게 동작해야 하는지 완벽하게 바꿀 수 있다.
서비스워커는 fetch 이벤트의 중간자 역할로 사용할 수 있다. 이 경우 서비스워커는 HTTP를 통해 정보를 요청하는 대신 가지고 있는 캐시에서 자료를 전달한다. 캐시가 삭제되지 않는 한 브라우저는 인터넷 연결 없이도 정보를 보여줄 수 있다.
window.navigator
에 serviceWorker
필드로 접근하여 서비스워커 캐시를 설정할 수 있다.
마지막으로, 푸시 캐시가 있다. 이에 대한 정보는 많이 나와있지 않은데, 서버 푸쉬 기능을 제공하는 HTTP2를 사용했을 때 HTTP2 세션에 저장되는 캐시인 것 같다. 정확한 명칭은 ‘unclaimed push streams container’라고 한다.
Ref https://developer.mozilla.org/ko/docs/Web/API/Service_Worker_API https://stackoverflow.com/questions/54959244/where-is-chrome-push-cache-stored-physically
'A1.23'
(숫자 혹은 +-가 아닌 문자로 시작할 때)
parseInt("A1.23"); // NaN
Number("A1.23"); // NaN
123A
(중간에 문자가 나올 때)
parseInt("123A"); // 123
Number("123A"); // NaN
1.23
(소수점이 있을 때)
parseInt("-1.24"); // -1
parseFloat("-1.24"); // -1.24
Number("-1.24"); // -1.24
1.23A
(소수점과 함께 문자가 있을 때)
parseInt("1.23A"); // 1
parseFloat("1.23A"); // 1.23
Number("1.23A"); // NaN
결론: Number
는 처음부터 똑바로 된 숫자를 넣어줘야 한다.
eslint는 린트 대상 파일과 가까운 eslintrc
파일의 구성을 우선시한다. 그 후에 디렉토리 상위를 탐색하면서 eslintrc
파일에 root: true
가 있거나, 최상단 루트디렉토리에 도달할 때 까지 발견한 모든 eslintrc
파일을 병합한다.
root: true
는 eslint 구성을 어디까지 병합할 지 조절할 때 사용한다.
eslintrc
파일과 eslintConfig
필드가 있는 package.json
이 동일한 디렉토리에 있다면 eslintrc
파일의 구성이 적용되며, package.json
의 구성은 무시된다. (합쳐지지 않는다.)
글자 디자인 시 발생하는 착시 현상들을 방지하고 글자의 시각적 결함을 찾아내어 글자의 디자인을 세밀하게 조정하는 작업을 말한다. 시각보정은 글자의 가독성과 판독성에 지대한 영향을 끼치기 때문에, 폰트디자인에 있어 가장 핵심이라고 할 수 있다.
간단하게 말하자면, 실제 수치상으로는 맞는데 사람의 시각에서는 이상하여 보정하는 작업이다.
path.join
vs path.resolve
path.join
은 주어진 경로 segment 를 모두 결합한 다음, 결과 경로를 정규화 한다.
path.resolve
는 절대 경로가 생성될 때까지 오른쪽에서 왼쪽으로 경로를 정규화 한다. 이때 경로 인자를 탐색하는 도중 /
을 만나면 절대경로로 인식해서 나머지 경로인자들을 무시한다. 절대경로를 찾지 못할 경우 워킹디렉토리(루트폴더) 가 자동으로 앞에 연결된다.
cf) path.resolve() === __dirname
은 실행중인 파일이 현재 작업 디렉토리에 있을 때에만 성립한다.
const path = require("path");
console.log(path.resolve()); // /home/runner/6pev2q2j72v
console.log(path.resolve("a", "b", "c")); // -> /home/runner/6pev2q2j72v/a/b/c
console.log(path.resolve("/a", "/b", "c")); // -> /b/c
console.log(path.resolve("/a", "b", "c")); // -> /a/b/c
console.log(path.resolve(__dirname, "/a")); // -> /a
console.log(path.join("/a", "/b", "/c")); // -> /a/b/c
console.log(path.join("/a", "/b", "c")); // -> /a/b/c
console.log(path.join("/a", "b", "c")); // -> /a/b/c
console.log(path.join("a", "b", "c")); // -> a/b/c
@testing-library/user-event
는 fireEvent
의 기반으로 빌드된 패키지지만, 사용자 상호작용과 더 유사한 여러 메서드들을 제공한다. fireEvent.change
는 단순히 input의 하나의 변경 이벤트를 트리거하지만 type
호출은 문자마다 keyDown
, keyPress
, keyUp
이벤트들을 트리거 한다. 즉, userEvent가 실제 사용자 상호작용과 유사하다.
언젠가 @testing-library/dom
에 포함될수도 있다고 한다.
tsconfig에서 "strict": false
면strictNullChecks
도 false가 되어서 undefined, null 타입을 무시한다. strict 모드에 속하는 세부 옵션들은 다음과 같다.
서로 다른 타입의 배열 유니온 타입의 경우 몇 가지 메소드를 사용할 수 없는 경우가 있다.
예를 들면,
type A = number[] | string[];
A
타입의 배열에는 filter
, reduce
, every
, find
등의 메소드를 사용할 수 없다. 그러나 forEach
, map
, some
등은 사용 가능하다.
이유는 각 메소드 콜백함수의 파라미터 타입이 number
인지, string
인지 알 수 없기 때문이다. 각 메소드의 인터페이스를 까보면 위에서 사용할 수 없는 메소드들은 모두 제네릭을 사용하고 있다.
extends
의 또 다른 사용type을 정의할 때 extends
키워드는 단순히 상속만을 위해 사용하지는 않는다.
type A = string | number;
type B = string;
type C = B extends A ? boolean : never;
위처럼 삼항연산자와 함께 사용하면 조건부 타입 정의가 가능하다. B
가 A
에 할당 가능한 타입이라면, 타입 C
는 boolean
이고 아니라면 never
가 된다.
window.navigator.userAgent
window.navigator.userAgent
를 파싱하여 브라우져 버젼, OS 버젼 등을 확인할 수 있다.
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.61 Safari/537.36
: 맥북 크롬Mozilla/5.0 (iPhone; CPU iPhone OS 13_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
: IE 못지않은 극악의 iOS 13.4TypeScript의 never
는 return type에 지정해도 당장의 타입체킹에 별다른 영향을 미치지 못 한다. 그러나 never
가 함수의 파라미터에 사용되는 경우 타입을 체킹할 수 있다.
function fn(input: never) {}
// 오직 `never` 만 받는다.
declare let myNever: never;
fn(myNever); // ✅
// 아무 값이나 전달하거나 아무 값도 전달하지 않으면 타입 에러 발생
fn(); // ❌ 인자 'input'에 아무 값도 주어지지 않음
fn(1); // ❌ 'number' 타입은 'never' 타입에 할당할 수 없음
fn("foo"); // ❌ 'string' 타입은 'never' 타입에 할당할 수 없음
// `any`도 통과할 수 없다.
declare let myAny: any;
fn(myAny); // ❌ 'any' 타입은 'never' 타입에 할당할 수 없음
return type이 void인 경우는 관찰대상이 아니다. 따라서 return 값에 어떤 타입이 와도 타입체킹을 하지 않는다.
const foo: () => void = () => {
return "bar"; // ✅ OK
};
Ref https://ui.toast.com/weekly-pick/ko_20220323
cacheTime
은 쿼리 인스턴스가 unmount된 후 메모리에 데이터를 캐싱해두는 시간
staleTime
은 최초의 쿼리 인스턴스가 마운트 된 이후부터 데이터를 구식이라고 판단하는 시점이다.
componentDidMount
vs render
리액트 클래스 컴포넌트 쓰는 사람 나야나
render()
메서드는 클래스 컴포넌트에서 반드시 구현돼야하는 유일한 메서드로, JSX를 렌더링한다.
componentDidMount()
는 모든 요소가 정상적으로 렌더링되었을 때 실행된다. (render()
메서드 이후에 실행된다.) 구체적으로는 컴포넌트가 마운트된 직후, 즉 트리에 삽입된 직후에 호출된다. DOM 노드가 있어야 하는 초기화 작업은 이 메서드에서 이루어지면 된다. 외부에서 데이터를 불러와야 한다면, 네트워크 요청을 보내기 적절한 위치이다.
constructor()
는 React 컴포넌트의 생성자로, 해당 컴포넌트가 마운트되기 전에 호출된다.
Ref React Lifecycle Methods Render And ComponentDidMount
git rebase
똑바로 하기다른 옵션들
Ref https://www.w3docs.com/snippets/git/how-to-rebase-git-branch.html
object의 boolean 값으로 sorting하기
const arr = [
{ id: 1, bool: true },
{ id: 2, bool: false },
{ id: 3, bool: false },
{ id: 4, bool: true },
];
// ✅ true values first
const trueFirst = arr.sort((a, b) => Number(b.bool) - Number(a.bool));
console.log(trueFirst);
// [ { id: 1, bool: true }, { id: 4, bool: true }, { id: 2, bool: false }, { id: 3, bool: false } ]
아래와 같이 해보자!
const newArray = array.map(
({ dropAttr1, dropAttr2, ...keepAttrs }) => keepAttrs
);
const arr = [
{ id: 1, name: "a", grade: 30 },
{ id: 2, name: "b", grade: 40 },
{ id: 3, name: "c", grade: 50 },
{ id: 4, name: "d", grade: 60 },
];
const newArr = arr.map(({ id, ...keepAttrs }) => keepAttrs);
console.log(newArr);
// [
// { name: 'a', grade: 30 },
// { name: 'b', grade: 40 },
// { name: 'c', grade: 50 },
// { name: 'd', grade: 60 }
// ]
Ref https://bobbyhadz.com/blog/javascript-sort-array-of-objects-by-boolean-property https://stackoverflow.com/questions/18133635/remove-property-for-all-objects-in-array
package lock 파일을 삭제 및 변경하지 않도록 유의하자. lock 파일을 지웠다가 다시 패키지를 설치하면서 @latest
옵션으로 패키지가 설치되는 경우가 있는데, 이 때 패키지의 major 버전이 바뀌면서 예기치 못한 새로운 에러가 발생할 수 있다.
test를 작성할 때 queryBy
는 실패할 게 예상되는 상황에서 사용하는 게 좋다. (Ref)
자바스크립트 Promise
에서 resolve()
를 호출해도 뒷 문장이 실행된다. 뒷 문장을 실행하고 싶지 않다면 return resolve()
를 해주자.
gif > mp4 변환 같은 이미지 프로세싱은 CPU 점유율이 매우 큰 편이다.
여러 개의 요소들이 묶여있는 그룹에서 어떤 요소의 width에 의해서 텍스트가 줄바꿈이 되면서 찌부되는 경우가 있는데, 이런 경우 white-space: nowrap
으로 줄바꿈되지 않도록 방지하여 찌부되는 것을 막을 수 있다.
block 요소 두개 중 하나는 border line이 그려져있고, 하나는 그려져있지 않을 때, flex로 정렬되더라도 두 개의 width가 다르게 나온다. 이럴 경우 flex: 50%
를 주어서 두 개의 요소 길이를 같게 만들 수 있다.
onClick
등의 이벤트 핸들러 안에서 에러를 throw하면 리액트 컴포넌트의 라이프사이클 밖에서 throw 된 에러이기 때문에 ErrorBoundary에 걸리지 않는다.
컴포넌트 테스트를 작성할 때 테스트 케이스가 많아진다면 해당 컴포넌트가 너무 많은 역할을 하고 있는건 아닌지 의심해보자.
tel:
링크를 활용하면 휴대전화에서 전화번호를 자동입력할 수 있다.
<a href="tel:+49.157.0156">+49 157 0156</a>
css only-of-type
- 같은 유형의 형제가 없을 때 사용한다.
/* Selects each <p>, but only if it is the */
/* only <p> element inside its parent */
p:only-of-type {
background-color: lime;
}
nexus를 이용하여 사설 npm package를 만들 수 있다. (Ref)
Vercel의 Next.js의 RFC에서 Remix처럼 중첩 레이아웃을 지원하겠다고 한다!
Ref https://nextjs.org/blog/layouts-rfc
C나 C++과 같은 언어는 가비지 컬렉터(GC)를 이용하여 수동으로 쓸모없는 메모리 영역을 해제할 수 있다. 하지만 자바스크립트는 그런 능력이 없다! (자바스크립트는 대체 뭘 할 수 있는 건지!)
정말로 자바스크립트의 V8 엔진은 대체 뭘 하는 걸까. V8은 힙 영역을 New/Old space으로 나누어, GC에 의해 Old space으로 옮겨진 객체는 오래된 것으로 판단하여 제거된다.
구체적으로는, 마이너 GC(Scavenger)와 메이저 GC로 나뉘어 사용하지 않는 객체들을 메모리에서 제거한다. 마이너 GC는 오래된 객체를 New space에서 Old space로 옮긴다. 메이저 GC는 Mark-Sweep-Compact 알고리즘과 Tri-color 알고리즘을 사용하여 Old space에 있는 객체들을 마킹 후에 제거한다.
전통적인 마이너 GC와 메이저 GC의 가비지 컬렉션이 수행할 때 프로그램이 멈추게 되며, 이 시간이 길어질수록 렌더링이 지연되어 UX 경험을 떨어뜨린다. 이에 최신 GC에는 여러 기술들이 추가되었다.
Ref https://fe-developers.kakaoent.com/2022/220519-garbage-collection/
오랜만에 프론트 정기밋업을 했다! 재밌었던 마수타와 여러 세션 발표가 있었다. 언젠가 (오랜 시간이 지난 후에…) 능력치가 쌓이면 발표해보고 싶다.
그리고 우테코 프론트 3기 엠티를 다녀왔다. 25명 전참이라니… 도른 사람들. (한 명은 입실렌티 갔다 늦게 왔당 ㅋㅋㅋ)