May 20, 2023 • ☕️☕️ 8 min read
오늘도 놀고 내일도 놀고 🎡
pnpm 공식문서에서, window에서는 symbolic link를 다루는게 약간의 문제가 있다고 한다.
대부분의 Windows 도구, 유틸리티 및 셸은 최대 260자를 초과하는 파일 및 폴더 경로를 처리할 수 없는 것이 문제인 듯하다.(2014년 기준)
~npm@2 버전까지는 non-flat 구조였으나, 중첩되는 node_modules마다 패키지를 설치했기 때문에 중복 설치되어 비효율적이었다. 그래서 npm@3~ 부터는 node_modules를 flat하게 만들었는데(최상위 node_modules로 모두 끌어올림), 서로다른 버전의 같은 패키지의 경우 문제가 발생하거나, 그 과정 자체가 쉽지 않다.
pnpm은 npm@~2의 구조를 가지지만, 패키지를 직접 설치하지 않고 symbolic link로 연결한다.
모바일에서는 hover가 데스크탑 달리 정상적으로 동작하지 않기 때문에 따로 처리해주어야 한다.
대응 CSS 코드
@media (hover: hover) { … }
@media (hover: none) { … }
Ref MDN - hover
auto
margin
을 제외한 높이를 가리킨다.fit-content
auto
의 하이브리드 모드처럼 동작한다.height
값으로 사용한다.auto
키워드처럼 가용 높이에서 margin
을 제외한 높이를 가리킨다.👩🏫
auto
는display: inline-block
인 요소에만 먹는다.
extends
는 is subtype of
으로 패러프레이즈할 수 있다.
예시)
Array extends readonly Array
1 extends number
{ children: ReactNode } extends { children?: ReactNode }
useDebugValue
hook에 custom label을 붙여준다.
import { useDebugValue } from "react";
function useOnlineStatus() {
// ...
useDebugValue(isOnline ? "Online" : "Offline");
// ...
}
Ref https://react.dev/reference/react/useDebugValue
React에서 ref는 첫 번째 렌더에 값을 가지지 않을 수도 있다.
ref의 값은 componentDidMount
이후에 설정되며, useRef
에서 ref는 함수 컴포넌트가 반환되고 컨텐츠가 렌더되기 전까지 값을 가지지 않을 수 있다. 즉 첫 번째 렌더 시에는 ref.current
가 null
이 나올 수도 있다.
그렇다면 useEffect
의 deps에 ref.current
값을 넣고 ref.current
값이 바뀌면 useEffect
가 호출될까?
아니다.
리렌더링이 발생하여 useEffect
가 호출되는 경우는 다음 경우 뿐이다.
ref 변화에 따라 리렌더링을 하고자 한다면 ref 대신 useCallback
을 사용하는 방법도 있다
const itemRef = useCallback((node) => {
if (node !== null) {
// do something...
}
}, []);
return <div ref={itemRef}>메뉴 아이템</div>;
Tanstack 라이브러리의 메인테이너도 배신 당했다고 한다. (Ref)
다음 글도 읽어보면 좋다.
벡터는 표시해야할 이미지(데이터)가 많으면 그것을 그대로 코드(점,선,면)로 들고있어야 하는데, 그럼 당연히 크기가 커질수 밖에 없다. 반면 래스터는 이미지(데이터)를 표현하는 방식이 픽셀 기반으로, 비교적 많은 데이터를 표현하기 쉽다.(포맷 알고리즘에 따라 압축도 가능하다)
Ref https://www.adobe.com/kr/creativecloud/file-types/image/comparison/raster-vs-vector.html
react-router-dom v6부터는 generic을 지원하지 않아 <>
제네릭이 아닌 as
타입 단언을 사용해야 한다.
// ❌
const location = useLocation<{ state: { isNewMember: boolean } }>();
// ✅
const location = useLocation() as { state: { isNewMember: boolean } };
tree
패키지를 통해 프로젝트 폴더 구조를 출력할 수 있다.
tree
를 출력하면 node_modules
때문에 스압이 장난 아니다…tree -I 'node_modules'
명령어로 node_modules
를 제외하고 깔끔하게 출력할 수 있다.React로 마이그레이션한 것 같다. 위젯 형태로 옹기종기 이쁘구만
오랜만의 Dan의 overreacted 블로그에서 다시 본 글
https://overreacted.io/before-you-memo/
React의 memo()
나 useMemo()
를 사용하지 않으면서도 일반적인 방법으로 렌더링 최적화를 할 수 있는 방법들을 소개한다.
export default function App() {
let [color, setColor] = useState("red");
return (
<div style={{ color }}>
<input value={color} onChange={(e) => setColor(e.target.value)} />
<p>Hello, world!</p>
<ExpensiveTree />
</div>
);
}
위처럼 color
값을 부모 div
에 부여하여 <ExpensiveTree />
의 불필요한 리렌더링이 발생하는 상황이라면?
export default function App() {
return (
<ColorPicker>
<p>Hello, world!</p>
<ExpensiveTree />
</ColorPicker>
);
}
function ColorPicker({ children }) {
let [color, setColor] = useState("red");
return (
<div style={{ color }}>
<input value={color} onChange={(e) => setColor(e.target.value)} />
{children}
</div>
);
}
App
컴포넌트를 두 부분으로 나누어, color
값에 의존하는 컴포넌트는 ColorPicker
로 분리한다. color
값이 변하면 ColorPicker
는 리렌더링하지만, App
에서 받은 children
은 변하지 않기 때문에 React는 해당 subtree를 방문하지 않는다. 따라서 ExpensiveTree
는 리렌더링되지 않는다.
👩🏫
memo
나useMemo
를 사용하기 전에, 바뀌지 않는 부분들을 분리하여 최적화할 수 있는지 방법을 찾아보자!
리소스 로딩 순서 최적화가 어려운 이유
각 리소스들에 대한 관계, 제약사항 및 우선순위들
<head>
에 동기적으로 포함된 3P스크립트는 CSS 및 폰트 파싱을 블록하여 FCP에 악영향을 준다. 메인 스레드에서 실행되는 3P 스크립트는 1P 스크립트의 실행을 지연시키고 hydration도 지연시켜 FID를 지연시킨다.이상적인 리소스 로딩 순서
👇 아래 링크에서 확인해보자 😋
Ref https://patterns-dev-kr.github.io/performance-patterns/loading-sequence/
하루는 팀원들과 롯데월드, 다음날은 스타필드 스포츠몬스터에 다녀왔다. 이틀 연속으로 신나게 놀다니 🤸♀️
주말에도 너무 예쁘고 평화로웠던 서래섬에 놀러가 힐링했다. 🌼
단합력(?)도 기르고, 리프레쉬도 제대로 한 만큼 다시 열일해야겠다!