개발 slecs

어드민 광고 유닛 폼 공용화와 recharts 차트 도입

목차

운영 화면 전반에 걸친 polish 작업과 공용 컴포넌트 정리, 그리고 recharts 도입까지 한 스프린트에 몰아서 처리했다.

왜 지금 이 작업이었나

기능 우선으로 달려온 어드민 화면은 언제나 "나중에 다듬자"는 부채를 달고 살기 마련이다. ad-units 관련 페이지와 audit-log 다이얼로그가 딱 그 상태였음. [id]/page.tsx, new/page.tsx 두 페이지가 각각 따로 구현된 폼 로직을 갖고 있었고, 컴포넌트 재사용 구조가 사실상 없었다. 팀원이 새 필드를 추가하려고 할 때마다 두 군데를 동시에 고쳐야 하는 상황 — 그게 반복되면 반드시 한쪽이 누락된다.

audit-log 쪽은 또 다른 문제였다. AuditDetailDialog.tsx가 덩치가 커지면서 "상세 정보를 보여주는 컴포넌트"인지 "데이터를 가공하는 컴포넌트"인지 경계가 흐릿해진 상태였고, 코드리뷰 때마다 "이거 나중에 쪼개야 하지 않나요?"라는 코멘트가 달렸다.

기능 추가가 잠깐 숨 고르는 타이밍이 생겼고, 이 기회를 놓치면 또 한 달은 밀릴 것 같아서 이번 스프린트에 한꺼번에 올렸다.

핵심 변경 — AdUnitFormEnhanced와 공용화

AdUnitFormEnhanced.tsx를 새로 만든 게 이번 작업의 중심이었다. 기존에 [id]/page.tsxnew/page.tsx가 각자 폼 상태를 관리하던 구조를

Before
├── [id]/page.tsx        자체  로직 포함
└── new/page.tsx         자체  로직 포함 (중복)

After
├── [id]/page.tsx        AdUnitFormEnhanced 사용
├── new/page.tsx         AdUnitFormEnhanced 사용
└── _components/
    └── AdUnitFormEnhanced.tsx   단일 진실 공급원

이렇게 정리했다. 두 페이지의 차이는 결국 "초기값이 있냐 없냐"와 "저장 API 엔드포인트가 다르냐" 정도인데, 그걸 props로 받는 구조로 만들면 충분했다.

항목 Before After
폼 필드 수정 시 영향 파일 2개 1개
신규 필드 추가 작업 두 군데 동시 수정 FormEnhanced 한 곳
페이지별 로직 차이 처리 직접 분기 props 주입

"Enhanced"라는 네이밍이 다소 작위적이긴 한데, 기존 AdUnitForm이 이미 쓰이고 있었고 점진적 교체를 하면서 이름 충돌을 피하기 위해 임시로 붙인 이름이다. 교체가 완료되면 접미사는 떼낼 예정.

recharts 도입

package.json에 recharts가 추가됐다. 어드민에서 차트가 필요한 시점이 온 거다.

운영 화면에서 차트를 도입할 때 항상 고민하는 선택지가 있다.

  • recharts — React 친화적, 컴포넌트 조합 방식, 번들 사이즈 있음
  • chart.js + react-chartjs-2 — 레퍼런스 많음, canvas 기반
  • visx — 커스터마이징 극대화, 러닝커브 높음
  • nivo — 예쁨, 옵션 방대하지만 무거움

어드민은 번들 사이즈 민감도가 유저향 서비스보다 낮고, 팀원 대부분이 JSX 조합 방식에 익숙하다는 점에서 recharts가 가장 무난한 선택이었다. 코드 리뷰 때 "왜 recharts냐"는 질문이 나올 걸 예상해서 PR 설명에 비교표를 미리 달았다.

// recharts 조합 방식  팀원이 읽기 편한 구조
<ResponsiveContainer width="100%" height={240}>
  <BarChart data={data}>
    <XAxis dataKey="date" />
    <YAxis />
    <Tooltip />
    <Bar dataKey="count" fill="#6366f1" radius={[4, 4, 0, 0]} />
  </BarChart>
</ResponsiveContainer>

선언형으로 조합하는 구조라 컴포넌트 경계가 명확하고, 팀원이 처음 봐도 어느 부분이 축이고 어느 부분이 실제 데이터인지 직관적으로 읽힌다.

AuditDetailDialog polish

audit-log의 AuditDetailDialog는 기능 추가보다 "보이는 것" 위주의 polish였다. 운영자가 실제로 쓰는 화면인데 정보 밀도가 너무 높거나 시각적 계층이 없으면 정작 중요한 정보를 빠르게 못 찾는다. 특히 diff성 데이터를 보여주는 다이얼로그는 before/after 구분이 시각적으로 명확해야 한다.

운영 화면 polish는 늘 후순위로 밀리는데, 이게 쌓이면 "이 화면 쓰기 불편하다"는 피드백이 슬그머니 쌓이다가 나중에 한꺼번에 터진다. 그래서 기능 숨 고르는 타이밍에 같이 처리하는 게 맞다고 생각한다.


이번 작업은 기능 티켓이 아니라 품질 티켓이었다. 외부에서 보이는 변화는 거의 없지만, 다음 기능 추가가 얼마나 빨리, 얼마나 안전하게 될 수 있느냐를 결정하는 게 이런 작업들이다. 팀 리드 입장에서 이런 리팩터링/polish 타이밍을 잡는 것도 결국 우선순위 결정의 일부다.

끝.


🛒 이 글과 어울리는 추천 상품

*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.

댓글 0

첫 댓글 달아줘.