문서 작업 가이드
레거시 오류를 옮기지 않고 HTML 조각을 React JSX로 변환하기
쓸모 있는 HTML 조각을 분리하고 JSX 구문으로 변환한 뒤 실행 코드와 파서 변경을 검토하고 실제 React 컴포넌트로 통합·검증합니다.
작성 및 검수 SimpleWebUtils게시일: 검토일:
이 작업 흐름을 검증한 방법
마크업 변환 워크벤치에서 다음 가이드 픽스처로 검증을 시작했습니다: “전역 클릭 핸들러를 남기지 않고 프로필 이름 필드 이관”. “하나의 일관된 조각과 의존성 분리”부터 “실행 코드를 보존하는 데서 멈추지 말고 재설계”까지 실행해 생성 결과를 기대값과 대조했습니다. 별도 한계 검토에는 “내보낸 전체 페이지를 한 번에 이관하기”, “Babel에서 유효한 표현식을 작동하는 컴포넌트로 오해하기” 항목을 사용했습니다.
JSX는 className과 htmlFor를 사용하고 label-input 관계를 유지했으며, 전역 onclick 핸들러는 컴포넌트 소유 callback으로 바꿔야 할 항목으로 드러냈습니다.
문제 상황
정적 HTML은 전역 script, DOM ID, 문자열 이벤트, 문서 메타데이터, 상대 에셋 경로, 다른 곳에서 불러온 CSS에 의존하는 경우가 많습니다. 기계적인 변환은 속성 이름을 바꾸고 유효한 JSX를 만들면서도 위험 URL, 오래된 동작, 접근할 수 없는 label, React 안에서 더 이상 존재하지 않는 전제를 그대로 남길 수 있습니다. 전체 페이지 HTML은 컴포넌트 조각과 다른 문서 파싱 규칙도 적용받습니다. 따라서 안전한 이관에는 구문 변환과 명시적인 동작·통합 검토가 모두 필요합니다.
공식 출처와 표준
다음 공식 문서는 이 작업 흐름에서 다루는 형식과 보안 경계의 기준입니다. 도구별 실행 검증은 위에 별도로 기록합니다.
- HTML Living Standard
WHATWG
이럴 때 사용하세요
- 디자이너나 프로토타입에서 검토된 HTML 카드, 폼, 내비게이션 항목, 표, SVG를 React로 옮길 때
- 레거시 페이지를 raw innerHTML로 삽입하지 않고 상호작용 단위로 이관할 때
- HTML 속성, 인라인 style, SVG 속성, 이벤트 문자열을 JSX 결과와 비교할 때
- 테스트나 문서에 작은 HTML 기반의 문법 검증 JSX fixture가 필요할 때
단계
- 1단계
하나의 일관된 조각과 의존성 분리
한 가지 사용자 작업을 해결하는 데 필요한 가장 작은 영역을 선택합니다. 현재 의존하는 CSS selector, 이미지·폰트 파일, 폼 전송 대상, 링크, 키보드 동작, 포커스 순서, 전역 변수, script를 기록합니다. 프레임워크 메타데이터를 컴포넌트 밖에서 별도로 옮기는 경우가 아니라면 doctype, html, head, body 래퍼를 제거합니다. 비밀값, 고객 데이터, 내부 URL, 운영 식별자는 의도적인 테스트 값으로 바꿉니다.
- 2단계
구문 변경 전 기대 동작 기록
기존 페이지나 통제된 fixture에서 원본 조각을 엽니다. 클릭, submit, 키보드 실행, 잘못된 입력, 로딩 실패, 좁은 화면에서 어떤 일이 일어나는지 기록하고 accessible name과 label 연결도 확인합니다. 대표 스크린샷이나 assertion을 남기세요. 기준선이 없으면 문법상 유효한 JSX가 동작을 잃어도 신뢰성 있게 비교할 수 없습니다.
- 3단계
변환 후 정규화된 트리 비교
마크업 변환 워크벤치에서 HTML → JSX 탭을 열어 집중된 조각을 변환하고 중첩, 텍스트, className, htmlFor, data·aria 속성, style 값, SVG 속성, 자체 닫힘 요소를 비교합니다. HTML 파싱은 잘못 닫힌 태그를 보정하고 암시적 table 요소를 추가하거나 문서 수준 콘텐츠를 재배치할 수 있습니다. 크기, 깊이, template, 구문 오류가 있으면 출력만 우회 수정하지 말고 원인을 해결합니다.
- 4단계
실행 코드를 보존하는 데서 멈추지 말고 재설계
onclick 계열 핸들러, script 요소, srcDoc, javascript URL, 실행 가능한 style 값 경고를 필수 검토 작업으로 취급합니다. 전역 변수와 DOM 조회를 props, state, ref, effect, 이름 있는 이벤트 핸들러로 교체합니다. 안전한 앱 내비게이션과 신뢰할 수 있는 URL만 사용하세요. 중첩 HTML이 정말 필요하다면 신뢰 경계에서 정제하고 raw 렌더링이 필요한 이유를 문서화합니다.
- 5단계
실제 컴포넌트 계약 구성
JSX 표현식을 이름 있는 컴포넌트에 넣습니다. props와 TypeScript 타입을 정의하고 에셋을 import하며 프로젝트의 스타일 체계로 규칙을 옮기고, 입력을 controlled 또는 uncontrolled로 사용할지 결정합니다. 의미 있는 요소, label, 대체 텍스트, 제목 순서, 키보드 동작을 보존하세요. 모든 정적 값을 state로 바꾸거나 일반 CSS가 더 적절한데도 인라인 style을 유지하지 않습니다.
- 6단계
대상 프로젝트에서 최종 검증
formatter, linter, type checker, 단위·상호작용 테스트, 프로덕션 빌드를 실행합니다. 데스크톱과 390px 모바일에서 기준선과 비교하고 키보드 전용 탐색과 접근성 스캐너도 사용합니다. 콘솔과 네트워크 활동, 에셋 실패, 폼 오류를 테스트하고 신뢰할 수 없는 코드나 URL이 추가되지 않았는지 확인한 뒤 이관을 병합합니다.
예시
전역 클릭 핸들러를 남기지 않고 프로필 이름 필드 이관
입력
<section class="profile-card"><label for="name">이름</label><input id="name" value="가람"><button onclick="saveProfile()">저장</button></section>출력
class와 for 구문을 변환한 뒤 보존된 onClick 본문을 컴포넌트가 소유한 handleSave 함수로 교체합니다. input을 value와 onChange로 제어할지 defaultValue로 둘지 결정하고 save callback을 prop으로 정의한 뒤 label 포커스, 키보드 실행, 검증, 실패 피드백을 테스트합니다.흔한 실수
내보낸 전체 페이지를 한 번에 이관하기
전체 문서는 메타데이터, script, style, 내비게이션, 서로 다른 작업을 섞습니다. 하나의 일관된 조각씩 변환해야 파서 정규화와 동작 변화를 검토할 수 있습니다.
Babel에서 유효한 표현식을 작동하는 컴포넌트로 오해하기
문법 검증은 누락된 식별자, import, 에셋, hook, 타입, CSS, 서버·클라이언트 경계, 앱 동작을 해결하지 않습니다. 대상 빌드와 테스트가 최종 기준입니다.
javascript URL이나 raw 중첩 HTML 유지하기
보존된 값이 승인된 값은 아닙니다. 실행 URL을 신뢰할 수 있는 내비게이션으로 교체하고 srcDoc·raw HTML은 별도의 정제와 Content Security Policy 결정으로 다룹니다.
레거시 이벤트 문자열을 불투명한 인라인 콜백으로 남기기
생성된 화살표 함수도 전역 값이나 DOM 상태에 의존할 수 있습니다. 의미 있는 동작을 명시적 입력, 오류 처리, 테스트가 있는 이름 있는 함수로 옮기세요.
모양만 비교하고 의미 구조를 확인하지 않기
시각적으로 비슷해도 label, 제목 순서, 포커스, 키보드 제어, 폼 검증, 오류 알림이 사라질 수 있습니다. 스크린샷과 함께 접근성 트리와 상호작용을 비교합니다.
자주 묻는 질문
왜 HTML 파일 전체가 아니라 조각을 변환해야 하나요?
컴포넌트는 보통 하나의 작업을 소유하며 문서 래퍼나 관련 없는 메타데이터를 포함하지 않습니다. 작은 조각은 파서 변경, 의존성, 동작, 검토 범위를 관찰하기 쉽습니다.
생성된 이벤트 핸들러를 유지해도 되나요?
이관 근거로만 사용하세요. 전역 호출, this 참조, return false 동작, DOM 조회를 명시적인 React 컴포넌트 로직으로 다시 작성하고 각 상호작용을 테스트합니다.
인라인 style과 style 요소는 어떻게 해야 하나요?
변환된 값을 검토한 뒤 안정적인 규칙은 대상 프로젝트의 CSS, module, 디자인 시스템으로 옮깁니다. 정말 동적인 값에만 인라인 객체를 사용하는 편이 좋습니다.
신뢰할 수 없는 CMS HTML에 출력을 사용할 수 있나요?
보안 경계로 사용할 수 없습니다. 변환은 원본 의미를 보존해 실행 코드나 URL이 남을 수 있습니다. 신뢰할 수 없는 콘텐츠에는 별도의 sanitizer, URL 정책, CSP, 렌더링 설계가 필요합니다.
마이그레이션 완료를 어떻게 판단하나요?
JSX 파싱, 프로젝트 빌드, lint·타입 검사, 대표 동작의 기준선 일치, 접근성·모바일 검사, 예상된 네트워크 요청을 모두 확인하고 모든 실행 코드 경고에 해결 근거가 있을 때 완료로 판단합니다.