January 14, 2023 • ☕️☕️☕️☕️ 18 min read
영어공부 잘 해보자구
브라우저는 렌더링 과정에서 웹 폰트가 다운되지 않았으면 해당 텍스트의 렌더링을 차단한다.
IE는 FOUT 방식으로 차단하고, 그 외 브라우저는 FOIT 방식으로 차단한다.
font-display
로 웹 폰트의 로딩 상태에 따른 동작 설정하기CSS의 font-display
속성으로 웹 폰트의 로딩 상태에 따른 동작을 설정할 수 있다.
swap
: FOUT 방식 - 웹 폰트 로딩 여부와 관계없이 항상 텍스트를 보여준다.
block
: FOIT 방식 - 웹 폰트가 로딩되지 않았을 때는 텍스트를 렌더링하지 않는다.(최대 3초)
fallback
: 100ms 동안 텍스트가 보이지 않고 그 후 폴백 폰트로 렌더링한다.
optional
: 100ms동안 텍스트가 보이지 않고 그 후 폴백 폰트로 전환한다.
참고로, pretendard의 font-display
는 기본으로 swap
이다
크롬, 파이어폭스 등의 브라우저들은 FOIT 방식으로 폰트를 렌더하기 때문에 네트워크 환경이 좋지 못한 사용자를 고려하려면 font-display
를 swap
등으로 변경해주는게 좋다.
Ref
tl;dr linux계열에서 pnpm은 hard-link를 이용해서 중복된 패키지들을 store로 관리한다. 윈도우에서는 junctions을 사용한다.
파일 시스템을 참조하는 방식들을 살펴보자.
ls -i
를 통해서 i-node 번호를 볼 수 있다.ln -s
명령어로 생성할 수 있으며, 일종의 바로가기라고 생각하면 된다.ln
명령어로 생성한다.pnpm의 hardlink와 store prune은 다음과 같다.
.pnpm-store
에 다운받고 hard link를 만들어서 node_modules에 저장한다.<meta />
태그로 구글 번역기의 실행 막기<meta *name*="google" *value*="notranslate" />
를 삽입해서 페이지에서 google 번역기가 실행되는걸 막을 수 있다.
class에 notranslate
을 주거나 다음 메타태그를 사용하는 것도 동일하다.
<meta name="google" content="notranslate" />
단 class에 옵션 부여 시 해당 태그 번역이 안될 뿐, 번역 버튼은 보인다. (<meta />
태그 사용 시 번역 버튼 자체가 보이지 않는다.)
+ HTML 명세에
translate
속성도 있다.<div translate="no"></div>
Ref https://html.spec.whatwg.org/multipage/dom.html#attr-translate
position: fixed
vs position: sticky
fixed
를 먹인 요소는 쌓임 스택에서 제거되어, 다른 요소들이 해당 공간을 침범할 수 있게 된다. 따라서 헤더를 fixed로 둘 경우, 헤더의 높이만큼 컨텐츠 영역에 padding-top을 먹여야 한다.sticky
를 먹인 요소는 쌓임 스택에 남아있어, 다른 요소들이 해당 공간을 침범하지 않는다. 따라서 헤더를 sticky(그리고 top: 0)로 둘 경우, 컨텐츠 영역에 별도의 조치가 필요하지 않다.Ref https://dev.to/luisaugusto/stop-using-fixed-headers-and-start-using-sticky-ones-1k30
<meta />
태그의 description
vs og:description
description
- 서치 엔진에 잡힐 수 있다.og:description
- facebook같은 소셜 플랫폼에 사용된다.둘의 content
가 같은 경우 합쳐서 쓸 수도 있다
<meta
name="description"
property="og:description"
content="배달의민족 사장님들을 위해 메뉴부터 광고까지, 가게 관리에 필요한 모든 서비스를 제공합니다."
/>
Ref
useEffect
의 실행 시점을 믿지 마세요useEffect
는 일반적으로 DOM paint 이후에 실행되지만, useLayoutEffect
에서 상태 업데이트가 발생한 경우 useEffect
는 paint 이전에 실행될 수도 있다.
useLayoutEffect
호출useEffect
호출useLayoutEffect
호출useEffect
호출→ useEffect
가 업데이트 이후에 호출될 것이라고 믿지 말아라!
Ref https://blog.thoughtspile.tech/2021/11/15/unintentional-layout-effect/
IME(Input Method Editor, 입력 방식 편집기)는 한글처럼 조합이 필요한 언어를 작성하는데 필요한 OS 부속 프로그램이다. (송 -> ㅅ + ㅗ + ㅇ)
운영체제와 브라우저는 이벤트를 중복처리하기 때문에 한글 입력이 중복으로 입력되는 경우가 생길 수 있다.
브라우저 이벤트에서는 CompositionEvent
를 제공하는데, 컴포지션 세션(composition session)은 다음의 단계로 나뉜다.
따라서 현재 Composition
이벤트가 발생중일 때, 이벤트 핸들러에서 return 시키면 중복 입력 문제를 해결할 수 있다. (event의 isComposing
속성으로 이벤트가 발생중인지 체크할 수 있다.)
disabled
된 요소는 이벤트가 트리거 되지 않는다.disabled
된 요소는 이벤트가 트리거 되지 않는다.
hover
로 트리거 되는 <Input>
컴포넌트가 있을 때 아래와 같이 사용하면 hover
가 트리거되지 않아 동작하지 않는다.
<Tooltip text="hello world">
<Input disabled />
</Tooltip>
이 때 이벤트를 트리거하기 위해서는 div
와 같은 요소로 한번 감싸 해당 요소에서 이벤트가 트리거하게 하면 된다. - 아래와 같이 코드를 작성하면 hover
로 트리거 되는 <Input>
컴포넌트는 정상 동작한다.
<Tooltip text="hello world">
<div>
<Input disabled />
</div>
</Tooltip>
vite는 빌드 시 외부 의존성은 esbuild로, 소스코드는 rollup으로 번들링한다. 외부 의존성은 일반적으로 그 내용이 변하지 않기 때문이다.
중요한 것은, esbuild는 타입 정보 없이 Transpilation만 한다는 것이다. 따라서 const enum
, 타입만 가져오는(import) 기능을 지원하지 않는다
이를 감지하기 위해 tsconfig에 "isolatedModules": true
를 필수로 설정해줘야 한다.
vite는 소스코드 build 과정에서 rollup을 사용하는데, rollup은 기본적으로 상대경로로 import되는 모듈만 대상으로 한다. 절대경로 import는 런타임에 필요한 외부종속성으로 처리한다. 즉 import ‘react’
, import ‘react-query’
와 같은 것들은 무시한다는 얘기다.
이때 경고가 뜨는데, externals
에 해다 옵션들을 명시해서 경고를 띄우지 않을 수 있다.
프로젝트에서 모노레포 공통 코드인 packages를 코드셰어링 형태로 공유하여 사용처의 환경에서 빌드하는 경우가 있다. 이때 사용처의 packages.json에서 @packages
의 의존성을 명시하고 import하기 때문에 코드상으로는 외부 의존성처럼 보인다.
하지만 rollup은 @packages
를 외부 의존성으로 인식해서 빌드대상에 포함하지 않는다. 따라서 rollup에게 특정 상대 모듈은 build에 포함시킬 것을 알려야하는데, 이를 위해 @rollup/plugin-node-resolve
플러그인을 사용해야 한다.
import type { SomeThing } from “./some-module.js”
, export type { SomeThing }
등은 타입만을 위한 구문이며, 컴파일시 완전히 제거된다.
따라서 class를 위와 같은 방식으로 import/export하면 extends에 사용한다거나, 인스턴스를 생성하기 위해 사용할 수 없다.
next는 dev server와 prod server를 구분한다
next dev
- dev 서버를 실행시킨다next build && next start
- prod 서버를 실행시킨다dev에서는 fast refresh같은 개발 편리성을, prod에서는 빌드 최적화 등의 추가작업을 제공해준다.
Next.js의
getInitialProps
는 항상 서버에서 실행되는 것을 보장하지 않는다. 대신 항상 서버 실행이 보장되는getServerSideProps
를 사용하자
Ref
엣지 런타임은 표준 Web API의 서브셋이며, ‘엣지’라는 명칭은 특정한 지역이 아닌 즉각적인 서버리스 컴퓨팅 환경을 가리킨다.
프레임워크 제작자들의 엣지 컴퓨팅과 웹표준에 기반한 오픈소스 도구 제작에 도움을 주고자 설계되었다. Next.js같은 프레임워크에 통합될 목적으로 설계되었으며, 미니멀하고 보안과 성능이 우수하다.
엣지 런타임 기반으로 설계된 프레임워크는 어디서든 실행될 수 있다. (뭔가 너무 추상적인…🤔)
Ref
UTC는 사실상 GMT를 계승한 것이다. 초의 소숫점 단위에서만 차이가 난다.
new Date()
의 인자 값으로 datestring을 사용할 수 있다.
ex) 2012-01-26T13:51:50.417-07:00
, '2007-04-05T14:30Z'
YYYY-MM-DD
– 년:월:일"T"
는 YYYY-MM-DD
구분자로 쓰임HH:mm:ss.sss
– 시간:분:초.밀리초이때 마지막 Z
파트는 zone에 대한 정보를 담는다.
Z파트에서 Z
문자만 오면 UTC+0을 의미하며,('2007-04-05T14:30Z'
), Z파트를 생략하면 로컬 타임으로 설정된다.
let d = new Date("2007-04-05T13:00");
d.toISOString();
// '2007-04-05T04:00:00.000Z'
// 한국은 UTC+9 때문에 9시간이 빠져서 나온다.
ISO 8601 날짜 형식
01/05/12는 January 5, 2012, or May 1, 2012. 등등 다양하게 표현가능하다. 이런 모호한 날짜표현을 해결하기 위한 동일한 날짜/시간 형식을 사용한다. 이 표준이 ISO 8601이다.
toISOString
메소드는 date객체를 ISO 8601 규칙 기반으로 UTC 날짜 및 시간을 표현해준다.
react-query에서 서버사이드에서 query fetching을 할 수 있는 방법을 크게 두 가지
initialData
사용<Hydrate />
사용제시하고 있는데, 여러 이슈 때문에 2. <Hydrate />
를 권장하고 있는 것 같다.
이때 <Hydrate />
를 쓴다고 앱의 모든 query들이 서버사이드에서 불러와지는 것이 아니라, 서버사이드에서 부르고 싶은 query는 next의 getStaticProps
에서 prefetchQuery
를 통해서 불러오고, 클라이언트에서 부르고 싶은 query는 그냥 일반적인 방식으로 리액트 컴포넌트 내에서 호출하면 된다.
Next는
prefetchQuery
호출 시queryClient
에 지정 queryKey와 fetch data를 매핑해서 저장한다. 해당queryClient
를 dehydrate해서 클라이언트의<Hydrate />
에 전달하면 클라이언트에서 사용하는queryClient
에서 해당 데이터를 사용해서 미리 queryKey-data 매핑을 해두기 때문에, 이후 동일한 queryKey로 fetching이 이루어질때 그 값을 바로 사용할 수 있는 거십니다. 결국 모든 query를 클라이언트에서 호출하는 로직이 있긴 해야 한다.
Ref https://react-query-v3.tanstack.com/guides/ssr#using-nextjs
void
void
연산자는 주어진 표현식을 평가하고 undefined
를 반환한다.
ex) 함수 즉시 실행
void (function iife() {
console.log("iife is executed");
})();
// Expected output: "iife is executed"
오직 undefined
원시값을 얻기 위해 void 0
또는 void(0)
처럼 사용할 수도 있다.
void 0; // undefined
Ref https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/void
setImmediate
수행시간이 긴 작업을 끝내고 브라우저가 이벤트나 화면 업데이트 등의 작업을 끝낸 직후에 콜백 함수를 실행하기 원할 때 사용한다. (? 언제 실행되는지 모르겠다…)
비동기로 실행하고 싶지만 최대한 빨리 실행하고 싶을 때 사용한다. (setTimeout(() => {}, 0)
보다 먼저 실행되는 것 같다.)
표준 API가 아니라 브라우저에서는 사용할 수 없다. Node.js 10+에서만 사용 가능하다.
Ref
Fetch-on-render - 1차 render을 모두 마친 후 필요한 데이터를 로딩 한다
Fetch-then-render - 자식 컴포넌트를 render하기 전에 필요한 데이터를 모두 로딩한다.
Render as you fetch - 렌더링과 데이터 페치를 동시에
body
태그에 margin: 8px
를 넣는 경우가 있다
with: ref: main
과 같이 branch를 명시한다. 기본적으론 push 등 action이 발생한 branch로 이미 checkout 되어 있지만, git checkout HEAD^
을 사용하면 좀 더 마음이 편해질 수 있다.git checkout -f
- 커밋되지 않은 변경 사항을 제거할 때 사용할 수 있다. 다만 unstage 상태의 파일의 변경사항이 모두 사라지니 조심하자.test -d
- 해당 파일이 존재하는지 여부를 반환한다.
test -d node_modules || npm install --legacy-peer-deps
"eslint.workingDirectories": [{ "mode": "auto" }]
- 여러 프로젝트가 존재하는 레포의 경우(ex. 모노레포) 각기 다른 설정의 린트 구성 파일을 가져야할 때 설정한다.메모리 누수는 부주의 또는 일부 프로그램 오류로 인해 더 사용되지 않는 메모리를 해제하지 못하는 것이다. 간단히, 어떤 변수가 100M의 메모리를 점유한다고 할 때, 이 변수가 사용되지 않더라도 수동 또는 자동으로 해제되지 않아 계속 메모리를 점유하는 것을 말한다.
자바스크립트를 사용하며 어떤 상황들에서 메모리 누수가 발생할까? 다음은 공통적인 사례들이다.
크롬 DevTools로 자바스크립트 애플리케이션의 메모리 사용량을 관찰할 수 있다.
⬇️ 이어서 보기 (엄청 흥미로우니 꼭 보기)
Ref https://ui.toast.com/posts/ko_20210611
프론트엔드 프레임워크로 스벨트가 점점 떠오르고 있다 😯 언젠가 한번 써봐야 하는데
빌드 툴로는 vite가 심상치 않아보인다.
Ref https://2022.stateofjs.com/en-US/
TC39에서 처음에 Promise의 취소 기능을 제안할 때는, Promise의 3가지 상태(pending/fulfilled/rejected)에 더해 새로운 ‘취소 상태(canceled)‘의 필요성을 주장했다. 이 과정에서는 취소 상태와 함께 ‘취소 토큰(Cancel Token)‘을 도입하자는 제안도 있었다.
const cancelToken = new Promise((resolve) => {
document.getElementById(“cancelButton”).onclick = () => resolve();
});
function timeout(ms, cancelToken) {
return new Promise((resolve, reject) => {
const timeoutHandle = setTimeout(() => resolve(), ms);
cancelToken?.then(() => clearTimeout(timeoutHandle));
});
}
timeout(10000, cancelToken).then(() => alert(“timeout!”));
그러나 Promise로 취소 토큰을 구현하면 취소 여부를 동기적으로 알 수 없다는 단점이 있다.
따라서 동기 및 비동기 방식에 사용할 수 있을 분 아니라, 취소 기능과 관련된 다양한 편의 기능을 제공하면서 범용성이 있는 인터페이스를 가지는 취소 토큰 표준이 최종적으로 제안되었다.
이때 제안된 취소 토큰은 비록 표준으로 채택되지 못했지만, Axios에서 요청을 취소하기 위한 기능에서 구현되었다.
그러던 와중에 AbortController
와 AbortSignal
이 등장했는데?!
⬇️ 이어서 보기 (+ 광고 SDK에서 렌더링 취소 문제를 해결한 방법)
Ref https://tech.kakao.com/2023/01/11/promise-cancelation-in-javascript/
신년이라 그런지 TIL을 많이많이 올려주시는 중… 나도 동참하기로 했다. 하루에 하나라도 배우기!
신년 목표같은거 구체적으로 세우지 않는 편이지만, 2주째 영어공부 열심히 하고 있다. 원서 읽기도 재미있다. 끝까지 흥미 잃지 않고 노력해서 호주 가서 날라댕겨보자 🦘