유지보수 가능한 퍼블리싱 구조란 무엇인가
Article
프로젝트가 끝나고 6개월 뒤, 클라이언트가 수정을 요청합니다. 이때 코드를 열었을 때 구조가 바로 파악되느냐—이게 유지보수 가능한 구조의 기준입니다.
솔직히 저도 예전에 만든 코드를 3개월 뒤에 열어보고 "이게 뭐였지?" 했던 적이 있습니다. 그 경험 이후로 구조에 대한 생각이 좀 바뀌었습니다.
문제가 되는 패턴들
실제로 자주 보는 안 좋은 예시들입니다:
의미 없는 클래스 네이밍
/* 이건 3개월 뒤에 아무도 이해 못 한다 */
.box1 { padding: 20px; background: #fff; }
.box2 { padding: 16px; background: #f5f5f5; }
.box3 { padding: 20px; background: #fff; border: 1px solid #ddd; }
.tt { font-size: 18px; font-weight: bold; }
.desc { font-size: 14px; color: #666; }
.box1이 뭐고 .box2가 뭔지, 만든 사람도 한 달 뒤면 기억 못 합니다. .tt가 title인지 tooltip인지도 모호합니다.
BEM으로 바꾸면
/* 컴포넌트와 역할이 이름에 드러난다 */
.service-card { padding: 20px; background: #fff; }
.service-card__title { font-size: 18px; font-weight: bold; }
.service-card__desc { font-size: 14px; color: #666; }
.feature-card { padding: 16px; background: #f5f5f5; }
.feature-card__title { font-size: 18px; font-weight: bold; }
.feature-card__desc { font-size: 14px; color: #666; }
파일을 열자마자 "서비스 카드의 제목"인지 "기능 카드의 설명"인지 바로 알 수 있습니다.
Tailwind를 쓴다면
// 클래스 네이밍 고민 자체가 사라진다
function ServiceCard({ title, description }: ServiceCardProps) {
return (
<div className="bg-white p-5">
<h3 className="text-lg font-bold">{title}</h3>
<p className="mt-2 text-sm text-stone-600">{description}</p>
</div>
);
}
Tailwind의 장점은 유틸리티 클래스 자체가 스타일의 설명이라는 점입니다. text-lg font-bold를 보면 바로 "큰 볼드 텍스트"라는 걸 압니다. 커스텀 클래스 이름의 모호함이 없습니다.
같은 UI인데 마크업이 다른 문제
프로젝트 안에서 카드 UI가 5군데에 나온다고 치겠습니다. 근데 각각 마크업이 다릅니다:
<!-- 메인 페이지 -->
<div class="main-card">
<strong>제목</strong>
<span>설명</span>
</div>
<!-- 서브 페이지 -->
<article class="sub-item">
<h3 class="sub-item-title">제목</h3>
<p class="sub-item-text">설명</p>
</article>
<!-- 목록 페이지 -->
<li class="list-card">
<div class="list-card-head">제목</div>
<div class="list-card-body">설명</div>
</li>
같은 역할인데 태그도 다르고, 클래스 규칙도 다르고, 구조도 다릅니다. 나중에 "카드 디자인 전체를 바꿔주세요"라는 요청이 오면 5군데를 다 찾아서 각각 수정해야 합니다.
컴포넌트로 통일하면
// Card.tsx — 이 하나만 수정하면 전체가 바뀐다
interface CardProps {
title: string;
description: string;
variant?: "default" | "outlined";
}
export default function Card({ title, description, variant = "default" }: CardProps) {
return (
<article
className={`p-5 ${
variant === "outlined"
? "border border-stone-200 bg-white"
: "bg-stone-50"
}`}
>
<h3 className="text-base font-semibold text-stone-900">{title}</h3>
<p className="mt-2 text-sm leading-relaxed text-stone-600">{description}</p>
</article>
);
}
// 어디서든 이렇게 쓴다
<Card title="서비스 소개" description="..." />
<Card title="포트폴리오" description="..." variant="outlined" />
수정 사항이 생기면 Card.tsx 하나만 고치면 됩니다. 5군데를 돌아다닐 필요가 없습니다.
파일 구조도 중요합니다
# 이건 나중에 찾기 어렵다
styles/
style.css ← 모든 스타일이 여기에 1000줄
pages/
index.html
about.html
contact.html
# 이게 훨씬 낫다
components/
Card/
Card.tsx
Navigation/
Navigation.tsx
Footer/
Footer.tsx
app/
page.tsx
about/
page.tsx
contact/
page.tsx
컴포넌트별로 파일이 나뉘어 있으면, "카드 수정"이라는 요청이 왔을 때 Card.tsx만 열면 됩니다. 1000줄짜리 CSS 파일에서 .card를 검색하며 헤매지 않아도 됩니다.
결국 핵심은 하나입니다
예측 가능성.
파일을 열기 전에 "이건 아마 여기 있을 거다"라고 추측할 수 있는 구조. 코드를 읽기 전에 "이건 아마 이런 역할일 거다"라고 짐작할 수 있는 네이밍. 이게 유지보수 가능한 구조의 전부입니다.
고급 기술이 아닙니다. 처음에 규칙을 정하고, 끝까지 일관되게 지키는 것. 이 습관 하나가 프로젝트 6개월 뒤의 수정 비용을 결정합니다.
에이전시에서 다시 찾는 퍼블리셔는 대체로 이 부분이 강한 사람들이라는 걸, 여러 현장을 보면서 점점 더 확실하게 느낍니다.