Skip to content

그리드/스프레드시트 편집을 위한 편집 세션 책임과 API 개선 제안 #1

@developer-1px

Description

@developer-1px

배경

anyeditable을 스프레드시트 셀 편집에 붙여보면, 라이브러리의 적절한 책임은 특정 도메인을 아는 것이 아니라 하나의 editable target에 대한 편집 세션 상태머신까지라고 보입니다.

현재 앱에서는 anyeditable을 얇은 어댑터로 감싸서 쓰고 있습니다.

anyeditable
→ editing id / draft / start / commit / cancel / input props 관리

app adapter
→ cell id 파싱, A1 key 변환, writeCell, navigation, validation, grid selection 처리

이 경계 자체는 좋습니다. 다만 그리드/스프레드시트류 UI에서 자주 필요한 편집 세션 기능이 몇 가지 더 있으면 앱 쪽 우회 코드가 줄어들 것 같습니다.

제안하는 책임 범위

anyeditable이 담당하면 좋은 것:

  • 현재 편집 대상 id 관리
  • draft 관리
  • startEdit / commitEdit / cancelEdit 상태 전이
  • input/select/textarea에 붙일 props 생성
  • Enter / Escape / blur / Tab 같은 편집 세션 키 처리
  • commit 후 이동 의도 표현
  • IME composition 보호
  • commit/cancel reason 전달

앱이 계속 담당해야 하는 것:

  • id의 의미 정의(cell id, row id, item id 등)
  • getValue(id)
  • onCommit(id, value, meta)
  • onNavigate(id, intent)
  • 값 검증/정규화 정책
  • spreadsheet selection/fill/merge/freeze/filter
  • formula evaluation
  • undo/redo document history
  • persistence

있으면 좋은 API/기능

1. commitEdit({ dRow, dCol }) 또는 좌표 이동 intent 지원

스프레드시트에서는 commit 이후 아래/위/왼쪽/오른쪽으로 이동하는 동작이 중요합니다.
현재는 앱에서 { dRow, dCol }up/down/left/right로 다시 변환해야 합니다.

commitEdit({ dRow: 1, dCol: 0 })
commitEdit({ move: 'next-row' })

같은 형태가 있으면 그리드 쪽 코드가 더 자연스러워집니다.

2. editable target guard 내장

input/textarea/select 안에서 Enter, Backspace, Delete 등이 상위 grid shortcut으로 새지 않도록 막는 기본 guard가 필요합니다.
그리드 라이브러리와 같이 쓰면 이벤트 버블링 때문에 편집 중인데 grid shortcut이 다시 실행되는 문제가 생기기 쉽습니다.

3. IME/composition 안전 처리

한글/일본어/중국어 입력 중 Enter/Escape/blur 처리에서 조합 중인 문자가 잘못 commit/cancel되지 않도록 composition 상태를 명시적으로 보호하면 좋겠습니다.

4. startEdit(id, prefill, { caret }) 계약 명확화

  • printable key로 시작: 기존 값 대신 입력한 문자로 draft 시작
  • F2/더블클릭: 기존 값 유지, caret end
  • Enter: 기존 값 선택 또는 끝 이동 등

이런 모드가 API 계약으로 드러나면 앱별 분기가 줄어듭니다.

5. commit/cancel reason 전달

onCommit(id, value, {
  reason: 'enter' | 'tab' | 'blur' | 'navigation' | 'programmatic',
  move?: { dRow: number; dCol: number }
})

처럼 이유가 있으면 앱이 blur commit, Enter commit, navigation commit을 다르게 다룰 수 있습니다.

6. beforeCommit / validateCommit hook

커밋 전에 값을 검증하거나 정규화하거나 거부할 수 있으면 좋겠습니다.
예를 들어 list validation, checkbox normalization, formula syntax warning 같은 기능을 앱이 자연스럽게 붙일 수 있습니다.

beforeCommit?: (id, draft) =>
  | { ok: true; value: string }
  | { ok: false; error: string }

7. editor slot / editor type adapter

현재는 앱이 input/select/textarea를 직접 분기합니다.
anyeditable이 편집 세션 props는 유지하되 editor type을 명시적으로 지원하면 list validation이나 wrap textarea 연결이 쉬워질 것 같습니다.

editorFor?: (id) => 'input' | 'textarea' | 'select'

우선순위

개인적으로는 아래 순서가 가장 체감이 클 것 같습니다.

  1. editable target guard
  2. IME/composition 안전 처리
  3. commitEdit({ dRow, dCol }) 지원
  4. commit/cancel reason 전달
  5. beforeCommit/validateCommit
  6. editor slot/input-select-textarea 통합

비목표

anyeditable이 아래 책임까지 가져가지는 않는 것이 좋겠습니다.

  • A1 주소나 spreadsheet row/col을 직접 알기
  • selection range 관리
  • undo stack 소유
  • formula parsing/evaluation
  • validation rule 저장
  • grid rendering
  • localStorage/server persistence

즉 목표는 spreadsheet 라이브러리가 되는 것이 아니라, grid/list/table/spreadsheet에서 공통으로 쓸 수 있는 편집 세션 상태머신을 단단하게 만드는 쪽이면 좋겠습니다.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions