TIL/React

FTP 기반 php 서버에 React 점진적 마이그레이션하기(2)

시럽이 2025. 5. 22. 15:46

 이전에 작업하던 리액트를 타입스크립트로 전환해보자!

 

1. Typescript 관련 패키치를 설치한다.

 

pnpm install --save-dev typescript @types/react @types/react-dom

 

2. 명령어로 tsconfig.json 생성

 

npx tsc --init

 

 

난 자동으로 생성된 tsconfig.json이 주석으로 도배되는 등 너무 난잡해서 React + ts 에 적합한 권장 설정을 찾아 넣었다.

 

{
  "compilerOptions": {
    "target": "ES2016",
    "module": "commonjs",
    "lib": ["DOM", "ESNext"],
    "jsx": "react-jsx", // React 17 이상일 경우
    "moduleResolution": "node",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "skipLibCheck": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}

 

 

  • "jsx": "react-jsx": React 17 이상에서는 import React from 'react' 없이 JSX 사용 가능하게 설정
  • "lib": ["DOM", "ESNext"]: 브라우저 환경(DOM) 및 최신 ECMAScript 기능을 사용할 수 있게 함
  • "moduleResolution": "node": node_modules 기준의 모듈 해석 방식.
  • "strict": true: 모든 타입 검사 강화 옵션 활성화. 유지보수성 향상.
  • "noEmit": true: 실제 JS 파일을 출력하지 않고 타입 검사만 수행. 대부분의 번들러(예: Vite, Webpack)를 쓸 경우 이 설정이 적절함.
  • "resolveJsonModule": true: import config from './config.json' 같은 JSON import를 허용함.
  • "isolatedModules": true: 각 모듈이 독립적으로 처리될 수 있도록 강제. Babel이나 SWC 같은 트랜스파일러를 사용할 때 필요.

 

 

3. 파일 확장자 변경

  • src/main.jsx  src/main.tsx
  • src/App.jsx  src/App.tsx

 

4. 코드 수정

src/main.tsx

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App'
import './index.css'

createRoot(document.getElementById('root') as HTMLElement).render(
  <StrictMode>
    <App />
  </StrictMode>
)

 

뭐가 달라졌나... 싶겠지만 document.getElementById('root') as HTMLElement ← 이 부분이 TypeScript에서 반드시 필요함!!

 

 

5. vite 설정도 파일명만 바꾸면 된다.

  • vite.config.js vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  base: '/dist/',
  build: {
    outDir: 'dist',
    emptyOutDir: true,
    rollupOptions: {
      input: './src/main.tsx',
      output: {
        entryFileNames: 'react-widget.js'
      }
    }
  }
})

 

 

이렇게 하면 타입스크립트로 전환 성공~!

 

 

 

그리고 문제는,,, css가 적용되지 않았다.

 

Vite는 빌드할 때 CSS를 자동으로 JS에 번들링해서 포함시키는 걸로 알고 있는데...

몇 번을 빌드해봐도 php 페이지 개발자 도구 - 네트워크 탭에서 CSS를 못 불러왔다.

그렇다고 php에 css파일을
<link rel="stylesheet" href="/dist/assets/main-xxxxx.css">
이렇게 넣자니 빌드할 때마다 저 xxxxx 가 알파벳과 숫자로 뒤섞여서 매번 바꾸는 건 말이 안됨

 

import 하는 경로도 맞고vite.config.ts 의 base 경로도 다시 확인하고

dist/ 폴더에 assets/와 react-widget.js도 있고

PHP에서 script src="/dist/react-widget.js"가 제대로 들어가 있고

npm run build도 다시 해서 dist/ 새로 생성했는데...

 

 

 

알고보니 Vite는 CSS를 별도로 분리해서 빌드하기 때문에, PHP 템플릿에서 CSS를 따로 로딩해야 한다.

하지만 앞서 말했듯 Vite는 CSS에 해시된 이름을 붙이기 때문에 vite.config.ts에서 해시를 제거한 고정 파일명으로 설정하면 된다!

 

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  base: '/dist/',
  build: {
    outDir: 'dist',
    manifest: true,
    emptyOutDir: true,
    rollupOptions: {
      input: './src/main.tsx',
      output: {
        entryFileNames: 'react-widget.js',
        assetFileNames: (assetInfo) => {
          if (assetInfo.name && assetInfo.name.endsWith('.css')) {
            return 'style.css'; // ✅ 항상 style.css로 고정
          }
          return '[name]-[hash][extname]'; // 그 외 파일은 기본
        },
      },
    },
  },
});

 

 

→ 빌드 후 항상 assets/style.css로 나오므로, PHP에 이렇게 고정 삽입 가능:

 

<link rel="stylesheet" href="/dist/assets/style.css">

 

 

 

이렇게 하면 FTP 기반 php 서버에 Vite + React + Typescript 프로젝트 생성 완료~!

 

 

메타 태그, CDN, <head>에 들어가는 HTML 요소는 React가 아닌 PHP 루트 파일 (예: index.php, main.php 등)에 넣어야 한다. React는 보통 특정 div(#root) 내부만 제어해서 <head> 태그나 <meta> 같은 요소는 서버사이드(PHP)가 렌더링한 HTML에서 직접 다뤄야 한다.

 

 

'TIL > React' 카테고리의 다른 글

FTP 기반 php 서버에 React 점진적 마이그레이션하기(1)  (2) 2025.05.21
[React] 함수 컴포넌트 vs 클래스 컴포넌트  (0) 2022.12.08
React에서 좋은 코드  (0) 2022.10.03
useMemo와 useCallback  (0) 2022.09.01
[React] Redux  (0) 2022.08.09