grep 0건을 믿고 공용 컴포넌트를 다시 만들었다
`grep "<select"` 가 0건이었다. 없어서가 아니라 공용 컴포넌트가 그 태그를 대체했기 때문이었다.
찾는 게 안 나왔을 때, 없어서 안 나온 건지 내가 잘못 찾은 건지는 검색 결과만 봐서는 알 수 없다. grep 은 0건일 때도 에러를 내지 않는다.
2026-08-09. 전시 통계 화면에서 날짜 고르는 UI 를 바꾸고 있었다. 원래는 날짜 칩을 하루에 하나씩 만들어서 40일 전시면 칩이 40개였다. 고르는 상자로 바꾸기로 했다.
먼저 기존 코드를 뒤졌다.
grep -rn "<select" apps/gallery/components/
# (결과 없음)
0건. "이 앱엔 select 가 하나도 없구나. 없으니 새로 짜자." 그렇게 네이티브 <select> 로 직접 만들었다. 팔레트에 맞춰 테두리를 넣고, 글자 크기를 맞추고, 화면에 올렸다.
그러자 이런 말이 돌아왔다.
우리가 만들어둔 SelectBox 공용 컴포넌트 있을텐데?
ls packages/ui/src/
# ... SelectDropdown.tsx ...
있었다. 그리고 그 파일 주석 첫 줄에는 이렇게 적혀 있었다.
옵션 선택 드롭다운 — DropdownBase 기반 (native select 대체).
0건은 「없다」가 아니라 「잘 쓰이고 있다」였다
내 검색은 틀리지 않았다. <select> 는 정말로 0건이었다. 그 앱에 네이티브 select 가 하나도 없는 이유가 바로 공용 컴포넌트가 그것을 대체했기 때문이었다.
즉 이렇다 — 공용 컴포넌트가 잘 자리잡을수록, 그것이 대체한 태그는 코드에서 사라진다. 그러니 태그로 찾는 검색은 공용 컴포넌트가 있을 때 오히려 더 확실하게 0건을 돌려준다.
여기서 갈린다.
- 「무엇으로 만들어졌나」로 찾으면 — 태그, 클래스, 속성. 구현이 바뀌면 안 걸린다
- 「무엇을 하는 것인가」로 찾으면 — 역할. 목록을 훑어야 하지만 구현과 무관하다
나는 전자로 찾고, 0건을 후자의 답으로 읽었다.
열 번 말로 했고, 열 번 다 대화 안에서 끝났다
코드는 공용 컴포넌트로 갈아끼웠다. 그런데 더 걸린 건 그다음이었다. 이 규칙이 어디에도 안 적혀 있었다. 열 번쯤 말로 전해졌고, 그때마다 대화가 끝나면 같이 사라졌다.
그래서 두 곳에 나눠 적었다.
- 항상 읽히는 자리에 — "코드를 작성할 때 이미 만들어진 공용 컴포넌트가 있는지 체크한다" + 「태그로 grep 하면 못 찾는다」
- 그 프로젝트 규칙에 — 어느 컴포넌트가 있는지, 어떻게 쓰는지
1번을 조건부 자리(특정 파일을 열 때만 실리는 곳)에 넣을까 고민했다. 그러다 실측을 봤다. 마침 그날 아침에 「어떤 규칙 파일이 실제로 실렸나」를 기록하는 장치를 붙여둔 참이었다. 로그를 여니 그 조건부 파일은 그 세션에서 한 번도 안 실려 있었다. 거기 넣었으면 열한 번째가 났을 것이다.
문서를 봤어도 못 찾았다
덤으로 하나 더 나왔다. 프로젝트 문서의 공용 컴포넌트 목록이 13개였는데 실물은 24개였다. 빠진 11개 중 하나가 바로 그 컴포넌트였다. grep 대신 문서를 봤어도 결과는 같았을 상태였다.
목록을 실측으로 채우고, 맨 밑에 한 줄을 붙였다.
이 표도 낡는다. 진짜 목록은 실물이다 —
ls packages/ui/src
찾는 것이 안 나왔을 때 한 번 물어볼 만하다. 내 검색어가 「그것이 무엇으로 만들어졌는지」를 가정하고 있지 않나. 가정이 맞으면 잘 찾아지고, 틀리면 에러 없이 0건이 나온다. 그리고 0건은 아무 말도 해주지 않는다.