HTML vs TSX: 에이전시 납품 시나리오 비교
Article
에이전시에서 UI 납품 방식이 바뀌면 실제로 어떤 차이가 생길까요?
말로만 설명하면 와닿지 않으니, 같은 컴포넌트를 두 가지 방식으로 만들어봤습니다. 하나는 기존 HTML/CSS 방식, 다른 하나는 TSX 컴포넌트 방식입니다.
시나리오 1: 블로그 포스트 카드
디자인 시안 기준:
- 카드 테두리 + 패딩
- 제목, 날짜, 설명 텍스트
- 태그 뱃지 (여러 개)
- 호버 시 테두리 색상 변경
기존 방식: HTML + CSS 분리 납품
<!-- post-card.html -->
<article class="post-card">
<h2 class="post-card__title">Next.js로 포트폴리오 만들기</h2>
<p class="post-card__date">2026-02-24</p>
<p class="post-card__desc">
웹퍼블리셔가 Next.js 환경에서 포트폴리오 사이트를 구축하는 전 과정
</p>
<ul class="post-card__tags">
<li class="post-card__tag">Next.js</li>
<li class="post-card__tag">웹퍼블리셔</li>
</ul>
</article>
/* post-card.css */
.post-card {
border: 1px solid #e7e5e4;
background-color: #fff;
padding: 20px;
transition: border-color 0.2s;
}
.post-card:hover {
border-color: #a8a29e;
}
.post-card__title {
font-size: 1rem;
font-weight: 700;
color: #1c1917;
}
.post-card__date {
font-size: 0.75rem;
color: #78716c;
margin-top: 4px;
}
.post-card__desc {
font-size: 0.875rem;
color: #57534e;
margin-top: 8px;
line-height: 1.6;
}
.post-card__tags {
display: flex;
gap: 6px;
margin-top: 12px;
list-style: none;
}
.post-card__tag {
background-color: #f5f5f4;
color: #78716c;
font-size: 0.75rem;
font-weight: 500;
padding: 2px 8px;
}
개발자가 이걸 받으면 어떻게 될까요? HTML 보면서 JSX 문법으로 다시 쓰고, CSS를 Tailwind 클래스나 CSS Module로 변환하고, 데이터를 props로 받게 구조도 바꿔야 합니다. 이 작업만 30분~1시간이 걸립니다.
TSX 컴포넌트 방식
// PostCard.tsx
interface PostCardProps {
title: string;
date: string;
description: string;
tags: string[];
}
export default function PostCard({ title, date, description, tags }: PostCardProps) {
return (
<article className="border border-stone-200 bg-white p-5 transition-colors hover:border-stone-400">
<h2 className="text-base font-bold text-stone-900">{title}</h2>
<p className="mt-1 text-xs text-stone-400">{date}</p>
<p className="mt-2 text-sm leading-relaxed text-stone-600">{description}</p>
<ul className="mt-3 flex flex-wrap gap-1.5">
{tags.map((tag) => (
<li key={tag} className="bg-stone-100 px-2 py-0.5 text-xs font-medium text-stone-500">
{tag}
</li>
))}
</ul>
</article>
);
}
개발자가 이걸 받으면? props 타입 확인하고 데이터 연결만 하면 됩니다. 마크업 재작성이 필요 없습니다. 5분이면 끝나요.
시나리오 2: 네비게이션
에이전시 프로젝트에서 가장 먼저 만드는 컴포넌트 중 하나입니다. 이것도 비교해볼게요.
HTML 방식
<nav class="gnb">
<a href="/" class="gnb__logo">StudioX</a>
<ul class="gnb__menu">
<li><a href="/about" class="gnb__link gnb__link--active">About</a></li>
<li><a href="/works" class="gnb__link">Works</a></li>
<li><a href="/contact" class="gnb__link">Contact</a></li>
</ul>
</nav>
문제가 보이시나요? gnb__link--active 클래스가 하드코딩 되어 있습니다. 어떤 페이지에서 어떤 메뉴가 활성화되는지, 개발자가 직접 로직을 짜야 합니다.
TSX 방식
// Navigation.tsx
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
const menus = [
{ label: "About", href: "/about" },
{ label: "Works", href: "/works" },
{ label: "Contact", href: "/contact" },
];
export default function Navigation() {
const pathname = usePathname();
return (
<nav className="flex items-center justify-between px-6 py-4">
<Link href="/" className="text-lg font-bold text-stone-900">
StudioX
</Link>
<ul className="flex gap-6">
{menus.map((menu) => (
<li key={menu.href}>
<Link
href={menu.href}
className={`text-sm transition-colors ${
pathname === menu.href
? "font-semibold text-stone-900"
: "text-stone-500 hover:text-stone-700"
}`}
>
{menu.label}
</Link>
</li>
))}
</ul>
</nav>
);
}
메뉴 데이터가 배열로 분리돼 있고, 현재 경로에 따라 활성화 스타일이 자동으로 적용됩니다. 개발자가 받아서 추가로 손댈 게 거의 없습니다.
차이 요약
| 항목 | HTML 납품 | TSX 납품 |
|---|---|---|
| 개발자 추가 작업 | HTML → JSX 재작성 필요 | 데이터 연결만 |
| 파일 수 | HTML + CSS 분리 | TSX 단일 파일 |
| 재사용성 | 없음 (정적 HTML) | props로 즉시 재사용 |
| 동적 처리 | 개발자가 로직 추가 | 컴포넌트 안에 포함 |
| 유지보수 | 마크업·스타일 별도 수정 | 컴포넌트 단위 관리 |
퍼블리셔가 TSX로 넘어가려면
HTML을 이미 잘 다루고 있다면, TSX는 생각보다 빨리 익힐 수 있습니다. 핵심 차이는 몇 가지 안 됩니다:
// 1. class → className
<div className="container">
// 2. 단독 태그는 자기닫힘
<img src="/logo.png" alt="로고" />
<br />
// 3. 동적 데이터는 {} 안에
<h1>{title}</h1>
<p>{description}</p>
// 4. 리스트는 map()
{items.map((item) => (
<li key={item.id}>{item.name}</li>
))}
// 5. 조건부 렌더링
{isVisible && <div>보이는 내용</div>}
{status === "error" ? <ErrorMsg /> : <Content />}
이 다섯 가지 패턴만 손에 익으면 대부분의 UI 컴포넌트를 TSX로 만들 수 있습니다. 나머지는 실무를 하면서 자연스럽게 붙습니다.
솔직히 처음에는 className이 어색하고, map() 안에서 JSX를 리턴하는 게 이상하게 느껴질 수 있습니다. 근데 2주만 연습하면 오히려 HTML로 돌아가는 게 불편해집니다. 그 정도로 금방 적응되는 문법이에요.