March 5, 2022 • ☕️☕️☕️ 15 min read
운동조와
baseURL
tsconfig.json에 있는 baseURL
에 따라 타입 체킹 타임에서 모듈의 위치를 판단한다. src
는 루트 디렉토리에 존재하고, src/component
디렉토리 하위에 있는 모듈을 import하고자할 때 baseURL: ‘.’
일 경우에는 import ‘src/component/...’;
처럼 작성하지만, baseURL: ‘src’
일 경우에는 import ‘component/...’;
와 같은 식으로 경로를 작성할 수 있다.
하지만 IDE에서 인지했다고 해서 빌드 중 해당 파일을 반드시 찾을 수 있는 것은 아니다. 빌드 시에는 webpack config 파일의 resolve.modules
항목에 따라 모듈의 위치를 판단한다.
// webpack.config.js
module.exports = {
//...
resolve: {
modules: ["node_modules"],
},
};
Ref https://webpack.js.org/configuration/resolve/#resolvemodules
Template Literal Type이란 기존 TypeScript의 String Literal Type을 기반으로 새로운 타입을 만드는 도구이다.
여기서 살펴볼 것은, Template Literal Type을 Union type(합 타입)과 함께하면, 결과물도 Union Type이 된다는 사실이다.
type Baemin = "baemin";
type Teams = "store" | "riders" | "b-mart" | "ceo-square";
// type BaeminTeams = 'baemin store' | 'baemin riders' | 'baemin b-mart' | 'baemin ceo-square';
type BaeminTeams = `${Baemin} ${Teams}`;
Ref https://toss.tech/article/template-literal-types
앨리어싱(Aliasing)이란, 컴퓨터 그래픽 해상도의 한계로 선 등이 우둘투둘하게 되는 현상을 말한다. 계단 현상이라 부르기도 한다.
안티 앨리어싱(Anti-Aliasing)이란 이를 방지하는 것을 의미한다. 브라우저는 이미지를 확대했을 때, 원래 픽셀에 해당하는 부분을 매끈하게 처리하는 안티 앨리어싱 처리를 한다. 그래픽이 중요한 게임 등의 서비스에서 많이 사용하는 개념이다.
Ref https://post.naver.com/viewer/postView.nhn?volumeNo=21010728&memberNo=42689664
.ts
파일 내 모듈 순서(import 순서)를 정렬하기eslint의 sort-imports
룰을 이용하면 같은 import 라인 상에서 named export 된 모듈명을 정렬할 수 있다.
{
"sort-imports": ["error", {
"ignoreCase": false,
"ignoreDeclarationSort": false,
"ignoreMemberSort": false,
"memberSyntaxSortOrder": ["none", "all", "multiple", "single"],
"allowSeparatedGroups": false
}]
}
🤓 참고
eslint-plugin-import
의import/order
룰을 사용하면, path에 따라 그루핑을 하여 각 줄들을 정렬할 수 있다.eslint-import-resolver-typescript
로 settings를 설정하면 tsconfig에 설정해둔 path alias를 internal로 인식해준다.
Ref https://eslint.org/docs/rules/sort-imports
OAuth 2.1에서는 2.0에서 주로 보안 이슈를 제거했다.
Glob 패턴은 와일드카드 문자를 사용해서 일정한 패턴을 가진 파일 이름들을 지정하기 위한 패턴이다. tsconfig.json과 같은 설정 파일 내에서 경로 지정 시 사용할 수 있다.
예를 들어, /**/*.js
와 같이 경로를 지정해주었다면, 현재 디렉토리와 그 하위 디렉토리 내에 존재하는 모든 .js
파일들을 선택한다.
Ref https://velog.io/@k7120792/Glob-패턴과-정규표현식
Record<Keys, Type>
vs 인덱스 시그니처TypeScript에서 객체 타입을 지정할 때 사용하는 Record<Keys, Type>
와 인덱스 시그니처 중에서, key를 명확하게 표현하고자 할 때는 인덱스 시그니처를 사용하는 것이 바람직하다.
type example = { [name: string]: number };
위 예제와 같이 key가 name
이라는 의도를 명확하게 표현할 수 있기 때문이다.
하지만 key를 특정 타입으로 제한하고자 할 때는 Record
타입을 쓰는 것이 좋다. 인덱스 시그니처의 key는 number
나 string
타입만 허용하며, 문자열 리터럴을 허용하지 않기 때문이다.
🤓 생각해보기
- 런타임 때까지 객체의 속성을 알 수 없을 경우에만(예를 들어 CSV 파일에서 로드하는 경우) 인덱스 시그니처를 사용하도록 한다.
- 안전한 접근을 위해 인덱스 시그니처의 값 타입에 undefined를 추가하는 것을 고려해야 한다.
z-index
와 쌓임 맥락‘쌓임 맥락’은 가상의 Z축을 사용한 HTML 요소를 3차원으로 개념화한 것이다. Z축 사용자 기준으로 보여지는 화면과 각각의 HTML 요소는 자신의 속성에 따른 우선순위를 사용해 3차원 공간을 차지하고, 그렇게 쌓여가는 것을 쌓임 맥락이라 부른다.
z-index
만을 이용하면 원하는 대로 쌓임 맥락을 만들 수 없다. 새롭게 만들어진 쌓임 맥락은 이전에 만들어진 쌓임 맥락보다 무조건 앞에 존재하기 때문이다. 따라서 뒤에 있는 쌓임 맥락에 z-index
를 아무리 큰 숫자를 주더라도 앞에 있는 쌓임 맥락보다 앞에 올 수 없게 된다.
모든 쌓임 맥락에는 그것의 뿌리(root) 요소인 HTML 요소가 있다. 어떤 요소에서 쌓임 맥락이 새롭게 만들어질 때, 그 쌓임 맥락은 자식 요소들이 쌓임 순서에서 특정 범위를 벗어나지 못하도록 한계를 정하게 된다. 이는 맨 뒤의 쌓임 맥락에 있는 요소는 그보다 앞의 쌓임 맥락에 있는 요소보다 앞에 나올 수 없다는 것을 의미한다.
🤓
isolation: isolate
>isolation
CSS 속성은 요소가 새로운 쌓임 맥락을 생성해야 하는지 지정한다.isolation: isolate
은 항상 새로운 쌓임 맥락을 생성합니다.
Ref http://b1ix.net/295 https://developer.mozilla.org/ko/docs/Web/CSS/isolation
크롬 개발자 도구에서 제공하는 Console Utilities API는 특정 태스크들을 수행하기 위한 편리한 메서드들을 제공한다. 주로 DOM을 선택하고 탐색하거나, 데이터를 읽기 쉬운 형식으로 변환하거나, 프로파일러를 멈추고 실행시키거나, DOM 이벤트들을 모니터링할 때 사용할 수 있는 도구들이다.
$0
: 현재 inspector로 선택한 element, 그 다음 선택한 것은 $0에 계속 갱신이 되고, 이전에 선택했던 것은 $1, $2, $3, $4에 차례로 할당된다. 즉 내가 inspector로 선택한 element 총 5개를 기억해두고 쓸 수 있다.$_
: console 창에서 맨 마지막에 계산된 값을 불러올 수 있다.$(selector)
: jQuery처럼 document.querySelector
를 줄여서 쓸 수 있다.이밖에도 $
표시로 시작하는 다양한 셀렉터들이 존재하니 구경 가보자~!1
Ref https://developer.chrome.com/docs/devtools/console/utilities/#0-4
useEffect
와 useMemo
의 실행 순서A 컴포넌트가 B 컴포넌트를 감싸는 형태일 때, 각 컴포넌트에 useEffect와 useMemo가 구현되어 있다고 가정해보자.
useEffect
: B 실행 후 A가 실행된다. 즉 useEffect
는 컴포넌트를 모두 그린 뒤 실행되며, 이에 따라 자식-부모 순서로 실행된다.useMemo
: A 실행 후 B가 실행된다. 즉 useMemo
는 컴포넌트를 그리기 시작할 때 실행되며, 이에 따라 부모-자식 순서로 실행된다.논리 픽셀(css 상의 픽셀)과 물리 픽셀(실제 디바이스 픽셀)이 따로 존재한다. 디바이스, 또는 브라우저마다 논리 픽셀과 실제 픽셀의 비율이 다를 수 있다. 그래서 디바이스에 따라 경계선이 흐리게 보이는 sub-pixel rendering 이슈가 발생할 수 있다.
예를 들어, 아이폰 4가 구현하는 해상도는 640*960이고(물리 픽셀), CSS로 표현할 수 있는 값은 320*480일 때 (논리 픽셀), CSS로 구현하는 화면은 320px이지만 실제 해상도는 640px로 2배의 밀도를 가지게 된다. (ratio 2)
만약 아이폰4에 디자인 작업을 할 때 320px의 디자인 파일을 받아서 작업을 하게 된다면, 640px의 해상도 화면에 320px의 디자인이 적용되기 때문에 이미지를 늘여 놓은 것과 같은 뿌연 화면이 나타나게 된다. 그렇기 때문에 모바일 작업을 할 때는 물리 픽셀에 맞춘 디자인으로 작업을 해야 한다.
이는 window.devicePixelRatio
를 통해 해결 가능하다. width나 height에 window.devicePixelRatio
를 곱해주면 된다.
논리픽셀을 적용하기 위한 수단으로
meta
태그를 사용할 수도 있다.<meta name=“viewport” content=“width=device-width”>
Ref https://abcdqbbq.tistory.com/47
결합도는 서로 다른 모듈 간에 상호 의존하는 정도 또는 연관된 관계를 의미한다.
응집도는 한 모듈 내부의 처리 요소들이 서로 관련되어 있는 정도를 말한다. 객체의 응집도란, 객체들간의 응집도가 아니라 객체 내 정의된 메서드들 간의 응집도를 가리킨다. 응집도가 높으면, 변경 대상과 범위가 명확해지는 장점이 있어서 코드를 수정하기 쉬워진다.
객체는 제너럴리스트가 아니라 스페셜리스트일수록 응집도가 높다.
setInterval
과 setTimeout
으로 custom hook 만들기리액트의 함수 컴포넌트를 이용하여 1초마다 증가하는 카운터를 만들어보자. 가장 먼저 드는 생각은 useEffect
에서 setInterval
을 사용하는 것이다.
function Counter() {
let [count, setCount] = useState(0);
useEffect(() => {
let id = setInterval(() => {
setCount(count + 1);
}, 1000);
return () => clearInterval(id);
});
return <h1>{count}</h1>;
}
위 코드는 괜찮아 보이지만, count
값은 시간이 지나도 계속 1일 것이다. 리액트는 기본적으로 매 렌더링마다 effect를 다시 등록하기 때문이다.
그러면, useEffect
의 두 번째 인자로 []
(빈 배열)을 넣어 컴포넌트 초기 마운트 시에만 effect를 실행할 수 있도록 코드를 수정해보자.
function Counter() {
let [count, setCount] = useState(0);
useEffect(() => {
let id = setInterval(() => {
setCount(count + 1);
}, 1000);
return () => clearInterval(id);
}, []);
return <h1>{count}</h1>;
}
그러나 이 역시 정상 작동하지 않는다! count
값은 한번 1로 증가한 후 계속 멈춰 있는다.
useEffect
가 첫 번째 렌더링 시에 count
의 값(즉, 0)을 capture하기 때문이다. 다시 말하면, setInterval
이 만든 클로저가 첫 번째 렌더 시의 count
의 값을 계속 참조하고 있기 때문에, count + 1
은 항상 1
이다!
문제를 해결하기 위한 두 가지 방법이 있다.
첫 번째는 setCount(count + 1)
대신 setCount(c => c + 1)
와 같은 형식의 ‘updater’ 함수를 사용하는 것이다. 그러면 항상 count
가 가리키는 최신값을 가지고 업데이트를 수행할 수 있다.
두 번째는 useReducer()
를 사용하는 것이다. reducer 안에 현재 상태와 새로운 props를 넣으면, dispatch
함수는 변하지 않기 때문에 어떤 클로저에서든 데이터를 집어넣을 수 있다.
여기서 나아가, Dan abramov는 그의 블로그에서 setInterval
hook을 제안한다.
function useInterval(callback, delay) {
const savedCallback = useRef();
useEffect(() => {
savedCallback.current = callback;
});
useEffect(() => {
function tick() {
savedCallback.current();
}
let id = setInterval(tick, delay);
return () => clearInterval(id);
}, [delay]);
}
setInterval
은 기존의 값을 계속해서 기억하고 있으며, 개발자가 언제든 새롭게 상태(ex. delay
값)를 변경할 수도 있다. useRef
hook을 통해 setInterval
에 넘어오는 콜백 함수를 붙잡아두고, 렌더링 전후로 해당 함수를 기억하게 되는 것이다.
이제 정상 작동하는 카운터를 실행할 수 있게 되었다!
Ref https://overreacted.io/making-setinterval-declarative-with-react-hooks/ https://www.aaron-powell.com/posts/2019-09-23-recursive-settimeout-with-react-hooks/
useQuery
를 사용했을 때, return 값이 undefined가 나오는 이유는 (당연히) 데이터가 비동기로 오기 때문에 아직 값이 없는 상태일 수 있기 때문이다. undefined가 아닌 데이터만을 원한다면 isSuccess
메서드를 통해 데이터를 활용하면 된다.
package.json의 main
옵션은 프로그램의 시작점이 되는 모듈의 ID를 가리킨다. 즉 ‘foo’라는 패키지가 있다면, 이 패키지를 사용자가 설치한 뒤, require('foo')
를 실행했을 때 main으로 지정한 모듈의 exports 객체가 반환된다
next 빌드 타임에는 환경이 브라우저가 아닌 node기 때문에 window
객체에 접근할 수 없다.
stale-while-revalidate
캐시 전략: API 요청에 대한 캐시 데이터가 있다면, 일단 캐시 데이터를 이용해서 사용자에게 UI를 제공하고, API 요청이 완료되면 최신 데이터로 화면을 최신화하는 전략
TTS(Text-to-Speech): 텍스트를 음성으로 변환하는 기술이다. 토스페이스 이모지에서 의미를 바꿔버린 탓에 문제가 될 수 있다고 한다.
css 스크롤 체이닝과 overscroll-behavior-x: contain;
속성은 자식 컴포넌트의 스크롤이 끝까지 도달했을 때 스크롤 체이닝으로 묶여 있는 부모 컴포넌트가 스크롤이 시작되는 것을 막아주는 속성이다.
window.onClickNativeBack
- 안드로이드 뒤로가기 버튼 누를 때 등 웹뷰에서 제어할 수 없는 뒤로가기
action에 대한 구현이 필요할 때 사용할 수 있다.
TypeScript의 infer
키워드는 CSS parser나 Router params에서 요소들을 추출하여 타입 체크를 수행할 때 사용할 수 있다.
조건에 따라 다른 값의 변수를 선언하고 싶을 때 즉시 실행함수를 사용할 수 있다.
const value = (() => {
if (condition) {
return 1;
} else {
return 2;
}
})();
배열의 모든 원소의 값이 true인지 확인할 때, 아래와 같이 작성할 수 있다.
arr.every(Boolean);
TypeScript 4.5에 새로 등장한 유틸리티 타입 중에 Awaited
가 있다. Promise
타입의 반환값을 가리킨다.
// A = string
type A = Awaited<Promise<string>>;
// B = number
type B = Awaited<Promise<Promise<number>>>;
// C = boolean | number
type C = Awaited<boolean | Promise<number>>;
Ref https://docs.npmjs.com/cli/v7/configuring-npm/package-json#main https://github.com/ghoullier/awesome-template-literal-types
mermaid
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
위와 같이 작성하면 아래와 같이 그려진다고 한다!
나날이 발전하는 github… 질수 없다. 따라잡아야지…
Ref https://github.blog/2022-02-14-include-diagrams-markdown-files-mermaid/
요새 최고로 핫해보이는… Remix 그리고 목숨을 위협 받는(?) Next.js
Ref https://blog.bitsrc.io/remix-vs-next-js-a-detailed-comparison-6ff557f7b41f
오랜만에 다시 살펴보는 프론트엔드 테스트. 우테코 프로젝트를 하며 실제로 많이 사용했던 react-testing-library와 hook 테스트에 대한 자세한 사용기가 있어서 추억(?)이 새록새록했다.
Ref https://tech.madup.com/front-test-tips/
공감하는 부분들도 있다! 뭐든 모두를 만족시킬 수 있는 도구는 없는 것 같다. 시간이 흐르고 기술이 발전해도 늘 사람들은 불평투성이야 😬
Ref https://blog.bitsrc.io/some-reasons-for-disliking-react-hooks-80f1e18eb9b3
Ref https://medium.com/codeart-mk/ux-ui-trends-2022-31023ae36fa
벌써 3월이당. 동생을 포함해서 아직 학교 다닐 사람들은 학교 개강하고, 괜히 봄이 찾아오는 것 같은 기분이다. 내 일상은 3월이 되어도 달라지는 게 없어서 그런가 이전만큼 봄이 새롭거나 설레진 않지만, 지금처럼 잔잔한 일상이 더없이 소중하게 느껴지는 하루하루다.
진짜 드라마 안 보는 성격인데 작년부터 왜 그렇게 보고싶은 게 하나씩 생기는지 모르겠다. 살만해져서 그런가… 며칠전엔 친구에게 넷플릭스 <소년심판>을 추천받아서 조금씩 보는 중이다. 성악설에 조금 기운 내게, 양아치 미자들을 정말 싫어하는 내게 딱 맞는 내용이다. 😬 일단 여유가 있을 때니 마저 봐야겠다.