본문으로 건너뛰기
Dot Design System
v0.3.1

생성과 편집

작성 맥락과 저장 상태를 유지하며 복잡한 데이터를 편집합니다.

목표

사용자가 필요한 가치를 이해한 뒤 최소한의 정보로 새 대상을 만들고, 편집 중인 값과 저장된 값을 혼동하지 않으며, 오류나 이동이 발생해도 작업 맥락을 잃지 않게 한다.

생성과 편집을 구분한다

  • 생성 화면은 결과물의 가치와 필요한 최소 입력을 먼저 보여준다.
  • 편집 화면은 현재 대상, 저장된 상태, 변경된 상태를 먼저 보여준다.
  • 생성과 편집이 같은 form을 공유해도 title, 주 행동 레이블, 취소 목적지는 구분한다.
  • 복제는 생성의 한 형태다. 어떤 값이 복사되고 무엇을 새로 정해야 하는지 명시한다.

정보 구조

  1. PageHeader: 대상 또는 생성 목적, 저장 상태, 주 행동
  2. 필요하면 EnvironmentBanner: preview와 실제 운영 차이
  3. Section: 한 번에 하나의 개념
  4. FormField: label, 입력 전 설명, 오류
  5. page 또는 workflow action: 저장, 검증, 다음 단계

긴 폼은 데이터 모델 순서가 아니라 사용자가 답하기 쉬운 순서로 배치한다. 이미 시스템이 아는 값은 채우고 확인만 받거나 아예 묻지 않는다.

입력 판단 규칙

  • 지금 단계에 꼭 필요한 값만 요구한다.
  • 사용자가 3~5초 안에 답하기 어려운 질문에는 예시, 기준 또는 선택지를 제공한다.
  • 구현 방식이나 내부 상태를 선택하게 하지 않는다.
  • 기본값은 가장 흔한 값이 아니라 현재 사용자의 맥락에서 안전한 값이어야 한다.
  • 민감한 정보는 필요한 이유, 사용 범위, 보관 방식을 입력 전에 설명한다.
  • placeholder를 label로 사용하지 않는다.

저장 모델

명시적 저장

  • 여러 필드가 하나의 일관된 변경 단위일 때 사용한다.
  • 주 행동은 저장보다 초안 저장, 설정 저장처럼 대상을 말한다.
  • 변경이 없으면 button을 비활성화할 수 있으나 이유를 명확히 이해할 수 있어야 한다.

자동 저장

  • 작은 변경을 자주 하고 충돌 가능성이 낮을 때 사용한다.
  • 저장 중, 저장됨, 저장 실패를 같은 위치에서 보여준다.
  • 저장 실패를 성공처럼 조용히 유지하지 않는다.
  • 사용자가 페이지를 닫아도 되는 시점을 알 수 있게 한다.

검증

  • 입력 전에 알 수 있는 제약은 description으로 제공한다.
  • 입력 형식 오류는 field 가까이에 표시한다.
  • 여러 field의 관계 오류는 관련 section 또는 form summary에도 연결한다.
  • submit 후 첫 오류로 focus를 이동하고 오류 수를 알린다.
  • 서버 오류가 발생해도 입력값을 보존한다.
  • 보안상 원인을 자세히 말할 수 없어도 사용자가 수정할 수 있는 문제인지, 기다리거나 문의해야 하는지 구분한다.

이탈과 충돌

  • 미저장 변경이 있을 때만 이탈 보호를 사용한다.
  • 취소나 뒤로 가기의 목적지를 분명히 표시한다.
  • 다른 사용자의 최신 변경이 있으면 자동 덮어쓰지 않는다. 현재 변경과 최신본의 차이, 다시 불러오기, 별도 저장 경로를 제공한다.
  • 저장 성공 후 목록으로 이동할지 상세에 남을지 작업 목적에 따라 일관되게 결정한다.

상태

  • initial loading: form 구조를 유지하는 skeleton 또는 전체 loading
  • ready/pristine: 저장된 값과 변경 없음
  • dirty: 수정됨, 아직 저장되지 않음
  • validating: 입력 유지, 검증 중
  • saving: 중복 submit 방지, 진행 레이블
  • saved: 저장 시각 또는 짧은 성공 feedback
  • validation error: field와 summary 연결
  • save error: 입력 보존, 같은 요청 재시도
  • conflict: 최신본과 충돌, 사용자의 명시적 해결 필요
  • permission changed: 작성 내용을 보존하고 가능한 복사·문의 경로 제공

좁은 화면

  • 2열 form은 한 열로 전환하되 논리적 입력 순서를 유지한다.
  • 고정 action bar가 마지막 field와 오류를 가리지 않게 safe spacing을 둔다.
  • outline+editor 구조는 outline 선택 뒤 editor로 이동하는 순차 흐름으로 바꾼다.
  • 긴 도움말은 접기 전에 입력 판단에 필수인 핵심 문장을 항상 보인다.

접근성

  • 모든 control에 programmatic label을 제공한다.
  • required는 시각적 표식과 실제 required 또는 aria-required를 함께 사용한다.
  • 오류는 aria-invalid, aria-errormessage 또는 aria-describedby로 연결한다.
  • form submit 실패 시 오류 summary와 첫 오류 focus 전략을 정의한다.
  • disabled field가 제출에서 제외되는지 read-only와 구분한다.
  • keyboard만으로 입력, 도움말 확인, 저장, 오류 복구가 가능해야 한다.
  • 자동 저장 상태는 polite live region으로 전달하되 입력마다 반복 낭독하지 않는다.

예제

사용 코드 · TSX
<PageScaffold>
  <PageHeader
    title="새 커리큘럼"
    description="학습자가 처음 만나게 될 목적과 기본 순서를 정해요."
    actions={
      <Button form="curriculum-form" type="submit">
        초안 만들기
      </Button>
    }
  />
  <form id="curriculum-form" onSubmit={submit} noValidate>
    <Section title="기본 정보" description="목록과 학습 시작 화면에 함께 보여요.">
      <FormField id="name" label="커리큘럼 이름" error={errors.name} required>
        <Input name="name" required />
      </FormField>
    </Section>
  </form>
</PageScaffold>

피해야 할 사용

  • 결과 가치를 설명하기 전에 긴 가입·입력 요구
  • 시스템이 이미 아는 값을 반복해서 질문
  • placeholder로 label 대체
  • 저장 실패 시 입력값 초기화
  • 변경이 없는데 모든 이동에 확인 dialog 표시
  • 서로 다른 저장 단위를 하나의 거대한 submit에 묶기
  • 자동 저장 실패를 작은 색상 점으로만 표시

검토 체크

  • 사용자가 생성 결과의 가치를 입력 전에 이해한다.
  • 지금 꼭 필요한 값만 질문한다.
  • 질문 순서가 사용자가 아는 정보 순서와 맞다.
  • label, description, error의 역할이 분리돼 있다.
  • pristine, dirty, saving, saved, error, conflict가 정의돼 있다.
  • 저장 실패와 권한 변경에서도 입력을 보존한다.
  • 미저장 변경이 있을 때만 이탈을 보호한다.
  • 좁은 화면의 field와 action 순서가 논리적이다.
  • submit 오류 focus와 summary가 정의돼 있다.

관련 항목