본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 16. 13:49

AI가 생성한 UI가 어색해 보이는 이유와 이를 해결하는 단 하나의 원칙

요약

AI가 생성한 UI가 어색해 보이는 근본 원인인 '불일치성(Incoherence)'을 분석하고, 이를 해결하기 위한 디자인 원칙을 제시합니다. 각 디자인 축에 대해 단 하나의 결정 사항을 선택하고 이를 모든 컴포넌트에 일관되게 적용하는 방법을 다룹니다.

핵심 포인트

  • AI는 컴포넌트를 개별적으로 생성하여 전체적인 일관성이 부족함
  • 문제의 핵심은 컴포넌트 간의 '불일치성(Incoherence)'임
  • 해결책은 디자인 축별로 단 하나의 값을 선택해 토큰화하는 것
  • 곡률, 그림자, 강조색, 간격 등의 디자인 요소를 공유해야 함

여러분도 본 적이 있을 겁니다. AI에게 대시보드를 만들라고 요청했는데, 결과물이… 그저 그렇다는 느낌을 주는 경우를요? 모든 컴포넌트는 개별적으로는 완벽합니다. 버튼은 버튼이고, 카드는 카드입니다. 그런데 전체적인 모습이 마치 생성된 것처럼 보입니다. 일종의 UI 스톡 사진 같은 느낌이죠.

오랫동안 저는 이 문제의 해결책이 '더 나은 컴포넌트'나 '프롬프트에 대한 더 많은 취향'이라고 생각했습니다. 하지만 그렇지 않습니다. 실제 디자인 문헌들—Refactoring UI, Material Design 3, Apple의 HIG(Human Interface Guidelines), IBM Carbon, WCAG, Financial Times의 시각적 어휘 등—을 깊이 파고든 끝에 진짜 원인이 무엇인지 알게 되었고, 그 이름은 다음과 같습니다:

불일치성 (Incoherence).

부분들끼리 서로 동의하지 못하고 있는 겁니다. 그리고 일단 이 문제를 인식하면 다시는 무시할 수 없죠.

이전에 당신의 분위기 코딩 앱이 왜 보기 흉한지, 그리고 제가 어떻게 했는지에 대해 글을 쓴 적이 있습니다. 이번 포스팅은 그보다 더 깊은 곳, 즉 '어색하다'는 느낌의 실제 메커니즘과 이를 고치는 단 하나의 원칙에 대해 다룹니다.

문제점: 서로 동의하지 못하는 부분들

여기에 아무것도

언어 모델(Language Model)은 UI를 로컬(locally) 방식으로 생성합니다. 모델은 카드(card)를 쓰고, 그다음 버튼(button)을 쓰고, 그다음 모달(modal)을 씁니다. 각각을 새롭고 그럴듯한 조각(snippet)으로 생성하는 방식입니다. 모델에게는 "40줄 위에 있던 버튼들은 알약 모양(pill-shaped)이었으니, 이것들도 그래야 한다"라는 식의 실행 중인 메모리(running memory)가 없습니다. 각 컴포넌트는 학습 데이터의 평균값으로 회귀하며, "버튼"의 평균값과 "카드"의 평균값은 서로 조정된 적이 없습니다.

인간은 이런 식으로 일하지 않습니다. 우리는 머릿속에 아주 작은 결정 세트—"이 제품은 모서리가 둥글고, 파란색 강조색을 사용하며, 8px 그리드를 따른다"—를 가지고 있으며, 모든 새로운 요소는 이를 상속받습니다. 이러한 결정들은 끈끈하게 유지됩니다(sticky).

따라서 해결책은 "모델의 미적 감각을 더 높이는 것"이 아닙니다. 해결책은 다음과 같습니다: 끈끈한 결정 사항들을 글로 적고, 모델에게 새로운 것을 발명하는 대신 그것들을 복사하도록 지시하는 것입니다.

메타 법칙(The meta-law): 축당 하나의 선택

전체 아이디어를 한 문장으로 요약하면 다음과 같습니다:

각 디자인 축(design axis)에 대해, 정확히 하나의 값 또는 제품군(family)을 선택하고, 이를 토큰(token)으로 인코딩하여 모든 곳에 적용하십시오.

일관성(Coherence)이란 "모든 화면이 동일해야 한다"는 뜻이 아닙니다. 동일한 결정 사항이 반복된다는 뜻입니다. 설정 페이지와 대시보드는 매우 다르게 보일 수 있지만, 곡률(radius)의 성격, 그림자 언어(shadow language), 강조색(accent), 그리고 간격 단위(spacing unit)를 공유한다면 여전히 하나의 제품처럼 느껴질 수 있습니다.

통일성을 유지해야 하는 축들은 다음과 같습니다:

축 (Axis)시스템 전체에 단 하나만 선택혼합되었을 때의 실패 사례
모서리 / 곡률 (Corner / radius)날카로운 0–4px · 부드러운 8–12px · 알약 모양 9999px날카로운 대화창 + 둥근 버튼 = "두 개의 제품을 붙여놓은 듯한 느낌"
...

비디자이너가 표현한 것 중 제가 들은 가장 훌륭한 직관은 다음과 같습니다:

"모서리가 날카롭다면, 모든 것이 날카로워야 합니다."

정확합니다. 그리고 이는 표의 모든 행에 일반화될 수 있습니다. 혼합된 축을 스타일의 선택이 아닌, 린트 에러(lint error)로 취급하십시오.

Every decision in a StyleSeed UI tied to the rule behind it — numbers 2:1, one accent, content in cards, one corner radius.

이 중 네 가지를 구체화해 보겠습니다.

1. 하나의 코너 성격(personality)을 정하고 중첩 법칙(nesting law)을 준수하세요

첫째, 반경(radius)은 **토큰(token)**이어야 하며, 결코 매직 넘버(magic number)가 되어서는 안 됩니다. 작은 스케일을 정의하고 모든 곳에서 이를 참조하세요:

:root {
  --radius-sm: 8px;   /* inputs, buttons   */
  --radius-md: 12px;  /* cards, menus      */
...

그다음 **하나의 성격(personality)**을 정하세요. 모두 날카롭거나(sharp), 모두 부드럽거나(soft), 또는 모두 알약 형태(pill)로 정한 뒤 이를 카드(card), 버튼(button), 입력창(input), 모달(modal), 이미지(image) 전체에 적용하십시오. 모델이 rounded-full 버튼을 가진 rounded-none 패널을 자유롭게(freestyle) 생성하도록 내버려 두지 마세요.

대부분의 사람들이 놓치는 미묘한 두 번째 규칙이 있습니다: 중첩된 반경(nested radii)은 중심을 공유해야 합니다. 패딩(padding)이 있는 둥근 컨테이너 안에 둥근 요소가 들어갈 때, 내부 반경(inner radius)은 더 작아야 합니다:

내부 반경 = 외부 반경 − 패딩
.card {
  --pad: 16px;
  border-radius: var(--radius-lg);          /* 16px */
...

내부 요소에 외부 요소와 동일한 반경을 부여하면, 모서리가 컨테이너의 호(arc) 밖으로 눈에 띄게 튀어나와 보입니다. Apple의 새로운 "Liquid Glass" 시스템은 바로 이 동심원 모서리(concentric-corner) 수학을 공식화했으며, Cloud Four에 이에 대한 표준적인 설명이 있습니다.

2. 단일 광원으로부터 나오는 계층적 그림자(Layered shadows)

깊이감(depth)을 가짜처럼 보이게 만드는 가장 빠른 방법은 단 하나의 강한 box-shadow를 사용하는 것입니다. 실제 그림자는 그라데이션(반그림자, penumbra)이므로, 여러 개의 낮은 불투명도(low-opacity) 레이어를 쌓아야 합니다. 그리고 결정적으로, 색이 탁해지는 순수 검은색을 사용하는 대신 표면의 색조(surface hue)에 맞춰 색을 입히는(tint) 것이 중요합니다:

/* card — 페이지 근처에 위치함 */
--shadow-md:
  0 1px 2px  hsl(220 40% 20% / 0.08),
...

일관성 규칙: 페이지 전체에 대해 하나의 광원 방향을 유지하십시오 (관례: 위쪽 및 약간 왼쪽). 수직 오프셋(vertical offset)은 수평 오프셋의 대략 2배로 설정합니다. 고도(elevation)가 높아질수록 오프셋과 블러(blur)는 증가하고 불투명도는 감소합니다. 이렇게 하면 카드와 모달이 서로 무관한 두 효과가 아니라, 서로 다른 높이에 있는 물체에 동일한 빛이 닿는 것으로 읽히게 됩니다. (Josh Comeau와 Tobias Ahlin 모두 이에 대해 훌륭한 심층 분석을 제공합니다.)

다크 모드(Dark mode)에서는 그림자가 거의 사라지므로, 톤 기반 고도화 (tonal elevation) — 고도가 높을수록 더 밝은 표면을 사용하는 방식 — 로 전환해야 합니다. 또한 베이스 컬러로 순수한 #000을 절대 사용하지 마세요. (Material Design에서는 레벨에 따라 화이트 오버레이를 얹은 #121212를 권장합니다.)

3. 하나의 강조색, 나머지는 모두 그레이스케일 (Greyscale)

대부분의 "AI 무지개" UI는 무언가를 강조해야 할 때마다 새로운 색상을 찾으려 하기 때문에 발생합니다. 지켜야 할 원칙은 다음과 같습니다:

  • 상호작용 강조를 위한 단 하나의 강조색 (accent).
  • 텍스트, 표면, 테두리에는 전체적인 틴트된 그레이 램프 (tinted-grey ramp) 사용 (순수 회색이 아니라, 브랜드 색조 쪽으로 5~15% 정도 미세하게 조정된 색상).
  • 오직 네 가지의 의미론적 색상(semantic colors) — 성공(success) / 경고(warning) / 오류(error) / 정보(info) — 만을 사용하며, 이는 오직 의미 전달을 위해서만 엄격히 사용하고 장식용으로는 절대 사용하지 말 것.
:root {
  --accent: #5b5bd6;
  /* 채도가 0인 회색이 아니라, 강조색의 색조 쪽으로 약간 틴트된 회색 */
...

그리고 타협할 수 없는 하나의 접근성 기준(WCAG 2.2 AA)이 있습니다: 본문 텍스트의 대비(contrast)는 4.5:1, 큰 텍스트 및 UI 컴포넌트는 3:1을 유지해야 합니다. 색상만으로 정보를 전달하지 마세요. 반드시 아이콘, 텍스트 또는 도형과 함께 사용해야 합니다. 잘못된 입력 필드에 빨간색 테두리만 두는 것으로는 부족합니다. 아이콘과 메시지를 함께 추가하세요.

4. 하나의 간격 그리드, 근접성(Proximity)을 통한 그룹화

모든 마진(margin), 패딩(padding), 간격(gap)을 단일 스케일 — 4, 8, 12, 16, 24, 32, 48, 64 — 에 맞춰 정렬하고, **근접성 (proximity)**이 의미를 전달하게 하세요. 게슈탈트(Gestalt) 이론과 Refactoring UI의 "모호한 간격 피하기" 원칙에 따른 규칙은 다음과 같습니다: 그룹 내부의 간격보다 그룹 주변의 간격이 명확하게 더 커야 합니다.

폼(form)을 위한 구체적인 단계는 다음과 같습니다:

label → input        : 4–8px
input → input         : 12–16px
group → group (section): 24–32px

모든 간격이 일정하면 눈은 무엇이 서로 연결되어 있는지 구분할 수 없습니다. 각 단계마다 간격을 두 배로 늘리는 것이 라벨을 해당 필드에 결합시키고, 섹션을 다음 섹션과 분리하는 핵심입니다.

기계가 스스로 검토하게 만들기

결정 사항을 문서로 작성하는 것이 싸움의 절반이라면, 나머지 절반은 위반 사항을 잡아내는 것입니다. 여기에 AI가 실제로 도움을 줄 수 있습니다 — 만약 당신이 AI에게 평가 기준(rubric)을 제공한다면 말이죠.

저는 위의 모든 사항을 Claude Code와 Cursor가 자동으로 읽을 수 있는 오픈 소스 디자인 엔진 (StyleSeed)에 녹여냈지만, 이 아이디어는 특정 도구에 국한되지 않습니다. 가장 유용했던 부분은 **일관성 평가기 (coherence grader)**였습니다. 이는 파일을 점수화하고, _혼합된 축 (mixed axes)_을 실제 감점 요인으로 표시하는 체크 기능입니다.

해당 출력 결과의 요약된 예시는 다음과 같습니다:

## 디자인 점수: 70 / 100   (Dashboard.tsx)

색상 규율 (Color discipline)   13/18  ▓▓▓░  #000 헤딩; 3개의 강조 색상 (accent hues)
...

"일관성 (Coherence)" 카테고리는 "AI가 생성한 것처럼 보인다"라는 느낌을 가장 잘 예측하는 항목입니다. 그 이유는 이 항목이 개별 컴포넌트의 예쁨이 아니라 _시스템 전반의 일관성 (system-wide consistency)_을 측정하기 때문입니다. 컴포넌트 하나는 아름다울 수 있지만, 이웃한 컴포넌트와 어긋난다면 여전히 틀린 디자인일 수 있습니다.

핵심 요약 (The takeaway)

딱 한 가지만 기억해야 한다면:

아름다운 부분들이 모인다고 아름다운 UI가 되는 것은 아닙니다. 부분들이 서로 **일치 (Agreeing)**해야 합니다.

각 축(axis) — 곡률 (radius), 그림자 (shadow), 강조 색상 (accent), 간격 (spacing), 아이콘 (icons), 타이포그래피 (type), 모션 (motion) — 마다 하나의 값을 정하십시오. 이를 토큰 (token)으로 기록하고, 새로운 요소를 만들 때마다 새로운 선택을 발명하는 대신 해당 토큰을 상속받게 만드십시오. 이 단 하나의 규율이 "로봇이 만들었다"와 "디자이너가 만들었다"를 가르는 차이이며, AI가 구축한 인터페이스를 위해 당신이 할 수 있는 가장 저렴하고 영향력이 큰 일입니다.

모서리가 각져 있다면? 그렇다면 모든 것이 각져 있어야 합니다. 끝까지 말이죠.

실용적인 측면이 궁금하신가요? 저는 관련 포스트에서 당신의 vibe-coded 앱이 추해 보이는 것을 멈추게 할 단 하나의 파일 수정법을 다루었습니다. 그리고 Refactoring UI / Material 3 / Apple HIG / WCAG에 근거한 구체적인 간격 수치, 앱 유형별 타이포그래피 레시피, 레이어드 그림자(layered-shadow) 및 중첩 곡률(nested-radius) 레시피를 포함한 연구 기반의 전체 버전은 오픈 소스 (MIT)로 공개되어 있습니다: github.com/bitjaru/styleseed. ⭐(Star) 하나는 더 많은 개발자(그리고 더 많은 AI 도구)가 이를 찾는 데 큰 도움이 됩니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0