Wordgard 0.1 릴리스
요약
Wordgard 0.1은 ProseMirror의 설계 경험과 CodeMirror 6의 철학을 반영하여 새롭게 설계된 JavaScript 리치 텍스트 편집기 라이브러리입니다. 기존 ProseMirror의 복잡한 steps 방식 대신 변경 섹션 기반 모델을 도입하여 더 단순하고 효율적인 문서 변경 관리를 제공합니다.
핵심 포인트
- ProseMirror의 설계 한계를 극복하기 위해 호환성을 배제하고 새 API로 재설계함
- steps 대신 변경 섹션(delta) 모델을 사용하여 변경 범위 추적 및 합성을 단순화함
- CodeMirror식 facet 확장 시스템과 토큰 카운팅 인덱스를 결합하여 구조적 안정성 확보
- 제한적인 운영 변환(OT) 지원으로 협업 편집 및 undo 기능 구현에 용이함
Wordgard 0.1은 ProseMirror 안정화 이후 9년간의 경험과 CodeMirror 6의 설계를 반영해 새로 만든 JavaScript 리치 텍스트 편집기 라이브러리임
- 기존 ProseMirror를 2.0으로 바꾸거나 1.x에 덧붙이지 않고,
호환성 부담 없는 새 API와 별도 이름으로 다시 설계함 - 핵심 설계는 steps 대신
변경 섹션 기반 모델을 쓰고, 독립적인 노드·마크 타입과 CodeMirror식 facet 확장 시스템을 결합함 - 브라우저 선택 동작 의존을 줄여 포인터·키보드 선택을 직접 처리하지만,
터치 선택은 네이티브 컨텍스트 메뉴 문제 때문에 브라우저 구현을 유지함 - npm의
wordgard
로 설치할 수 있고 문서와 참조 매뉴얼도 공개됐지만, 피드백과 버그 수정을 거치며 한동안 0.x 버전에 머물 예정임
Wordgard의 성격과 배포 상태
- Wordgard는 ProseMirror 스타일 리치 텍스트 편집기 시스템을 새로 반복한 프로젝트임
- ProseMirror 안정화 이후 9년 동안 배운 점과 CodeMirror 버전 6 재설계에서 많은 영향을 받음
- 브라우저 DOM으로 편집기 인터페이스를 표시하는
JavaScript 라이브러리이며, 라이선스는 MIT임 - 코드는 Forgejo 서버에 공개되어 있음
- npm 레지스트리에서
wordgard
로 설치할 수 있고, 사용법은 웹사이트에서 확인 가능함
ProseMirror를 바꾸지 않고 새 시스템을 만든 이유
- ProseMirror는 계속 유지보수되지만, 일부 설계는 지금 기준에서 다르게 만들었어야 했던 부분으로 남아 있음
- 비호환 인터페이스의 ProseMirror 2.0을 내면 사람들이 “ProseMirror”라고 부를 때 무엇을 뜻하는지 모호해질 수 있음
- ProseMirror 1.x에 하위 호환 방식으로 새 아이디어를 붙이면 구조가 타협적으로 흐를 수 있음
- Wordgard는 ProseMirror의 많은 아이디어를 가져오되,
프로그래밍 인터페이스는 호환성을 고려하지 않고 처음부터 다시 설계함
변경 표현: steps 대신 섹션 기반 모델
- ProseMirror의
steps는 변경을 여러 원자적 작업으로 나누고, 각 step이 이전 step으로 만들어진 문서에 적용되는 방식임 - 이 방식은 동작하지만 여러 step의 위치 보정과 변경 범위 추적이 복잡해 다루기 어색함
- Wordgard는 CodeMirror의 변경 표현과 ShareJS의 “delta” 형식에서 온 방식을 바탕으로 더 단순한 모델을 사용함
- 문서 길이가 10일 때 위치 4에
L
을 삽입하면 [keep 4] [replace 0 with "L"] [keep 6]
으로 표현함
- 처음 두 문자를 삭제하면
[replace 2 with ""] [keep 8]
로 표현함
- 리치 텍스트 처리를 위해
변경 섹션을 추가해, 구조를 유지한 채 강조·링크 스타일·이미지 대체 텍스트 같은 마크를 추가하거나 제거할 수 있음 - 3부터 6까지의 단어를 굵게 만들면
[keep 3] [update 3 +bold] [keep 4]
로 표현함
- Wordgard는 ProseMirror와 같은
토큰 카운팅 인덱스를 사용해 노드 열기·닫기 토큰과 리프 토큰의 평평한 시퀀스로 문서 위치를 다룸 - 단일 트랜잭션은 항상 하나의 변경을 가지므로, 변경 합성과 검사·추론이 쉬워짐
- 제한적인
운영 변환을 지원해 같은 시작 문서를 기준으로 표현된 여러 변경을 병합할 수 있음 - 여러 변경을 가진 트랜잭션을 더 편하게 표현할 수 있음
- 협업 편집과 일부 변경만 되돌리는 undo history 구현에 활용 가능함
유효한 문서 구조를 유지하는 방식
-
Wordgard 문서는 단순한 토큰 시퀀스가 아니라 균형 잡힌 트리 구조여야 함
-
예를 들어 노드 닫기 토큰을 삭제하면 토큰 균형이 깨져 적용할 수 없는 변경이 만들어질 수 있음
-
변경 집합 생성 코드는 결과가
유효한 문서 구조가 되도록 변경을 검사하고 보정해야 함 -
운영 변환에서도 변환된 변경이 문서를 무효화하지 않아야 함
-
Wordgard의 변경 모델은 변환 중 결합 결과를 보정하는
fix-up change를 도출함 -
A-over-B와 B-over-A에 대해 같은 보정을 만들도록 입력을 조심해서 사용함
-
보정이 없으면 두 순서는 같은, 그러나 무효할 수 있는 문서를 만들 수 있음
-
같은 보정을 합성하면 두 순서 모두 같은 유효 문서로 수렴함
-
대부분의 변경은 보정이 필요 없지만, 필요한 경우에도 수렴성을 유지하도록 설계됨
스키마 조합과 마크 일반화
-
ProseMirror의 문서 스키마는 노드 간 관계를 직접 지정하므로 보통 손으로 설정해야 함
-
ProseMirror의 노드와 마크 타입은 특정 스키마 안에서만 존재하며, 스키마 사이에서 공유할 수 있는 노드 정체성이 없음
-
Wordgard에서는
노드·마크 타입이 독립 객체이며 여러 문서 스키마에 포함될 수 있음 -
이 객체들은 타입 지정과 자동완성을 지원하는 핸들처럼 동작해, 필요한 요소를 조합해 스키마를 만들기 쉬움
-
스키마는 기존 요소의 관계를 오버라이드할 수 있음
-
노드나 마크 정의는 기본 콘텐츠나 대상 타입을 지정함
-
같은 요소를 다르게 쓰고 싶을 때 스키마가 그 관계를 바꿀 수 있음
-
기본 내장 노드를 더 풍부하게 제공할 수 있어, 편집 지원 확장이나 메뉴 버튼 같은 시스템 통합을 해당 노드에 직접 붙이기 쉬움
-
텍스트 정렬이나 대체 텍스트처럼 특정 노드 속성으로 묶였던 기능은
마크 일반화를 통해 더 모듈식으로 추가할 수 있음 -
노드 타입 자체는 어떤 마크가 자신을 대상으로 하는지 알 필요가 없음
콘텐츠 제약을 완화한 이유
-
ProseMirror의 대표 기능인 정규식 기반 허용 콘텐츠 지정은 Wordgard에서 지원하지 않음
-
Wordgard의 노드 콘텐츠 설명은 어떤 자식 타입을 지원하는지만 제한하고, 그
순서는 제한하지 않음 -
정규식 기반 제약은 범용 문서 조작 코드를 작성하기 어렵게 만듦
-
특정 스키마에 맞춰 작성하지 않은 코드는 어떤 변환이 유효한지 거의 가정할 수 없음
-
모든 작업을 콘텐츠 제약과 대조해야 하며, 이 과정이 미묘하고 부담스러움
-
문서 형태를 강하게 잠그는 제약은 사용자가 의도한 형태로 가는 중간 편집 단계를 막아 사용자 경험을 해칠 수 있음
-
Wordgard는 더 느슨한 문서 형태 접근을 장려함
-
스키마 규칙을 넘어서는 불변 조건이 필요할 때는
correction 추상화를 제공함 -
허용하고 싶지 않은 문서 형태를 프로그램으로 보정함
-
콘텐츠 표현식 강제보다 더 지능적이고 문맥을 반영한 보정이 가능함
-
ProseMirror 제약으로도 표현할 수 없던 직사각형 테이블 보장 같은 조건에도 사용할 수 있음
확장 시스템: CodeMirror 6식 facet
-
ProseMirror의 확장 시스템은 플러그인이 여러 일을 맡고, 배열 순서가 우선순위에 영향을 주는 방식임
-
한 플러그인이 어떤 훅에서는 낮은 우선순위가 필요하고 다른 훅에서는 높은 우선순위가 필요한 상황이 생길 수 있음
-
CodeMirror의 facets 기반 시스템은 확장을 더 세밀하게 만들고, 각 확장 값이 자체 우선순위 범주를 설정할 수 있게 함
Facet은 타입이 지정된 확장 지점이며, 라이브러리 자체뿐 아니라 어떤 코드든 정의할 수 있음 -
Wordgard는 이 부분에서 CodeMirror의 시스템을 거의 그대로 가져오며, 상태 업데이트와 재구성 메커니즘도 포함함
-
구성은 플러그인 배열이 아니라
확장 트리임 -
이벤트 핸들러 정의
-
편집기 속성 설정
-
새 편집기 상태 추가
-
기능 구현은 보통 함께 동작하는 확장 묶음으로 구성됨
-
확장 번들은 대부분 구성에 넣기만 해도 잘 조합되도록 원시 요소가 설계됨
브라우저 의존성 축소와 선택 처리
-
ProseMirror의 많은 문제는 브라우저 네이티브 선택 동작에 의존하는 방식과 관련됨
-
기존 접근은 브라우저가 양방향 텍스트나 특이한 스타일의 콘텐츠에서 커서 이동을 처리하게 두고, 그 결과를 자체 선택 모델에 반영하는 방식이었음
-
실제 브라우저는 일부 콘텐츠를 지나 커서를 이동하지 않거나, 커서를 그리지 않거나, 잘못된 위치에 그리거나, 마우스 선택 드래그에서 이상 동작을 보일 수 있음
-
Wordgard는 포인터와 키보드 기반 선택을 거의 모두 직접 처리함
양방향 텍스트 처리를 구현함 -
콘텐츠 배치 모델을 만듦
-
커서를 직접 그림
-
터치 선택은 예외적으로 네이티브 구현을 사용함
-
다시 구현하면 네이티브 컨텍스트 메뉴가 깨지는 것으로 보임
-
휴대폰과 태블릿에서는 컨텍스트 메뉴를 대체하기 어려움
-
터치 선택은 키보드 선택보다 이상 동작이 덜한 편임
입력 이벤트 처리와 DOM 변경 감시 제거
- 지난 9년 동안 브라우저의 편집 이벤트 지원, 특히
beforeinput
지원은 더 일관돼짐
- 실제 사용 환경 테스트가 필요하지만, Wordgard는 ProseMirror가 의존한 DOM 변경 감시와 변경 콘텐츠 파싱 트릭 없이 동작할 수 있어 보임
- Wordgard는 조합 텍스트 입력을 제외한 모든 것에 대해
beforeinput
이벤트를 처리함
- 이 방식은 여러 지저분한 우회 구현이 필요한 문제군을 피함
안정성, 버전 계획, 라이선스
- Wordgard는 이전 프로젝트들이 발표 시점에 있던 상태보다 조금 더 진전된 상태임
- 핵심 인터페이스는 원하는 기능의 거의 전부를 지원하고, 설계가 실용적인지 확인하기 위한 여러 확장도 작성됨
- 문서는 아직 다소 거칠지만
참조 매뉴얼은 완성되어 사용할 수 있음 - 실제 작업에 사람들이 사용하기 전까지는 많은 문제가 드러나지 않을 수 있음
- 앞으로 추가하고 싶은 기능이 있으며, 공개 후 다른 사람들도 살펴보기를 기대함
- 공개 인터페이스 일부는 더 많은 통찰에 따라 다시 생각해야 할 수 있음
- 첫 버전은 0.1이며, 피드백 수집·버그 수정·거친 부분 정리를 위해 한동안 0.x 버전에 머물 예정임
- 라이선스는 이전 프로젝트들과 마찬가지로
MIT임 - 더 제한적인 라이선스도 고려했지만, 널리 사용되는 쪽에 더 관심이 있어 허용적 라이선스를 선택함
AI 모델, 코드 생성, 풀 리퀘스트 정책
- 이 소프트웨어를 만드는 데
언어 모델은 사용되지 않음 - JavaScript 코드가 웹에 있고 문서가 공개되어야 하므로, 공개된 코드와 아이디어가 대형 언어 모델에 들어가는 것을 막을 신뢰할 만한 방법은 없다고 봄
- Wordgard에서는 표준 오픈소스 관행과 달리 pull request를 받지 않는 실험을 함
- 큰 변경을 리뷰하고 기대에 맞도록 조정하는 과정은 직접 구현하는 것보다 더 많은 일이 될 때가 많음
- 코드 생성 비용이 크게 낮아지면서, 다른 사람이 코드를 던지고 관리자가 리뷰·유지보수하거나 거절 이유를 설명해야 하는 구조가 더 매력적이지 않게 됨
댓글과 토론
AI 자동 생성 콘텐츠
본 콘텐츠는 GeekNews의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기