Window객체 확장
declare global 구문을 사용하면 브라우저의 window 객체를 확장하는 인터페이스를 정의할 수 있습니다. TypeScript에서 Window 인터페이스는 전역 window 객체를 나타내므로, 이 인터페이스를 확장하면 브라우저 환경에서 window 객체에 새로운 속성을 추가할 수 있습니다.
declare global {
interface Window {
myCustomProperty: string;
myCustomFunction: () => void;
}
}
// window 객체에 새로운 속성을 추가
window.myCustomProperty = "Hello, world!";
window.myCustomFunction = () => {
console.log("Custom function called!");
};
// 사용 예제
console.log(window.myCustomProperty); // "Hello, world!"
window.myCustomFunction(); // "Custom function called!"
declare global 구문을 사용하면 브라우저의 window 객체를 확장하는 인터페이스를 정의할 수 있습니다. TypeScript에서 Window 인터페이스는 전역 window 객체를 나타내므로, 이 인터페이스를 확장하면 브라우저 환경에서 window 객체에 새로운 속성을 추가할 수 있습니다.
` prettier --write` 명령어
prettier --write 명령어는 파일을 자동으로 포맷하고 변경 사항을 저장(덮어쓰기)하는 명령어입니다.
prettier --write "src/**/*.{js,ts,jsx,tsx}"
prettier --write --parser babel index.js
Vite와 TypeScript의 Alias 설정은 동일하게 맞추는 것이 좋다!
- Vite의 alias → 번들링(Bundling) 시 적용
- TypeScript의 paths → 트랜스파일링(Transpiling) 시 적용
즉, 서로 다르게 설정하면 모듈 해석 방식이 달라져서 충돌 가능성이 높아지므로, 같은 alias를 동일하게 설정하는 것이 가장 안전한 방법입니다.
ESM(ES Modules) vs CJS(CommonJS) 개념 정리
ESM (ECMAScript Modules) | CJS (CommonJS) |
import/export 문법 사용 브라우저 및 최신 Node.js 환경에서 사용 가능 비동기 로드(호이스팅 지원, 최적화 가능) |
require/module.exports 문법 사용 Node.js에서 기본 지원 (하지만 브라우저에서는 직접 실행 불가능) 동기 로드(실행 순서가 중요함) |
CSR (브라우저 실행)
- 브라우저에서 실행되므로 기본적으로 ESM 사용.
- import 문법으로 모듈을 로드함.
SSR (Node.js 실행)
- Node.js에서는 기본적으로 CJS 방식(require())을 사용.
- 하지만, ESM 전용 패키지를 사용하려면 추가 설정이 필요함.
- Vite 같은 번들러에서는 ssr.noExternal 설정을 통해 해결 가능.
- package.json에 "type": "module" 추가
- tsconfig.json에 "moduleResolution": "NodeNext" 설정
- Vite 사용 시 ssr.noExternal 옵션 추가
-Vite에서 SSR을 사용할 때 기본적으로 node_modules에 있는 대부분의 패키지를 외부 모듈(external)로 설정합니다.
-Vite뿐만 아니라 Webpack, Rollup, esbuild 같은 번들러들도 기본적으로 node_modules를 외부 모듈(external)로 설정하는 경우가 많습니다.
=> 이유는 번들 크기를 줄이고 성능을 최적화하기 위해서입니다.
여러 프로젝트나 페이지가 동일한 외부 라이브러리(예: React, Vue, lodash 등)를 사용할 때, 각 번들에 라이브러리를 포함시키지 않고 외부에서 로드하면 중복된 코드를 제거할 수 있습니다.
Vite의 경우 특정 외부모듈을 번틀링 설정할 수 있음
import { reactRouter } from "@react-router/dev/vite";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
export default defineConfig({
plugins: [reactRouter(), tsconfigPaths()],
optimizeDeps: {
include: ["@mui/material", "@mui/icons-material"],
},
ssr: {
noExternal: ["@mui/material", "@mui/icons-material"], // MUI 관련 패키지 번들링 포함
},
});
리엑트의 상태와 재랜더링 (useState, useEffect)
usState의 상태값
기본적으로 `set[State]` 함수는 항상 같은 참조값을 유지
1. 기본 타입 (number, string, boolean, null, undefined)
- 상태 값이 변하지 않으면 참조 값도 변하지 않음 → 리렌더링이 발생하지 않음.
- 상태 값이 변하면 새로운 값으로 대체됨 → 리렌더링 발생.
2. 객체, 배열, 함수 ({}, [], () => {})
- 상태 값이 새로운 객체(배열, 함수)로 변경되면 참조값이 변경됨 → 리렌더링 발생.
=> 안의 변경사항이 없이 다시 set하다러도 새로운 객체가 할당됨으로 참조값이 변경됨 - React는 은 비교(shallow comparison)를 사용해서 기존 객체와 다른 새 객체가 생성되면 리렌더링을 트리거함.
React의 상태 업데이트 최적화 방식과 의존성 배열(deps)이 상태 변화에 미치는 영향 때문
export default function Home() {
const [count, setCount] = useState(0);
const input = { mbrNo: "0909" };
setCount(1); // ❌ 렌더링 중 상태 업데이트 → 무한 루프 발생 🚨
return (
<>
<p>hello</p>
<button onClick={() => setCount(0)}>init</button>
</>
);
}
React는 렌더링 중에 setState를 호출하면 즉시 다시 렌더링을 트리거함.
useEffect활용
useEffect(() => {
setCount(1);
console.log("useEffect....");
}, [input]);
❓ 왜 무한 루프가 발생하지 않을까?
- 여기서 핵심은 setCount(1);이 실행되더라도 React가 상태가 변하지 않았다고 판단하면 리렌더링을 하지 않기 때문
‼ React에서는 useEffect 내부에서 사용된 외부 변수 의존성 배열([])에 포함되지 않으면 경고
'WEB개발 > REACT' 카테고리의 다른 글
VITE (0) | 2025.03.17 |
---|---|
[환경구성] React개발을 위한 유용한 노드모듈 (node_modules) (0) | 2025.02.14 |
[환경구성] tsconfig.js, tsc (0) | 2025.02.13 |
[React] Next, Typescript... 오류모음 (0) | 2024.01.26 |
[React] web성능 메트릭 (0) | 2023.12.18 |