개발 slecs

partner-portal 등급 카드 빈 공간·깨진 아이콘 수정

목차

partner-portal의 myinfo 페이지에는 사용자 등급을 시각적으로 표시하는 카드 컴포넌트가 있다. 등급 아이콘, 등급명, 조건 같은 요소를 한 카드 안에 묶어 보여주는 구조인데, 특정 상황에서 아이콘이 깨지거나 카드 안에 원인 모를 빈 공간이 생기는 버그가 있었다.

변경 파일은 뷰/스타일 1개. 범위만 보면 소소하지만 이 류의 UI 버그는 원인이 단순해도 찾는 데 예상보다 시간이 걸리는 경우가 많다. 증상이 "전체 깨짐"이 아니라 "특정 상황에서만 이상하게 보임"이라서 재현 조건을 먼저 파악해야 하기 때문이다.

등급 카드 UI 버그가 잘 생기는 이유

등급 카드처럼 "조건부로 표시되는 요소"가 섞인 컴포넌트는 엣지 케이스가 잘 붙는다. 데이터가 항상 채워져 있다는 가정으로 마크업을 짜면, 값이 비거나 null이 내려오는 순간 레이아웃이 틀어진다.

빈 공간 문제는 보통 두 가지 중 하나다. 숨겨야 할 요소가 display: none 대신 높이 0짜리 상태로 DOM에 살아있는 경우, 또는 조건부 렌더링 블록이 빈 채로 컨테이너의 패딩/마진을 그대로 먹는 경우. 아이콘 깨짐은 또 다르다. 아이콘 폰트나 SVG 스프라이트를 쓸 때 클래스명이나 id가 잘못 바인딩되면 아이콘 자리에 빈 박스나 엉뚱한 문자가 나온다. 등급에 따라 다른 아이콘을 써야 하는데 기본값 처리가 빠져있으면 이렇게 나타난다.

두 증상이 같은 컴포넌트에 동시에 있던 건 우연이 아니고, 같은 엣지 케이스 - 특정 등급 상태에서 아이콘 데이터가 없거나 null인 경우 - 에서 파생된 거였다.

수정 패턴과 폴백 처리

비슷한 상황에서 자주 쓰는 패턴 두 가지.

조건부 렌더링 시 컨테이너 자체를 묶어버리기:

<!-- before: 요소만 숨기고 컨테이너는 살아있음 -->
<div class="icon-wrap">
  <img v-if="grade.icon" :src="grade.icon" />
</div>

<!-- after: 데이터가 없으면 컨테이너 자체를 없앰 -->
<div v-if="grade.icon" class="icon-wrap">
  <img :src="grade.icon" />
</div>

컨테이너가 살아있으면 .icon-wrap에 걸린 패딩/마진이 그대로 적용된다. 내부 요소가 숨겨져도 공간이 남는 원인이 여기 있었다.

아이콘 폴백 처리:

const GRADE_ICON_MAP = {
  gold:    'icon-grade-gold',
  silver:  'icon-grade-silver',
  bronze:  'icon-grade-bronze',
  default: 'icon-grade-none',  // 빠뜨리기 쉬운 부분
}

function getGradeIcon(grade) {
  return GRADE_ICON_MAP[grade] ?? GRADE_ICON_MAP.default
}

null 병합이나 fallback을 일관되게 쓰는 건 작은 습관처럼 보이지만, 있냐 없냐로 몇 달 뒤 "이상하게 나온다"는 제보가 오냐 안 오냐가 갈린다. 등급 데이터가 서버에서 예상과 다른 값으로 내려올 때 클라이언트가 조용히 깨지지 않으려면 방어 코드가 있어야 한다.

수정 후 확인 방식

버그를 고친 다음 바로 PR을 올리는 게 아니라, 수정한 케이스를 직접 재현해서 눈으로 확인했다. 테스트 코드가 있으면 좋지만 UI 버그는 실제 화면을 직접 보는 게 최종 검증이다.

이번엔 추가로, 카드에 표시되는 수치가 관련 다른 화면의 수치와 일치하는지 cross-check했다. UI 픽스 하나 넣으면서 숫자 표시 로직을 건드리는 경우는 없었지만, 버그 수정을 명분으로 주변 코드를 같이 훑으면 맥락이 보이고 놓쳤던 게 눈에 들어올 때가 있다.

확인 항목 이유
같은 로직이 다른 경로에도 있는지 중복 구현은 한 쪽만 고치면 나중에 또 터짐
수정이 정상 케이스를 깨뜨리지 않는지 회귀 방지 - 수정 전 동작은 유지돼야 함
해당 화면에서 실제 동작 직접 확인 코드 리뷰만으론 UI 버그를 잡기 어려움
관련 화면과 숫자 cross-check 픽스 과정에서 새 버그가 끼어드는 경우 조기 발견

엣지 케이스를 꼼꼼히 따지는 게 귀찮아 보여도, 같은 버그로 다시 오는 시간 비용이 훨씬 크다. 특히 등급이나 포인트 같은 도메인은 숫자 하나, 아이콘 하나가 틀려도 사용자 신뢰에 직결되기 때문에 "대충 맞는 것 같은데"로 넘기는 건 안 된다.

커밋과 작업 기록에 대해

이번 수정은 파일 하나, 커밋도 하나지만, 규모가 있는 작업을 할 때는 커밋을 논리 단위로 잘게 쪼개는 습관을 유지하고 있다. 뭔가 이상해졌을 때 git bisect이나 커밋 단위 롤백이 실제로 쓸모있으려면, 커밋이 "오늘 한 거 전부"가 아니라 독립된 논리 단위여야 한다. 묶어서 넣으면 롤백 단위가 너무 커져서 실용성이 없어진다.

커밋 메시지도 "무엇을 바꿨다"보다 "왜 바꿨다"를 담으려 한다. 코드를 보면 뭘 바꿨는지는 알 수 있지만, 왜 바꿨는지는 메시지에 없으면 6개월 뒤엔 아무도 모른다. 그 6개월 뒤가 나일 확률이 꽤 된다.

partner-portal 같은 사내 서비스는 기능 하나가 SQL 집계, 상태 로직, 예외 처리, 화면 렌더링, 권한 체크가 다 얽혀 있다. 어느 하나가 엣지 케이스를 놓치면 특정 사용자에게만 이상한 화면이 나오는 조용한 버그가 된다. 조용하다는 게 더 문제다 - 제보가 늦게 오거나 아예 안 올 수 있어서, 모르는 채로 방치되는 시간이 길어진다.

작업 전 현재 동작을 스크린샷이나 수치로 기록해두는 것도 이 흐름의 연장이다. 수정 후 "전에 어떻게 보였더라"를 기억으로 비교하는 건 불확실하고, 기록이 있으면 비교가 명확해진다.

댓글 0

첫 댓글 달아줘.