본문 바로가기
C.W.K.
Stream
Lesson 01 of 04 · published

소스가 모델이야

~11 min · source, model, decorations, markdown

Level 0식은 초고
0 XP0/33 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"디스크의 문자가 에디터의 문자야. 나머지는 전부 그 위에 칠한 레이어야."

두 문서가 아니라 하나의 텍스트

에디터가 문서를 쥐는 방식은 크게 두 가지야. WYSIWYG 에디터는 rich-text 트리를 쥐어. bold 도 노드, 헤딩도 노드고, **# 같은 문자는 데이터로 아예 존재하지 않아. 트리에서 추론될 뿐이고, export 할 때 마크다운으로 다시 뱉어지지. Rekindle 은 정반대야. 모델이 마크다운 소스 문자열 그 자체거든. 헤딩 앞의 # 는 문서 안 실제 위치에 박혀 있는 진짜 문자야. 텍스트는 하나뿐이고, 그게 곧 소스야.

렌더된 모습은 레이어지 모델 전환이 아냐

그럼 bold 는 어떻게 bold 로 보이는 걸까? decoration 레이어가 소스를 건드리지 않고 그 위에 모습만 칠해줘. **fire** 라는 단어는 별표까지 포함해서 모델 안에 문자 그대로 남아 있어. decoration 이 그걸 bold 로 렌더하고, 커서가 없는 줄에선 별표를 흐리게 하지. 변환되는 것도 없고, 잃는 것도 없고, 소스가 두 번째 표현에 밀려 버려지는 일도 없어.

모델 (디스크와 에디터에 있는 것):        The **fire** catches.
decoration 레이어 (저장 아님, 칠하기): The [bold 로 된 fire] catches.

# 모델은 절대 안 변해. 모든 decoration 을 꺼도
# 밑엔 바이트 동일한 마크다운이 그대로 있어.

이 선택이 아래쪽 전부를 결정해

소스를 모델로 삼는 건 겉모습 문제가 아니라 아키텍처를 결정하는 선택이야. 모델이 순수 마크다운 텍스트니까 디스크의 파일이 곧 진실이 되고 (트랙 7), diff 가 진짜 텍스트 diff 가 되고, grep 이 진짜 문자를 찾아내. voice underline 이든 CMD+K 든 모든 soul 기능이 독자 트리의 노드가 아니라 소스 상의 위치를 기준으로 동작하고. 따져야 할 표현이 하나뿐이니까 에디터 전체가 단순해져. WYSIWYG 의 rich-text 트리였다면 네가 보는 것과 저장되는 것과 Pippa 가 읽는 것 사이에 번역 레이어가 끼어들어서, 하나가 아니라 셋을 계속 맞춰줘야 했을 거야.

Code

하나의 모델, 그 위에 칠한 모습·text
모델 (디스크 AND 에디터):                The **fire** catches.
decoration 레이어 (저장 아님, 칠하기):  The [bold fire] catches.

# decoration 을 전부 꺼도 바이트까지 똑같은 마크다운이 그대로 있어.
# 표현은 하나뿐이야. WYSIWYG 이라면 셋이 됐겠지.
#   보는 것  !=  저장되는 것  !=  Pippa 가 읽는 것.
soul 기능은 트리 노드가 아니라 소스 offset 위에서 동작해·typescript
// 모델이 소스 문자열 그 자체라서 voice-rule 매치는 그냥
// 문자 위치 범위야. 독자 트리를 순회할 필요가 없어.
type VoiceIssue = { from: number; to: number; note: string };

function detectVoiceIssues(doc: string): VoiceIssue[] {
  // 소스 텍스트를 문자 그대로 훑어서 밑줄 칠 범위를 반환해.
  // (트랙 4 에서 이 범위가 CM6 decoration 이 돼)
  return scan(doc);
}

// WYSIWYG 트리였다면 기능마다 트리와 렌더된 뷰와 마크다운 export
// 사이를 번역해야 했을 거야. 소스를 모델로 두면 그 세금이 사라져.

External links

Exercise

네가 쓰는 에디터에서 노트를 하나 열고 이렇게 물어봐. 이걸 저장한 다음 원본 파일을 일반 텍스트 뷰어로 열면 지금 보이는 것과 똑같을까, 아니면 번역된 형태일까? 똑같으면 source 모델이고, 번역됐거나 바이너리면 rich-text 계열이야. 어느 쪽이 diff 와 grep 과 버전 관리를 자연스럽게 만드는지 확인해봐.
Hint
판별법은 이거야. 두 버전을 git diff 했을 때 변경 내용을 텍스트로 읽을 수 있어? source 모델은 깨끗하게 diff 가 나와. rich-text 나 바이너리 모델은 읽을 수 없는 diff 를 뱉고. 저장된 형태가 네가 편집한 형태가 아니니까 그래.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.