리브랜딩 마이그레이션의 마지막 20% — sed 일괄 치환과 조용히 사라진 온보딩 배너
MatchDa 개발기 시리즈 (3/3) 1편: 봇 차단 스크래핑 3단 폴백 · 2편: React 자동완성 칩 입력 직접 만들기 · 3편: 리브랜딩 마이그레이션에서 놓친 화면 찾기 (이 글)
리브랜딩은 메인 화면에서 끝나지 않는다
사이드 프로젝트 JobRadar를 MatchDa로 리브랜딩하면서 대시보드, 탐색, 워크스페이스 같은 메인 화면은 새 디자인으로 갈아탔다. 로고도 파비콘도 바꿨다. "다 됐다" 싶었는데, 실제로 서비스를 처음부터 눌러보니 아니었다.
- 로그인 페이지: 여전히 구 스타일 (Tailwind
zinc팔레트) - 온보딩 페이지: 구 전역 헤더를 그대로 쓰는 중
- 커버레터 모달, 맞춤 이력서 모달, JD 입력 모달… 공용 모달 10종: 전부 구 톤
리브랜딩의 앞 80%(메인 화면)는 재미있는데, 뒤 20%(모달·로그인·엣지 화면)는 지루해서 자꾸 밀린다. 그런데 유저는 그 20%를 매일 만난다. 이 글은 그 잔여분을 하루에 정리한 기록이고, 그 과정에서 발견한 더 심각한 문제 — 화면이 촌스러운 게 아니라 아예 사라진 문제 — 에 대한 이야기다.
Step 1: 현황 파악 — 구 팔레트 grep
구 디자인은 Tailwind 기본 zinc 팔레트, 새 디자인은 브랜드 hex 토큰(#046C4E 그린 계열 + #101828/#667085 그레이 계열)을 쓴다. 덕분에 잔여 화면 찾기는 grep 한 줄이면 된다.
grep -rl 'zinc-' src/components src/app --include='*.tsx'
이번에 걸린 게 17개 파일이었다. 구 스타일과 새 스타일이 문법적으로 구분되는 것(유틸 클래스명 vs 임의 값)의 부수 효과인데, 마이그레이션 진행률을 기계적으로 잴 수 있어서 생각보다 유용했다. "zinc가 0건이면 마이그레이션 끝"이라는 완료 조건이 생긴다.
Step 2: 기계적인 부분은 sed로 일괄 치환
모달 10종의 변경 대부분은 색 매핑이 1:1이다. 이런 건 손으로 고칠 이유가 없다.
| 구 (zinc) | 신 (브랜드 토큰) | 용도 |
|---|---|---|
text-zinc-900 | text-[#101828] | 제목 |
text-zinc-700 | text-[#344054] | 본문 |
text-zinc-500 | text-[#667085] | 보조 텍스트 |
border-zinc-200 | border-[#ECEEF0] | 테두리 |
bg-zinc-100 | bg-[#EEF1F3] | 배경 |
hover:bg-zinc-50 | hover:bg-[#F4F6F8] | hover 배경 |
sed -i '' \
-e 's/text-zinc-900/text-[#101828]/g' \
-e 's/text-zinc-700/text-[#344054]/g' \
-e 's/text-zinc-500/text-[#667085]/g' \
-e 's/border-zinc-200/border-[#ECEEF0]/g' \
-e 's/bg-zinc-100/bg-[#EEF1F3]/g' \
src/components/CoverLetterModal.tsx src/components/JdInputModal.tsx # ...
주의할 점 두 가지.
- 치환 후 반드시 diff를 눈으로 확인한다.
bg-zinc-100이 항상 같은 의미로 쓰였다는 보장이 없다 (선택 상태 배경 vs 비활성 배경처럼 맥락이 다르면 매핑도 달라야 한다) - 액센트 색(
blue-600→ 브랜드 그린#046C4E)은 일괄 치환하면 위험하다. 상태 색(에러 red, 경고 amber)과 액센트가 섞여 있어서 이 부분만 손으로 갔다
로그인 페이지처럼 구조 자체가 바뀌는 곳은 치환이 아니라 다시 스타일링했다. 예를 들어 탭 전환 버튼은 이렇게 바뀐다.
- <div className="flex gap-1 mb-6 bg-zinc-100 rounded-lg p-1">
+ <div className="flex gap-1 mb-6 bg-[#EEF1F3] rounded-[9px] p-[3px]">
Step 3 (반전): 스타일이 아니라 화면이 사라져 있었다
잔여 화면을 돌며 확인하다가 이상한 걸 발견했다. 신규 가입 유저가 온보딩으로 갈 방법이 없었다.
원인을 추적해 보니 이랬다.
- 구 버전에는 전역 레이아웃에 "프로필을 완성하세요" 배너가 있었다
- 리브랜딩하면서 메인 화면들이 새 MatchDa 셸(자체 사이드바 + Topbar)로 이동했다
- 새 셸은 구 전역 크롬을 렌더링하지 않는다 → 배너가 어디에도 안 보이게 됐다
- 스타일 마이그레이션 diff에는 아무 문제가 없다. 뭘 "고장낸" 게 아니라 렌더링 경로에서 조용히 빠진 것이라 어떤 에러도 없었다
컴파일 에러도, 런타임 에러도, 깨진 레이아웃도 없이 기능 하나가 사라졌다. 이런 유실은 코드 리뷰로는 잡기 어렵고, 신규 유저 시나리오를 처음부터 클릭해보는 것으로만 잡힌다.
복구는 새 셸의 대시보드에 배너를 다시 넣는 것으로 했다. 이번엔 전역이 아니라 대시보드 컴포넌트가 직접 소유하게 해서, 다음 개편 때 또 조용히 사라지지 않도록 했다.
{/* 온보딩 미완료 유저 → 프로필 완성 유도 (매칭·맞춤 이력서의 전제 조건) */}
{needsOnboarding && (
<a href="/onboarding"
className="mb-6 flex items-center justify-between gap-3 rounded-[14px]
border border-[#CEEBDC] bg-[#ECFDF3] px-5 py-4 hover:bg-[#DFF7E9]">
<div>
<div className="text-[14px] font-bold text-[#046C4E]">
✨ 프로필을 완성하고 나에게 꼭 맞는 채용 매칭을 받아보세요
</div>
<p className="mt-0.5 text-[13px] text-[#3D7A63]">
채팅으로 답하면 영어 이력서까지 자동으로 정리해 드려요. 3분이면 충분합니다.
</p>
</div>
<span className="whitespace-nowrap rounded-[9px] bg-[#046C4E] px-4 py-2
text-[13px] font-semibold text-white">완성하기 →</span>
</a>
)}
needsOnboarding은 서버 컴포넌트(page.tsx)에서 프로필 완성 여부를 조회해 prop으로 내려준다. 같은 맥락에서, 탐색 화면에서 공고를 추가한 직후 "워크스페이스에서 보기" 바로가기도 붙였다 — 기능을 화면 단위로 옮기다 보면 이런 화면 사이의 연결 동선이 가장 먼저 끊긴다.
트러블슈팅 체크리스트: 화면 단위 마이그레이션에서 잃어버리기 쉬운 것
- 전역 레이아웃(배너, 토스트, 공지)에 있던 요소가 새 셸에서도 렌더링되는가
- 신규 유저 최초 플로우(가입 → 온보딩 → 첫 액션)를 끝까지 클릭해봤는가
- 모달·다이얼로그처럼 라우트에 없는 화면도 새 톤인가 (grep으로 잔여 팔레트 확인)
- 화면 A → 화면 B로 넘어가던 동선(링크·리다이렉트)이 살아 있는가
정리
- 구/신 팔레트가 문법적으로 구분되면 grep이 마이그레이션 진행률 측정기가 된다 (
zinc-0건 = 완료) - 1:1 색 매핑은 sed 일괄 치환 + diff 육안 검수가 손 편집보다 빠르고 안전하다. 단, 액센트·상태 색은 손으로
- 리브랜딩에서 무서운 건 촌스러운 화면이 아니라 조용히 사라진 화면이다. 에러가 안 나는 유실은 신규 유저 시나리오 클릭 테스트로만 잡힌다
- 복구할 땐 위치만 되돌리지 말고, 소유권을 옮겨서(전역 → 해당 화면) 같은 사고가 재발하지 않게 한다
이것으로 하루치 커밋 4개를 풀어 쓴 시리즈를 마친다. 1편(스크래핑 폴백), 2편(칩 입력 컴포넌트)과 묶어 보면, 결국 하루의 절반은 기능을 만들고 나머지 절반은 "만든 줄 알았던 것"을 다시 확인하는 데 쓴 셈이다.
backtodev
40대 PM, 다시 개발자로 돌아갑니다. 실패하고 배우며 성장하는 기록.