React Auto Key Plugin
transition() 호출 시 key를 자동 생성해주는 빌드 플러그인
개요
@ssgoi/react의 Auto Key Plugin은 transition() 함수 호출 시 고유한 key를 자동으로 생성해주는 빌드 타임 플러그인입니다.
왜 key가 필요한가?
SSGOI는 요소의 애니메이션 상태를 추적하기 위해 고유한 key가 필요합니다. key가 없으면:
- 같은 트랜지션을 사용하는 요소들을 구분할 수 없음
- 페이지 이동 후 돌아왔을 때 애니메이션 상태가 유지되지 않음
- 요소가 마운트/언마운트될 때 예상치 못한 동작 발생
플러그인의 역할
빌드 시점에 모든 transition() 호출을 분석하여 파일명:라인:컬럼 기반의 고유한 key를 자동 주입합니다.
// 작성한 코드
<div ref={transition(fade())}>Content</div>
// 빌드 후 변환된 코드
<div ref={transition({ ...fade(), key: "page.tsx:15:6" })}>Content</div>
설치 및 설정
플러그인은 @ssgoi/react 패키지에 포함되어 있습니다. 별도 설치가 필요 없습니다.
Next.js (Webpack)
// next.config.ts
import type { NextConfig } from "next";
import SsgoiAutoKey from "@ssgoi/react/unplugin/webpack";
const nextConfig: NextConfig = {
webpack: (config) => {
config.plugins.push(SsgoiAutoKey());
return config;
},
};
export default nextConfig;
Vite
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import SsgoiAutoKey from "@ssgoi/react/unplugin/vite";
export default defineConfig({
plugins: [react(), SsgoiAutoKey()],
});
Rollup
// rollup.config.js
import SsgoiAutoKey from "@ssgoi/react/unplugin/rollup";
export default {
plugins: [SsgoiAutoKey()],
};
esbuild
import SsgoiAutoKey from "@ssgoi/react/unplugin/esbuild";
await esbuild.build({
plugins: [SsgoiAutoKey()],
});
사용법
기본 사용 (플러그인 O)
플러그인이 설정되어 있으면 key를 생략할 수 있습니다.
import { transition } from '@ssgoi/react';
import { fade, scale } from '@ssgoi/react/transitions';
function MyComponent() {
return (
<>
{/* key 생략 가능 - 자동 생성됨 */}
<div ref={transition(fade())}>
Fade 효과
</div>
<div ref={transition(scale())}>
Scale 효과
</div>
</>
);
}
명시적 key 사용
특별한 경우 명시적으로 key를 지정할 수 있습니다. 플러그인은 이미 key가 있는 경우 건너뜁니다.
<div ref={transition({
key: "my-custom-key", // 명시적 key 사용
...fade()
})}>
Content
</div>
리스트에서 사용 (.map)
.map()으로 렌더링되는 리스트에서는 JSX key만 있으면 됩니다. 플러그인이 JSX key를 읽어서 파일:라인:컬럼:${jsxKey} 형태로 자동 생성합니다.
function ItemList({ items }) {
return (
<ul>
{items.map((item) => (
<li
key={item.id} // JSX key만 있으면 충분!
ref={transition(fade())} // 플러그인이 자동 처리
>
{item.name}
</li>
))}
</ul>
);
}
생성되는 key 예시: ItemList.tsx:8:10:item-1, ItemList.tsx:8:10:item-2, ...
플러그인 없이 사용
플러그인을 사용하지 않는 경우, 반드시 고유한 key를 직접 지정해야 합니다.
// 플러그인 없이 사용 시 - key 필수!
<div ref={transition({
key: "unique-key-1",
...fade()
})}>
Content
</div>
// 리스트에서도 key 필수
{items.map((item) => (
<li
key={item.id}
ref={transition({
key: `item-${item.id}`, // transition key도 필요
...fade()
})}
>
{item.name}
</li>
))}
작동 원리
1. 코드 분석
플러그인은 .tsx, .jsx 파일에서 transition() 함수 호출을 찾습니다.
2. 위치 기반 key 생성
각 호출의 소스 코드 위치(파일명, 라인, 컬럼)를 기반으로 고유한 key를 생성합니다.
파일명:라인:컬럼
예: MyComponent.tsx:25:8
3. JSX key 결합 (리스트)
.map() 내부의 요소인 경우, 상위 JSX 요소의 key prop을 찾아 결합합니다.
파일명:라인:컬럼:${jsxKey}
예: ItemList.tsx:8:10:item-123
4. 코드 변환
원본 코드를 변환하여 key를 주입합니다.
// Before
transition(fade())
// After
transition({ ...fade(), key: "MyComponent.tsx:25:8" })
플러그인 옵션
interface SsgoiAutoKeyOptions {
/**
* 처리할 파일 확장자
* @default ['.tsx', '.jsx']
*/
include?: string[];
/**
* 제외할 파일 패턴
* @default [/node_modules/]
*/
exclude?: (string | RegExp)[];
}
사용 예시
// next.config.ts
import SsgoiAutoKey from "@ssgoi/react/unplugin/webpack";
const nextConfig = {
webpack: (config) => {
config.plugins.push(SsgoiAutoKey({
include: ['.tsx'], // .tsx 파일만 처리
exclude: [/node_modules/, /\.test\.tsx$/], // 테스트 파일 제외
}));
return config;
},
};
주의사항
이 플러그인은 React 전용입니다. Svelte, Vue, Angular 등 다른 프레임워크에서는 사용할 수 없습니다.
조건부 렌더링 주의: 같은 위치에서 조건에 따라 다른 요소가 렌더링되는 경우, 동일한 key가 생성될 수 있습니다. 이런 경우 명시적 key를 사용하세요.
// ⚠️ 주의: 같은 위치에서 조건부 렌더링
{isLoading
? <div ref={transition(fade())}>Loading...</div> // key: file:10:6
: <div ref={transition(fade())}>Content</div> // key: file:11:6 (다른 줄이라 OK)
}
// ✅ 같은 줄이면 명시적 key 사용
{isLoading
? <div ref={transition({ key: "loading", ...fade() })}>Loading...</div>
: <div ref={transition({ key: "content", ...fade() })}>Content</div>
}
디버깅
개발 중 생성된 key를 확인하려면 브라우저 개발자 도구에서 빌드된 코드를 확인하거나, 다음과 같이 로깅할 수 있습니다:
const myTransition = transition(fade());
console.log(myTransition); // key 값 확인 가능