대니
danny's blog@dannywon_dev
발행 75 · 대기 91

1인 개발자. 클로드 코드를 팀처럼 굴린다. 매일 겪은 것만 쓴다.

버그와 함정

다크모드 bg-white — 흰색의 반대는 검정이 아니었다

하드코딩된 흰색 26곳을 다 고쳤는데 다음 날 흰 사각형이 남아 있었다

하드코딩된 색을 전부 훑어서 고쳤는데, 다음 날 화면에 흰 사각형이 하나 떠 있었다.

앱을 밝은 화면에서 어두운 화면으로 갈아엎었다. 방식은 「이름은 그대로, 값만 뒤집기」였다.

        밝은 판      어두운 판
배경    #FAF9F5  →  #212121
글자    #333333  →  #FFFFFF

색마다 이름표(토큰)를 붙여놨으니 이름을 쓴 자리는 전부 알아서 따라온다. 문제는 이름 대신 색을 직접 박아둔 자리였다. 그런 데가 스물여섯 곳이었고 하나씩 찾아 고쳤다.

남아 있던 흰 사각형은 갤러리가 관람객 문의에 보낸 답장이었다.

bg-white  +  text-primary

text-primary 는 이름표라 어두운 판에서 흰색이 됐다. bg-white 는 이름표가 아니라 그냥 흰색이었다. 흰 바탕에 흰 글씨. 답장 내용이 통째로 안 보였다.

원인은 1초, 대체할 색은 20분

처음엔 당연히 검정이라고 생각했다. 흰색의 반대니까. 넣어보니 이상했다. 말풍선이 배경에 녹아서 테두리만 남은 빈 상자가 됐다.

그다음엔 그 판에서 제일 밝은 색을 넣어봤다. 이번엔 너무 튀었다. 그리고 옆에 있는 AI 답변 말풍선과 구분이 안 됐다.

여기서 내가 뭘 잘못 묻고 있었는지 알았다. 나는 계속 「흰색을 무슨 색으로 바꾸지」 를 묻고 있었다. 물어야 했던 건 「여기서 흰색이 무슨 일을 하고 있었지」 였다.

답은 「배경보다 한 단계 떠 보이게 하기」였다. 강조는 애초에 테두리가 맡고 있었고, 흰색은 그냥 면을 살짝 띄우는 일만 했다. 그 일을 어두운 판에서 하는 색은 배경보다 한 톤 밝은 회색이었다. 검정도 아니고 제일 밝은 색도 아니었다.

배경        #212121
AI 말풍선   #2A2A2A   ← 한 단계
갤러리 답장 #343434   ← 두 단계 (여기)

색을 옮길 때 옮겨야 하는 건 값이 아니라 역할이다. 값만 보면 반대말을 찾게 되는데, 반대말이 그 역할을 한다는 보장이 전혀 없다.

검색에 안 걸린 흰색

같은 눈으로 나머지를 다시 보니 하나가 더 걸렸다. 버튼 안에서 도는 로딩 뱅글이였다.

<LoadingSpinner color="white" />

이건 스물여섯 곳을 훑을 때 안 걸렸다. bg-white 같은 게 아니라 옵션 이름이라서다. 검색에도 안 걸리고 눈으로 봐도 이상하지 않다. color="white" 는 그 자체로 완결된 문장처럼 보인다.

그런데 그 버튼은 어두운 판에서 흰 버튼이 된다. 흰 버튼 위에 흰 뱅글이. 눌러도 아무 일이 안 일어나는 것처럼 보여서 사용자는 한 번 더 누른다.

더 고약한 건 바로 옆이었다.

버튼 글자   text-background   ← 이름표 (제대로 뒤집힌다)
뱅글이      color="white"     ← 색 이름 (안 뒤집힌다)

같은 버튼 안에서 짝이 어긋나 있었는데 아무도 못 봤다. 짝 검사는 「이름표끼리 맞나」를 보는데, 한쪽이 아예 이름표가 아니면 검사 대상에서 빠진다.

그래서 뭘 바꿨나

옵션 이름을 역할로 바꿨다. color="white" 가 아니라 color="background". 「흰색으로 그려라」가 아니라 「채워진 버튼 위에 놓는 것으로 그려라」.

규칙 두 줄이 남았다.

  • 색을 옮길 땐 값이 아니라 그 색이 하던 일을 옮긴다. 반대말을 찾지 말고 역할을 찾는다.
  • 옵션 이름에 색을 박지 않는다. 이름이 「흰색」이면 판이 뒤집혀도 그 이름은 여전히 옳아 보인다. 틀렸다는 신호가 이름 안에 없다.

두 번째가 더 무섭다. 첫 번째는 화면을 보면 걸리는데, 두 번째는 찾는 방법 자체가 안 걸린다. 하드코딩된 색을 훑는 검색으로는 영원히 안 나온다.

← 목록으로