JOURNAL ENTRY Engineering

자동 테스트가 통과해도 디자인은 통과한 게 아니었다

빌드와 브라우저 테스트가 모두 통과한 UI가 실제로는 부자연스러웠다. 기술적 correctness와 perceptual coherence를 분리하고, AI의 첫 구현과 Human review 사이에 self-review를 넣게 된 과정을 정리한다.

UI 작업에서 테스트가 모두 통과하면 꽤 안심하게 된다.

타입 체크가 통과했고, 빌드가 성공했고, 브라우저 smoke test도 문제없고, 여러 viewport에서 overflow도 없었다. 스크롤 상태 전환도 예상한 값으로 바뀌었다.

그런데 실제 화면을 손으로 써보니 이상했다.

움직임이 지나치게 붙어 있었고, 세로로 스크롤하는데 가로 rail이 따로 움직였고, mobile에서는 화면이 더 불안정하게 느껴졌다.

기계가 확인한 동작은 맞았다. 사용 경험은 아니었다.

이 사건 이후 디자인 작업에서 다음 두 문장을 분리해서 보게 됐다.

BEHAVIORAL TEST PASS
!= MOTION UX PASS

DETERMINISTIC ACTIVE STATE
!= PERCEPTUALLY NATURAL INTERACTION

모든 assertion은 맞았는데 화면은 왜 이상했을까

Portfolio의 scroll interaction을 손보던 작업이었다.

수정에는 active section 계산, sticky behavior, mobile state readout, horizontal centering 같은 요소가 포함되어 있었다. 자동 검증도 꽤 넓게 걸려 있었다.

typecheck
lint
build
browser smoke
1440 / 360 / 390 / 412 viewport check
scroll down / up transition
reduced motion
hero overlap
mobile positioning

기계적으로 묻기 좋은 질문은 대부분 확인했다.

active 값이 바뀌는가?
요소가 예상 위치에 남는가?
overflow가 발생하는가?
scroll 방향이 바뀌어도 state가 갱신되는가?

문제는 내가 실제 화면에서 불편하다고 느낀 질문들이 전혀 다른 종류였다는 것이다.

왜 여기에서 갑자기 붙는가?
왜 이 요소가 화면 공간을 계속 점유하는가?
왜 세로 scroll 중 가로 요소가 별도로 움직이는가?
왜 content와 state 변화가 반 박자 어긋나 보이는가?

첫 번째 묶음은 assertion으로 만들기 쉽다.

두 번째 묶음은 perceptual coherence에 가깝다.

그래서 디자인 acceptance는 단순히 테스트 개수를 늘리는 문제로 끝나지 않았다.

TECHNICAL CORRECTNESS
+
PERCEPTUAL COHERENCE
=
DESIGN REVIEW CANDIDATE

문제를 고치려다 solution shape를 너무 빨리 고정했다

이 작업에서 더 흥미로웠던 부분은 prompt 자체였다.

scope를 좁히기 위해 나는 꽤 구체적인 구현 방향을 제시했다.

예를 들면 sticky를 복구한다거나, viewport의 특정 지점을 activation line으로 사용한다거나, active item을 자동으로 가운데에 보이게 하는 식이었다.

이 정도로 구체적으로 주면 AI executor는 구현하기 편하다.

하지만 그만큼 원래 문제를 다시 해석할 필요도 줄어든다.

"따라와야 한다"
→ sticky

"현재 section이 보여야 한다"
→ fixed viewport ratio

"active item이 보여야 한다"
→ horizontal auto-scroll

각각은 설명 가능하고 테스트 가능한 구현이었다.

그런데 합쳐놓으니 경험이 부자연스러웠다.

여기서 디자인 prompt에 대해 한 가지 원칙이 생겼다.

DESIGN / MOTION PROMPT SHOULD FIX
- intent
- constraints
- observed failure
- acceptance experience

SHOULD NOT PREMATURELY FIX
- exact CSS mechanism
- arbitrary offset
- arbitrary viewport ratio
- unnecessary auto-motion

AI에게 구체적으로 지시하는 것이 항상 좋은 것은 아니다.

구현 방법까지 너무 빨리 잠가버리면 AI는 UX 문제를 해석하는 대신 체크리스트를 코드로 번역하게 된다.

더 큰 병목은 Human review가 너무 일찍 시작된다는 것이었다

처음에는 문제를 AI의 디자인 능력 부족으로 봤다.

하지만 반복해서 작업하다 보니 workflow 자체에도 문제가 있었다.

기존 흐름은 사실상 이랬다.

HUMAN DIRECTION
      ↓
AI IMPLEMENTATION
      ↓
HUMAN REVIEW
      ↓
AI PATCH
      ↓
HUMAN REVIEW

이 구조에서 Human은 최종 디자인 authority이면서 동시에 첫 번째 visual QA 담당자가 된다.

AI가 만든 raw first-pass에서 spacing, alignment, motion, mobile sanity 같은 명백한 결함까지 내가 직접 찾아야 했다.

하지만 Human이 최종 authority라는 것과 Human이 모든 pixel-level QA를 해야 한다는 것은 같은 말이 아니다.

HUMAN DESIGN AUTHORITY
!=
HUMAN MUST PERFORM ALL VISUAL QA

그래서 구현과 Human review 사이에 한 단계를 추가했다.

HUMAN DIRECTION
      ↓
AI DESIGN / IMPLEMENTATION
      ↓
RENDER
      ↓
AI SELF-REVIEW
      ↓
BOUNDED REFINEMENT
      ↓
RENDER AGAIN
      ↓
HUMAN REVIEW CANDIDATE

핵심은 AI에게 최종 디자인 권한을 주는 것이 아니다.

Human에게 보여주는 candidate의 품질을 올리는 것이다.

Screenshot을 만들었다고 self-review가 끝난 것은 아니다

브라우저 자동화와 screenshot artifact는 계속 유용하다.

다만 각 단계의 역할을 분리해야 했다.

TYPECHECK / BUILD / BROWSER TEST
= functional regression protection

VISUAL CAPTURE
= evidence surface

AI VISUAL SELF-REVIEW
= perceptual pre-filter

HUMAN REVIEW
= design authority / acceptance

중요한 건 screenshot을 생성했다는 사실이 아니다.

AI가 그 화면을 다시 보고 스스로 질문해야 한다.

hierarchy가 의도대로 보이는가?
content보다 UI chrome이 더 강하지 않은가?
mobile viewport를 과도하게 점유하지 않는가?
spacing rhythm이 무너지지 않았는가?
motion이 사용자의 scroll과 싸우지 않는가?
없애는 편이 더 나은 요소는 없는가?

테스트는 결과를 측정한다.

self-review는 결과를 본다.

둘은 서로 대체할 수 없다.

실제로 Human feedback의 단위가 달라졌다

이 loop를 Portfolio V2 작업에 적용하면서 의미 있는 변화가 하나 있었다.

첫 implementation 이후 AI가 실제 render를 다시 확인했고, project evidence를 약하게 만드는 opacity transition과 새 stage를 숨기는 오래된 mobile rule을 Human review 전에 발견해 수정했다.

다음 pass에서도 grid alignment collision을 먼저 잡고 여러 mobile width에서 다시 확인했다.

이전에는 내가 이런 문제를 하나씩 찾아서 다시 넘겼다.

self-review가 들어간 뒤 Human review의 질문은 조금 위로 올라갔다.

FROM
"여기 간격이 이상하다"
"왜 mobile에서 이게 움직이나"
"이 요소가 왜 가려지나"

TO
"전체 페이지가 하나의 디자인 시스템으로 읽히는가?"
"이 interaction 방향 자체가 맞는가?"

이 차이가 중요했다.

Human의 시간을 없앤 것이 아니라 더 높은 수준의 판단에 쓰게 했다.

그렇다고 AI self-review가 완전한 것도 아니었다

새로운 한계도 바로 드러났다.

AI는 자신이 크게 수정한 영역을 잘 검토했지만 페이지 전체에 남아 있는 이전 디자인 문법을 자동으로 모두 발견하지는 못했다.

한 시점에는 대략 이런 상태가 됐다.

Hero          = V2
Selected Work = V2
System Map    = V1.5
Journey       = V1

변경한 component만 보면 괜찮았다.

전체 페이지로 보면 서로 다른 세대의 디자인이 섞여 있었다.

그래서 self-review도 두 축으로 나눠야 했다.

A. CHANGED AREA REVIEW
B. WHOLE-SURFACE REVIEW

이것 역시 자동화의 한계라기보다 review scope를 명시하지 않으면 mutation scope에 시선이 갇힌다는 문제에 가까웠다.

디자인 작업에서 PASS의 의미를 다시 정의했다

이후 디자인 작업에서 PASS를 하나의 상태로 보지 않게 됐다.

BUILD PASS
!= BROWSER PASS
!= VISUAL PASS
!= HUMAN ACCEPTANCE

각각 다른 질문에 답한다.

AI가 구현한 디자인의 첫 결과를 바로 Human에게 던지는 것도 줄이려고 한다.

최소한 다음 loop는 거친 뒤 올리는 편이 낫다.

INSPECT
→ IMPLEMENT
→ RENDER
→ SELF-CRITIQUE
→ BOUNDED REVISE
→ RENDER AGAIN
→ VALIDATE
→ HUMAN REVIEW

여기서 최종 방향과 product identity는 여전히 Human이 결정한다.

AI self-review는 authority가 아니라 quality gate다.

자동 테스트가 더 많아진다고 디자인 판단이 자동으로 생기지는 않는다.

반대로 모든 visual QA를 사람이 직접 해야 할 이유도 없다.

내가 얻은 결론은 그 중간에 있다.

기계 검증은 동작을 증명하고, AI self-review는 보이는 결함을 걸러내고, Human은 방향과 의미를 결정한다.