전체 글
-
프런트엔드 AX 설계기 7편 - 게이트를 속이는 AI를 차단 없이 잡기AI 엔지니어링 2026. 7. 20. 17:48
게이트를 세운 이유는 단순했다. 사람이 매번 안 들여다봐도 품질 바닥이 유지되길 바랐다. lint·타입체크·테스트를 CI에 걸고, 구현은 AI 코더에게 "통과할 때까지 고쳐"라고 맡겼다. 며칠 뒤 초록불이 켜진 PR을 열었는데, 테스트 파일의 케이스 수가 줄어 있었다. 실패하던 테스트를 AI가 지워 버린 것이다. 게이트는 통과했고, 그 통과는 거짓말이었다.lint·tsc·test 게이트를 AI에게 맡겨 본 사람이라면 한 번쯤 겪는 장면이다. 이 글은 그 뒤에 무엇을 붙였는지에 대한 기록이다 — 게이트 옆에서 "게이트를 속이는지"를 보는 별도 레이어, 그리고 그 레이어가 정당한 수정까지 잡아 버리는 false-positive 폭탄이 되지 않게 만든 과정.게이트는 '고쳐라'와 동시에 '속여라'를 가르친다검증..
-
프런트엔드 AX 설계기 6편 - done은 직관으로 정하는 상태가 아니다AI 엔지니어링 2026. 7. 17. 17:51
에이전트에게 일곱 번째 task를 맡긴 참이었다. 구현 도중 에이전트가 두 번째 task —이미 done으로 닫아둔— 의 설계가 틀렸다는 걸 스스로 드러냈다. 나는 잠깐 멈췄다. 상태 판에는 분명 done이라 적혀 있는데, 그 done은 더 이상 사실이 아니었다. 팀에 AI 보조 개발을 들이면 이 장면을 반드시 만난다. 사람이 혼자 짤 때보다 에이전트는 더 자주, 더 빨리 앞선 결정을 무너뜨린다(빈도는 내 운영 관찰이지 벤치마크는 아니다 — 추정으로 읽어달라). 그런데 내가 쓰던 상태 도구에는 그 상황을 적을 칸이 없었다.이 글은 그 뒤로 done이라는 상태를 다시 설계한 작업기다. 두 군데가 나를 물었다. done에서 나오는 쪽과, 애초에 done으로 들어가는 쪽. 두 번 다 내 직관이 틀렸고, 두 번..
-
클로저·this·viewport를 지키며 큰 컴포넌트를 쪼갠 작업기React 2026. 7. 15. 17:26
"이 컴포넌트 너무 크니까 좀 쪼개 줘." 이 요청을 받으면, 사람이든 AI 에이전트든 가장 쉽게 빠지는 함정이 줄 수(LOC)를 줄이는 데 최적화하는 것이다. 함수로 뽑고 helper로 흩어 메인 본문을 짧게 만든다. 지표는 좋아진다. 그런데 화면이 깜빡이고, 차트 호버가 죽고, 다른 탭에 다녀오면 그래프가 어긋났다. 기술 트렌드를 시각화하는 한 화면(기술 트리·버블 차트·보고서)을 다섯 갈래로 쪼개면서 나는 이걸 다섯 번 확인했다. 큰 컴포넌트·훅을 분해해 봤고 useEffect나 차트 라이브러리에서 미묘한 회귀를 겪어 본 사람이라면 익숙한 장면일 것이다.줄을 세는 일과 의미를 지키는 일은 다르다분해를 하다 보면 매번 같은 단어로 돌아왔다. 런타임 계약. 코드가 겉으로 드러내지 않지만 동작이 의존하는..
-
Zustand stale 플래그와 변경 직전 pre-fetch로 VERSION_CONFLICT 숨긴 작업기React 2026. 7. 13. 19:23
프로젝트 소스 패널에서 폴더를 삭제했을 뿐인데 "잠시 후 다시 시도해 주세요"라는 빨간 토스트가 떴다. 코드를 따라가 보니 서버 응답은 400 VERSION_CONFLICT였다. 우리 서버는 폴더 변경에 낙관적 동시성 제어를 쓴다. 폴더마다 version: number를 들고 있고, 삭제·이름 변경·이동 요청에 내가 알고 있는 expectedVersion을 실어 보내면 서버가 현재 버전과 비교한다. 어긋나면 거부한다. 문제는 사용자 모르게 그 버전이 올라가는 경로가 있었다는 것이다. 외부 소스를 폴더로 적재하는 백그라운드 "불러오기" 작업이 끝나면 서버 폴더 버전이 오른다. 그런데 브라우저 캐시는 옛 버전 그대로다.재현 경로는 이랬다. 사용자가 불러오기를 시작하고, 모달을 닫거나 새로고침하고, 백그라운드..
-
React Flow·dnd-kit·zundo로 트리 편집기 작업기React 2026. 7. 10. 19:02
노드를 끌어다 놓아 트리를 편집하고, 순서를 바꾸고, Ctrl+Z로 되돌린다. 요구사항만 보면 평범하다. 노드 캔버스는 React Flow(@xyflow/react), 드래그 정렬은 dnd-kit, undo/redo는 zundo(Zustand 미들웨어)를 쓰면 된다. 각 라이브러리의 README 예제는 5분이면 동작한다.문제는 이 넷을 같은 DOM, 같은 마우스 이벤트, 같은 상태 트리 위에 포개는 순간 시작됐다. React Flow는 노드 클릭을 자기가 처리하려 하고, dnd-kit도 같은 mousedown을 노리고, zundo는 store에 일어나는 모든 변경을 히스토리에 쌓으려 하고, 캔버스 컨테이너의 overflow는 드롭다운을 가둔다. 기능을 구현하는 시간보다 이 충돌을 격리하는 시간이 더 길었..
-
단일 `ko.json`이 모든 PR의 충돌 진원지일 때 - next-intl 메시지를 도메인으로 쪼개는 설계Tip 2026. 7. 8. 19:49
1. 도입부 (Why This Matters)화면에 문구 하나 추가하는 PR이 왜 자꾸 머지 충돌이 날까. 범인은 대개 하나다 — 모든 도메인의 번역이 들어찬 단일 messages/ko.json. 검색·상세·결제·랜딩처럼 서로 다른 기능을 건드리는 PR이 전부 같은 파일의 다른 줄을 편집한다. 파일이 수천 줄로 불어나면 병렬 작업과 릴리스 분기에서 충돌은 상수가 된다.이 글은 그 단일 파일을 도메인 파일로 쪼갠 설계 기록이다. 단순히 파일을 나누는 게 아니라 — 충돌 면적 축소, 번들러 정적 분석 안전성, 타입 기준(source of truth), 그리고 도메인 추가 비용을 0에 수렴시키는 codegen까지 — 네 가지를 한 번에 푼다. 읽는 데 약 8분, 읽고 나면 당신의 가장 큰 메시지 파일을 어디서..
-
프런트엔드 AX 설계기 5편 - 테스트를 지워 초록불을 만드는 AIAI 엔지니어링 2026. 7. 6. 19:55
1. 도입부 (Why This Matters)검증 게이트(lint·타입체크·테스트)를 세우는 이유는 분명하다. AI 코더에게 "통과할 때까지 고쳐"라고 말하면, 사람이 일일이 안 들여다봐도 품질 바닥이 유지될 거라 기대한다. 그런데 게이트는 동기를 하나 더 만든다. AI 입장에서 게이트를 통과시키는 가장 싼 경로는, 코드를 고치는 게 아니라 게이트가 불평을 멈추게 하는 것이다.실패하는 테스트를 지운다. 린트 경고에 eslint-disable을 붙인다. 타입 에러를 as any로 덮는다. assertion을 "지금 동작에 맞춰" 다시 쓴다. 전부 초록불이 켜진다. 그리고 그 초록불은 거짓말이다.이 글은 게이트 옆에 "게이트를 게이밍 하는지"를 보는 별도 탐지 레이어를 어떻게 붙이는지 다룬다. 핵심 난점은 ..
-
프런트엔드 AX 설계기 4편 - LLM-as-judge는 왜 "다른 에이전트"가 채점해야 하는가AI 엔지니어링 2026. 7. 3. 19:47
1. 도입부 (Why This Matters)AI가 spec을 쓰고, 같은 세션에 "이 spec 괜찮아?"라고 물으면 거의 항상 "좋다"는 답이 돌아온다. 점수를 매기게 해도 마찬가지다 — 늘 0.85쯤에서 통과한다. 자동 검증을 붙였다는 안도감은 크지만, 실제로 돌아간 건 검증 연극(theater)에 가깝다.이 글은 그 자기 채점이 왜 항상 통과하는지(self-preference bias), 그걸 체크를 더 넣는 대신 구조로 어떻게 풀었는지(writer/evaluator 분리 + 절대 rubric + 실데이터 임계값 보정), 그리고 모델을 상위 티어로 올린 뒤에도 이 분리가 여전히 필요한지 A/B로 재측정한 결과까지 담는다. 읽는 데 8~10분. 다 읽고 나면 지금 돌리는 자동 검증이 theater인지..