버전: 1.0
대상: 프론트엔드 개발자, 시스템 아키텍트
1. 개요 (Executive Summary)
본 문서는 기존에 작성된 HTML5 및 Vanilla JavaScript 기반의 사용자 인터페이스(UI)를, 이미 백엔드 통신과 인증(Auth) 체계가 구축된 React 애플리케이션에 통합하는 표준 절차를 기술합니다.
단순한 문법적 변환(Translation)이 아닌, React의 핵심 철학인 **선언적 프로그래밍(Declarative Programming)**과 **단방향 데이터 흐름(Unidirectional Data Flow)**에 맞춘 구조적 재설계(Re-engineering)를 목표로 합니다. 이를 통해 기존 시스템의 인증 상태와 API 클라이언트를 재사용하며 유지보수성을 극대화합니다.
2. 핵심 패러다임 전환 (Paradigm Shift)
성공적인 통합을 위해서는 개발자의 사고방식이 다음 두 가지 측면에서 전환되어야 합니다.
2.1 DOM 조작에서 상태(State) 관리로
기존 HTML5 코드는 document.getElementById 등을 통해 화면(DOM)을 직접 제어했습니다. React에서는 화면을 제어하지 않고 데이터(State)만 변경합니다. 화면 갱신은 React가 알아서 처리합니다.
- 기존: “버튼을 누르면 모달창
div의display를block으로 바꿔라.” - React: “모달의 상태(
isOpen)를true로 설정하라.” (화면은isOpen값에 따라 자동으로 렌더링됨)
2.2 전역 스코프에서 컴포넌트 스코프로
HTML 파일 전체에 흩어져 있던 스타일과 스크립트를 독립된 컴포넌트(Component) 단위로 캡슐화해야 합니다. 이는 기존 시스템의 사이드 이펙트(Side Effect)를 격리하는 데 필수적입니다.
3. 단계별 통합 절차 (Migration Phases)
Phase 1: 구조적 통합 (Structural Integration) – JSX 변환
기존 HTML 마크업을 React의 표준 문법인 JSX로 이식하는 단계입니다.
- 속성(Attribute) 표준화:
class$\rightarrow$className(필수: JS 예약어 충돌 방지)for$\rightarrow$htmlFor(라벨 연결)tabindex$\rightarrow$tabIndex(카멜 케이스 적용)
- 태그 종결(Self-closing):
<input>,<img>,<br>등 닫는 태그가 없는 요소는 반드시/>로 닫아야 합니다.
- 스타일 이식:
- 인라인 스타일:
style="display: none"$\rightarrow$style={{ display: 'none' }}(객체 형태) - 외부 CSS: 가급적 CSS Modules(
styles.module.css)나 CSS-in-JS로 변환하여 스타일 충돌을 방지합니다.
- 인라인 스타일:
Phase 2: 로직 재구현 (Logic Re-engineering) – Hooks 도입
기존 JavaScript의 명령형 로직을 React Hooks로 대체합니다.
| 기존 패턴 (Legacy) | React 패턴 (Modern) | 구현 가이드 |
변수 선언 (var, let) | State (useState) | UI 변경을 유발하는 데이터는 모두 useState로 관리합니다. |
DOM 접근 (querySelector) | Ref (useRef) | 꼭 필요한 경우(예: 포커스 제어, 캔버스)에만 useRef를 사용합니다. |
초기화 로직 (window.onload) | Effect (useEffect) | 컴포넌트 마운트 시점([] 의존성)에 useEffect를 실행합니다. |
이벤트 리스너 (onclick) | Handler Prop | JSX 내부에 onClick={handler} 형태로 직접 주입합니다. |
Phase 3: 아키텍처 연결 (Architectural Integration) – API & Auth
가장 중요한 단계입니다. 새로 만든 컴포넌트를 기존 React 앱의 생태계(API, 로그인 정보)에 연결합니다.
1. 인증 컨텍스트(Auth Context) 소비
기존 React 앱은 이미 로그인을 처리하는 AuthProvider나 전역 상태(Redux/Zustand)가 존재할 것입니다.
- 수정 위치: 신규 컴포넌트 내부
- 방법:
useContext또는 전역 상태 훅을 사용하여 현재 로그인한 사용자의 토큰(Token)이나 정보(User Profile)를 가져옵니다.
JavaScript
// 예시: 기존 앱의 Auth Context 사용
import { useAuth } from '../context/AuthContext'; // 기존 앱에 존재하는 훅
const NewComponent = () => {
const { user, token } = useAuth(); // 로그인 정보 획득
// ...
};
2. API 클라이언트 재사용
기존 앱에는 이미 axios 인스턴스나 fetch 래퍼(Wrapper)가 설정되어 있을 것입니다 (헤더에 토큰 자동 포함 등).
- 수정 위치: 데이터 요청 로직 (
useEffect또는 이벤트 핸들러) - 전략: 새로
fetch를 짜지 말고, 기존 앱의 API 유틸리티를 import하여 사용합니다.
JavaScript
// Bad: 직접 fetch 구현 (인증 토큰 누락 위험)
fetch('/api/data');
// Good: 기존 앱의 API 모듈 사용
import api from '../utils/api';
// ...
const loadData = async () => {
const response = await api.get('/data'); // 토큰 자동 처리됨
};
4. 실전 코드 비교 (Implementation Example)
이해를 돕기 위해 동일한 기능의 코드를 비교합니다.
A. 기존 (Legacy HTML/JS)
HTML
<div id="welcome-msg"></div>
<button onclick="loadData()">데이터 로드</button>
<script>
var token = localStorage.getItem('token'); // 보안 취약점: 직접 토큰 접근
function loadData() {
// 직접 DOM 조작
document.getElementById('welcome-msg').innerText = "로딩 중...";
fetch('/api/user?token=' + token)
.then(res => res.json())
.then(data => {
document.getElementById('welcome-msg').innerText = data.name;
});
}
</script>
B. React 통합 (Modern Integration)
JavaScript
// UserProfile.jsx
import React, { useState } from 'react';
import { useAuth } from '../hooks/useAuth'; // 1. 기존 인증 훅 사용
import api from '../services/api'; // 2. 기존 API 모듈 사용
const UserProfile = () => {
// 3. 상태 관리 (DOM 조작 대체)
const [message, setMessage] = useState('');
const { user } = useAuth(); // 현재 로그인 유저 정보
const handleLoadData = async () => {
setMessage("로딩 중...");
try {
// 4. 기존 설정된 API 클라이언트 사용 (토큰 자동 처리)
const response = await api.get('/user');
setMessage(response.data.name);
} catch (error) {
setMessage("오류 발생");
}
};
return (
<div>
{/* 5. 선언적 렌더링 */}
<div id="welcome-msg">{message}</div>
<button onClick={handleLoadData}>데이터 로드</button>
</div>
);
};
export default UserProfile;
5. 결론 및 제언
기존 HTML5 UI를 React 환경으로 가져오는 것은 단순한 ‘복사-붙여넣기’가 아닌 ‘재조립’ 과정입니다.
- UI:
className등 JSX 문법 준수. - Logic: DOM 조작 코드를 모두 제거하고
useState로 대체. - Integration: 독자적인 통신 코드를 작성하지 말고, 기존 React 앱의
Auth Hook과API Client를 반드시 재사용하십시오.
이 절차를 준수할 때, 레거시 코드는 현대적인 React 생태계 내에서 안전하고 효율적으로 작동하는 컴포넌트로 다시 태어날 것입니다.
답글 남기기