Skip to content

Conversation

@Grit03
Copy link
Member

@Grit03 Grit03 commented Oct 19, 2025

Overview

Next.js와 Vite 프로젝트에서 SVG 파일을 React 컴포넌트로 자동 import 할 수 있도록 설정하기 위해선 여러 파일과 플러그인 설치, 적용이 필요합니다. 해당 내용을 자동화하는 @mash-up-web-toolkit/cli/generate-svg-config CLI 패키지를 구현했습니다.

코드 생성을 위해서, 기존 플러그인을 유지해야(비파괴적 수정)할 수 있는데, 이런 처리를 위해 ast 변환 후 코드를 일부분 수정하여 생성하는 방식을 채택했습니다. AST 변환을 위한 라이브러리는 recast를 사용하였습니다.

Package Scope

@mash-up-web-toolkit/cli/generate-svg-config

주요 기능

1. 자동 프로젝트 감지 및 설정

  • 프레임워크 감지: package.json의 dependencies를 분석하여 Next.js 또는 Vite 프로젝트 자동 감지
  • 언어 감지: TypeScript 또는 JavaScript 자동 감지
  • 패키지 매니저 감지: pnpm, npm, yarn 자동 감지 (user agent 또는 lockfile 기반)

2. Next.js 설정 자동화

  • AST 파싱(recast)을 통한 config 파일 비파괴적 수정
  • @svgr/webpack 자동 설치
  • webpack 설정 자동 추가 (SVG를 React 컴포넌트로 변환)
  • turbopack 설정 자동 추가 (Next.js 15+ turbopack 지원)
  • svgr.d.ts 타입 선언 파일 생성
  • tsconfig.json의 include 배열에 타입 선언 추가

3. Vite 설정 자동화

  • vite-plugin-svgr 자동 설치
  • vite.config 파일에 svgr 플러그인 자동 추가
  • src/vite-env.d.ts 타입 선언 파일 업데이트

4. 스마트 Config 파일 처리

다양한 export 패턴 지원:

  • ESM: export default { ... }
  • CJS: module.exports = { ... }
  • Variable export: const config = { ... }; export default config
  • Function-based config: export default defineConfig(() => ({ ... }))
  • mergeConfig 패턴 지원

기존 설정 보존:

  • 이미 webpack 함수가 있으면 내부에 SVG 처리 로직 추가
  • 이미 plugins 배열이 있으면 svgr만 추가
  • 중복 설정 방지

지원 범위

프레임워크

프레임워크 지원 여부 비고
Next.js 15.3.0 버전 이상, webpack + turbopack
Vite Vite + React

설정 파일

Next.js Vite 비고
next.config.ts vite.config.ts TypeScript
next.config.js vite.config.js JavaScript
next.config.mjs - ES Modules

패키지 매니저

패키지 매니저 지원 여부
pnpm
npm
yarn

Config 패턴

패턴 예시 지원
ESM default export export default { ... }
CJS module.exports module.exports = { ... }
Variable export const config = { ... }; export default config
defineConfig export default defineConfig({ ... })
Function-based export default defineConfig(() => ({ ... }))
mergeConfig mergeConfig(base, { ... })
핵심 파일 구조 더보기

generate-svg-config 패키지 파일 구조

packages/cli/generate-svg-config/
├── src/
│   ├── index.ts                    # 메인 진입점 및 프로젝트 감지 로직
│   ├── template/
│   │   ├── nextjs-config.ts        # Next.js config 템플릿 (JS/TS, webpack/turbopack)
│   │   └── svgr-type-declaration.ts # SVG 타입 선언 템플릿
│   ├── utils/
│   │   ├── next-config.ts          # Next.js config AST 파싱 및 수정
│   │   ├── vite-config.ts          # Vite config AST 파싱 및 수정
│   │   ├── pk-install.ts           # 패키지 매니저 감지 및 설치 로직
│   │   ├── type-utils.ts           # 타입 선언 파일 생성 및 tsconfig 수정
│   │   ├── check-dependency.ts     # package.json 의존성 확인
│   │   └── ast.ts                  # AST 유틸리티 함수
│   └── types/
│       ├── project.ts              # ProjectType ('next' | 'vite' | 'unknown')
│       └── ast.ts                  # AST 타입 정의

테스트 환경

  • apps/svg-config-playground/next-ts: Next.js + TypeScript 테스트용
  • apps/svg-config-playground/vite-react-ts: Vite + React + TypeScript 테스트용
  • apps/my-playground: 실제 동작 테스트 완료

Checklist

  • Merge 할 브랜치가 올바른가요?
  • 불필요한 코드는 제거했나요?
  • 테스트 작성 및 통과했나요?

@Grit03 Grit03 self-assigned this Oct 19, 2025
@Grit03 Grit03 added the enhancement New feature or request label Oct 19, 2025
@Grit03 Grit03 marked this pull request as draft October 19, 2025 13:36
@Grit03 Grit03 force-pushed the generate-svg-config branch 2 times, most recently from ee8bc40 to 489c2fe Compare October 19, 2025 14:01
@Grit03 Grit03 force-pushed the generate-svg-config branch from 489c2fe to 72f5bbb Compare October 19, 2025 14:13
@Grit03 Grit03 force-pushed the generate-svg-config branch from 65c63b2 to 4b96dae Compare October 19, 2025 16:52
@Grit03 Grit03 marked this pull request as ready for review October 19, 2025 19:04
@Grit03 Grit03 requested review from Brightbong92 and jeongwoo903 and removed request for Brightbong92 October 19, 2025 19:04
Comment on lines +34 to +44
if (
(types.namedTypes.Property.check(prop) ||
types.namedTypes.ObjectProperty.check(prop) ||
types.namedTypes.ObjectMethod.check(prop)) &&
((types.namedTypes.Identifier.check(prop.key) &&
prop.key.name === keyName) ||
(types.namedTypes.Literal.check(prop.key) &&
String(prop.key.value) === keyName))
) {
return prop;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Grit03

조건절이 길다보니 파악이 어려울수 있으니, 의미하는바를 변수나 함수로 바꾸는건 어떻게 생각하나요?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants