UI 상태

UI State

개념

버튼이나 목록 같은 화면 요소 하나가 조작과 데이터 사정에 따라 달리 보이는 모습을 갈래마다 미리 정해 둔 것입니다.

등장 배경

화면 시안은 오래도록 한 장짜리 그림이었습니다. 목록에 항목이 열두 개 들어 있고 버튼은 파란색이며 아무 문구도 떠 있지 않은 화면, 그러니까 모든 것이 잘 풀렸을 때의 모습 한 장입니다. 그런데 실제 제품에서 그 목록에 열두 개가 들어 있는 순간은 전체 중 일부입니다. 방금 가입한 사람에게는 0개이고, 통신이 느린 사람에게는 몇 초 동안 비어 있고, 서버가 답하지 않으면 끝까지 비어 있습니다. 시안 한 장은 여러 사정 가운데 하나만 그려 놓은 셈이었습니다.

나머지 모습은 만드는 사람이 그때그때 채웠습니다. 채운다는 자각조차 없이 채워지는 것이 문제였습니다. 목록을 그리는 코드는 항목이 0개면 아무것도 그리지 않는 것이 기본 동작이라, 따로 정해 두지 않으면 빈 화면이 나옵니다. 불러오는 동안 무엇을 보일지 정해 두지 않으면 그 몇 초도 빈 화면입니다. 요청이 실패했을 때 무엇을 보일지 정해 두지 않으면 역시 빈 화면입니다. 서로 완전히 다른 세 가지 사정이 사용자에게는 똑같은 한 장면으로 도착합니다.

페이지덱에서 이 문제가 드러난 것은 목록 화면 세 개를 나란히 놓고 보면서였습니다. 문서 목록은 비어 있을 때 아무것도 뜨지 않았고, 댓글 목록은 댓글이 없다는 문구가 가운데에 떴고, 공유 대상 목록은 회색 상자 다섯 개가 계속 깜빡이고 있었습니다. 셋 다 태오가 만들었고, 셋 다 시안에는 없던 화면입니다. 수아에게 들어온 문의는 문서가 사라졌다는 것이었는데 확인해 보니 그 계정의 문서는 처음부터 0개였습니다. 사라진 적 없는 문서를 찾느라 양쪽이 이틀을 썼습니다. 고장 난 것은 문서를 저장하고 불러오는 기능이 아니라, 문서가 0개일 때 무엇을 보일지 아무도 정하지 않았다는 사실이었습니다.

UI 상태는 이 빈자리를 목록으로 바꾼 개념입니다. 요소 하나를 두고 그것이 가질 수 있는 모습을 미리 세어 이름을 붙여 두면, 시안에도 그만큼의 장면이 들어가고 만드는 쪽도 무엇이 정해지지 않았는지 알게 됩니다. 버튼 하나에 다섯 가지, 목록 하나에 네다섯 가지가 있다는 사실을 드러내는 것이 이 개념이 하는 일의 거의 전부입니다. 인터랙션 디자인이 사람의 조작과 제품의 반응을 짝지어 정해 두는 영역이라면, 그 반응이 화면에서 실제로 어떤 모습을 띠는지를 갈래로 나눠 놓은 것이 UI 상태입니다.

분야 구성

상태를 가르는 기준은 무엇이 달라짐을 일으키느냐입니다. 사람이 손을 대서 달라지면 상호작용 갈래이고, 데이터가 늦거나 없거나 실패해서 달라지면 데이터 갈래입니다. 앞쪽은 버튼·입력칸·메뉴처럼 조작할 수 있는 요소마다 붙고, 뒤쪽은 목록·표·카드처럼 내용을 실어 나르는 요소마다 붙습니다. 한 화면에는 보통 두 갈래가 함께 들어 있습니다.

상호작용 갈래는 다섯입니다. 사람의 포인터와 키보드와 손가락이 요소에 닿는 순간마다 하나씩 대응합니다.

  1. 기본 상태 — 아무도 건드리지 않았을 때의 모습입니다. 나머지 넷은 전부 이 모습에서 얼마나 달라지는지로 정의되기 때문에, 기본 상태가 정해지지 않으면 나머지도 정할 수 없습니다. 시안에 그려져 있는 한 장이 대개 이것입니다.
  2. 호버 — 포인터가 요소 위에 올라가 있는 동안의 모습입니다. 배경이 한 단계 진해지거나 커서가 손가락 모양으로 바뀌어서, 누르기 전에 이것이 눌리는 것임을 알려 줍니다. 마우스가 있는 환경에서만 생기는 상태라, 삭제 버튼을 호버할 때만 보이게 만들면 휴대폰에서는 그 버튼이 없는 것과 같아집니다.
  3. 포커스 — 키보드의 탭 키나 보조기기로 지금 선택돼 있는 요소의 모습입니다. 마우스를 쓰지 않는 사람에게는 자기가 화면 어디에 서 있는지 알려 주는 유일한 표시입니다. 테두리가 보기 싫다고 지우면 그 사람들은 엔터를 눌렀을 때 무엇이 눌릴지 모르는 채로 화면을 쓰게 됩니다.
  4. 액티브 — 누르고 있는 동안, 손을 떼기 전까지의 짧은 모습입니다. 버튼이 살짝 눌려 들어가거나 색이 진해지는 0.1초짜리 변화인데, 이것이 없으면 눌렀는지 아닌지를 손끝이 아니라 결과로만 확인하게 됩니다. 결과가 늦게 오는 화면일수록 이 짧은 반응이 크게 작동합니다.
  5. 비활성 — 지금은 쓸 수 없는 요소의 모습입니다. 회색으로 흐려 두고 눌러도 반응하지 않게 만듭니다. 흐리게 만드는 것까지는 쉬운데 왜 못 쓰는지를 알려 주는 일이 자주 빠져서, 결제 버튼이 회색인 이유가 카드가 등록되지 않아서인지 금액이 0원이어서인지를 사용자가 추측하게 됩니다.

데이터 갈래는 여섯입니다. 화면이 보여 줄 내용을 다른 곳에서 가져와야 하기 때문에 생기는 상태들입니다.

  1. 로딩 상태 — 내용을 가져오는 중임을 알리는 모습입니다. 돌아가는 원이나 진행 막대를 씁니다. 이 자리가 비어 있으면 사용자는 기다리는 중인지 고장 난 것인지 구분하지 못하고, 대개 한 번 더 누릅니다. 저장을 두 번 누른 요청이 둘 다 성공해 같은 문서가 두 개 남는 일이 여기서 시작됩니다.
  2. 빈 상태 — 가져왔는데 보여 줄 것이 없을 때의 모습입니다. 실제로는 두 종류가 섞여 있어서 나눠야 합니다. 아직 아무것도 만들지 않은 새 사용자의 빈 화면에는 무엇을 만들면 되는지가 들어가야 하고, 검색이나 필터의 결과가 0건인 빈 화면에는 조건을 어떻게 바꾸면 되는지가 들어가야 합니다. 둘에 같은 문구를 쓰면 한쪽은 반드시 어긋납니다. 문서가 하나도 없는 사람에게 검색어를 바꿔 보라고 하거나, 검색 결과가 0건인 사람에게 첫 문서를 만들어 보라고 하는 화면이 그렇게 나옵니다.
  3. 오류 상태 — 가져오다 실패했을 때의 모습입니다. 무엇이 잘못됐는지와 지금 무엇을 하면 되는지를 함께 적습니다. 다시 시도 버튼이 있는 화면과 없는 화면은 같은 실패를 겪고도 문의 건수가 다릅니다.
  4. 성공 상태 — 요청한 일이 끝났음을 알리는 모습입니다. 저장됨 표시나 완료 문구가 여기 들어가고, 몇 초 뒤에 사라지게 할지 화면에 남길지가 함께 정해집니다. 되돌릴 수 있는 작업이라면 이 자리에 되돌리기를 붙입니다.
  5. 스켈레톤 UI — 로딩 상태를 표현하는 한 가지 방식입니다. 돌아가는 원 대신, 앞으로 들어올 내용의 자리를 회색 덩어리로 먼저 그려 둡니다. 실제 속도가 빨라지지는 않지만 화면 구조가 미리 보이기 때문에 같은 2초가 짧게 느껴지고, 내용이 채워질 때 화면이 덜 흔들립니다.
  6. 옵티미스틱 UI — 서버의 답을 기다리지 않고 성공했다고 가정해 화면을 먼저 바꾸는 방식입니다. 좋아요를 누르면 하트가 즉시 채워지고 서버 요청은 뒤에서 돌아갑니다. 실패했을 때 화면을 되돌리는 처리를 함께 만들어야 하므로, 실패할 일이 드물고 되돌아가도 큰 손해가 없는 조작에만 씁니다.

두 갈래는 한 요소 안에서 이어집니다. 문서를 공유하는 버튼 하나를 보면, 누르기 전까지는 상호작용 갈래가 붙어 기본·호버·포커스·액티브를 오가고, 누른 뒤에는 데이터 갈래로 넘어가 로딩·성공·오류 중 하나가 됩니다. 버튼 하나에 필요한 장면이 일곱 개라는 뜻인데, 실제로 일곱 장을 매번 그리지는 않습니다. 대신 어떤 상태가 어떤 규칙으로 달라지는지를 공통 규칙으로 한 번 적어 둡니다. 버튼의 호버는 배경색을 한 단계 진하게 하고 비활성은 투명도를 40퍼센트로 내린다는 식으로 정해 두면, 화면에 버튼이 스무 개여도 그려야 할 시안은 한 벌입니다.

실무 용례

"이 목록 빈 상태 시안이 없는데요. 처음 들어온 사람은 여기서 뭘 보나요?"

내용이 있을 때의 화면만 받았으니 0건일 때의 화면을 달라는 요청입니다. 이대로 만들면 새 사용자에게는 아무것도 없는 화면이 나갑니다.

"버튼 상태 다섯 개 다 있나요? 비활성일 때 안내 문구도 같이 주세요."

기본 모습만 그려진 시안을 받고 나머지 넷과, 왜 못 누르는지를 설명하는 문구까지 요청하는 말입니다.

"여기는 서버 응답 기다리지 말고 먼저 반영하죠. 실패하면 되돌리고 안내 띄우고요."

옵티미스틱 방식으로 가되 실패했을 때의 복구 경로까지 이번 작업에 포함하자는 합의입니다.

페이지덱에서 이 말이 가장 많이 오가는 자리는 민서가 시안을 넘기고 태오가 받는 회의입니다. 민서는 언제부턴가 화면 옆에 표를 한 장 붙여 옵니다. 세로에는 요소 이름을, 가로에는 상태 이름을 적고 칸마다 어떤 모습인지를 채운 표입니다. 태오가 묻는 질문도 그 표를 따라갑니다. 문서가 0개일 때 목록 자리에 무엇이 들어가는지, 불러오는 데 5초가 걸리면 그동안 무엇이 보이는지, 공유 링크를 만드는 동안 버튼이 어떤 모습인지 같은 것입니다. 표가 없던 시절에는 이 질문들이 회의가 아니라 배포 다음 날 문의함에서 나왔습니다.

표에 빈칸이 남아 있으면 그 자리는 회의에서 정해집니다. 정하지 못하면 적어도 빈칸으로 남아 있다는 사실이 기록됩니다. 예전처럼 아무도 모르는 채로 코드의 기본 동작이 대신 답하는 일은 그 뒤로 줄었습니다.

흔한 오해

상태를 정하는 일을 화면을 예쁘게 다듬는 마감 작업으로 여기는 경우가 많습니다. 상태가 대개 색과 그림자와 투명도로 표현되니 시각 작업처럼 보이는 것이 자연스럽습니다. 그런데 어떤 상태가 존재하느냐는 시각의 문제가 아니라 제품이 어떤 사정에 처할 수 있느냐의 목록입니다. 빈 상태가 필요하다는 말은 항목이 0건인 사용자가 실제로 있다는 뜻이고, 오류 상태가 필요하다는 말은 요청이 실패하는 경로가 있다는 뜻입니다. 이것을 마감 작업으로 분류해 두면 일정이 밀릴 때 가장 먼저 잘리고, 잘린 자리는 코드의 기본 동작이 채웁니다. 화면마다 다른 제품처럼 보이는 상태가 그렇게 만들어집니다. 목록 세 개가 저마다 다르게 비어 있던 페이지덱의 화면이 정확히 그 결과였습니다.

스켈레톤 UI를 속도 개선으로 읽는 것도 흔합니다. 바꾸고 나면 사용자들이 실제로 빨라졌다고 말하니 그렇게 믿게 됩니다. 하지만 서버가 답하는 데 걸리는 시간은 1밀리초도 줄지 않았습니다. 줄어든 것은 기다림의 불확실성입니다. 화면 구조가 먼저 보이므로 무엇이 올지 알고 기다리게 되고, 그래서 같은 2초가 짧게 느껴집니다. 이 차이를 구분하지 않으면 3초 걸리던 요청을 그대로 둔 채 표현만 바꾸고 끝내게 됩니다. 기다리는 시간이 8초를 넘어가면 회색 덩어리가 아무리 정교해도 사람은 화면을 떠나므로, 그때는 표현이 아니라 요청 자체를 손봐야 합니다.

같이 보면 좋은 페이지

  • 인터랙션 디자인

    상태가 어느 설계 영역 안에 놓인 갈래인지 먼저 봅니다

  • 기본 상태

    나머지 상태가 전부 여기서 갈라지므로 하나만 고른다면 이것입니다

  • 상태 관리

    화면이 그 상태를 어떻게 기억하고 바꾸는지를 만드는 쪽에서 봅니다

하위 용어

마지막 업데이트 2026-09-16