본문 바로가기
C.W.K.
Stream
Lesson 03 of 05 · published

Cmd+Z 한 번이 전체를 되돌려야 해

~10 min · undo, single-action, pasteboard, ux

Level 0불씨 없음
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"깔끔히 못 되돌리는 받아쓰기는 쓰기 무서운 받아쓰기야."

되돌리기는 제품의 일부

Firekeeper 가 텍스트를 문서에 떨구고 나면, 바로 다음에 오는 감정이 후회일 수도 있어. 창을 잘못 봤거나, 문장을 잘못 알아들었거나, 그냥 마음이 바뀌었거나. 그 되돌리기 의 품질은 나중에 붙일 곁다리가 아니라 진짜 기능이야. 목표는 단순하고 엄격해. 타깃 앱에서 Cmd+Z 한 번이 삽입 전체를 한 단계로 되돌려서, 받아쓰기 직전 상태를 그대로 되살리는 것.

왜 한 번에 넣어야 하나

되돌리기 품질은 어떻게 삽입하느냐에서 그대로 따라 나와. 한 번에 붙여넣기나 한 번에 접근성 교체를 하면 타깃 앱에서 되돌릴 수 있는 동작 하나로 등록돼. 그래서 Cmd+Z 한 번이 전부를 무르지. 문자 하나씩 넣으면 정반대야. 합성한 키 입력 하나하나가 자기만의 되돌리기 단계가 될 수 있어서, 문장 하나 무르려고 Cmd+Z 를 스무 번 두드리게 돼. 게다가 앱마다 묶는 방식이 달라서 예측도 안 되고. 사다리가 가능한 곳마다 키 이벤트보다 붙여넣기랑 AX 교체를 좋아하는 구체적인 이유가 바로 이거야. 속도만이 아니라 되돌리기가 온전한지가 걸려 있거든.

단일 붙여넣기 / AX 교체  ->  되돌리기 1단계   -> Cmd+Z 한 번이 이전 상태 복원
문자 하나씩              ->  되돌리기 N단계   -> Cmd+Z 두드리기, 예측 불가

# 고르는 삽입 방법이 곧 배포하는 되돌리기 경험이야.

일부러 만든 예외

Firekeeper 가 일부러 더 나쁜 되돌리기를 받아들이는 자리가 딱 하나 있어. 터미널 프로파일이야. 긴 터미널 받아쓰기는 가끔 청크나 줄 단위로 들어가. 텍스트가 숨은 블록 하나로 툭 떨어지는 대신 눈에 보이고 손댈 수 있게 남으라고. 청크로 넣으면 되돌리기가 조각나. 진짜 비용이지. 그런데 터미널에선 실행하기 전에 눈으로 보고 고칠 수 있다는 게 깔끔한 한 방 되돌리기보다 값져. 중요한 건 이 맞바꿈을 골랐고 범위도 정해 뒀다 는 거야. 어쩌다 걸린 게 아니라. 터미널 프로파일만 빼면 어디서나 한 번에 넣기가 되돌리기를 지켜.

동작을 어떻게 하느냐가 그 되돌리기의 품질을 정해. 어떤 연산을 한 단계로 되돌리고 싶으면, 작은 것들을 줄줄이 흘리지 말고 원자적인 동작 하나로 해. 되돌리기가 온전한 건 나중에 얹는 별도 기능이 아냐. 애초에 변경을 어떤 방식으로 하기로 골랐는지에서 따라 나오는 성질이야.
되돌리기를 깎아먹는 맞바꿈은 명시적이고 좁게 만들어. 더 나쁜 되돌리기를 받아들여야 할 때, 그러니까 터미널에 청크로 넣어야 할 때 같은 경우엔, 필요한 자리에만 정확히 가두고 이유를 알고 있어. 이름 붙이고 범위 정한 맞바꿈은 설계 결정이야. 같은 걸 아무 데나 얼떨결에 적용하면, 화난 유저 신고로 다시 발견하게 될 버그고.

Code

삽입은 원자적으로, 청킹은 골라 둔 자리에서만·swift
// 기본: 원자적 액션 하나라 Cmd+Z 가 받아쓰기 전체를 무름.
func insertAtomic(_ text: String, into t: TargetSnapshot) async -> Bool {
    if t.category.axReliable { return await axReplace(text, in: t.focusedElement) }
    return await pasteInsert(text, into: t)   // 단일 붙여넣기 = 단일 되돌리기
}

// 터미널 프로파일만: 가시성 위해 청크/줄별,
// 먼저 보고 편집할 능력을 위해 깔끔한 되돌리기를 알면서 맞바꿈.
func insertTerminal(_ text: String, into t: TargetSnapshot) async {
    for line in text.split(whole: true) {
        await keyEventInsert(line, into: t)   // 되돌리기 조각냄 -- 여기선 받아들임
    }
    // 유저가 명시적으로 요청 안 하면 Enter 절대 자동으로 안 누름.
}

External links

Exercise

네 작업에 한꺼번에 큰 변경을 가하는 도구를 떠올려봐. 찾아 바꾸기, 대량 가져오기, 자동 포매터 같은 거. 되돌리기 한 번이 변경 전체를 무를까, 아니면 조각조각 물러야 할까? 그 도구가 어떻게 구현했길래 그런 되돌리기 경험이 나왔는지 적어보고, 어느 쪽이 도구를 더 믿게 만드는지도 생각해봐.
Hint
되돌리기 동작 하나로 등록되는 대량 연산은 마음이 놓여. Cmd+Z 한 번이 구해 주니까 마음껏 실험하게 되고. 되돌리기를 조각내는 도구는 조심하게 만들어. 무르는 게 지루하고 결과도 확실치 않으니까. 이 신뢰 차이는 결국 변경을 원자적인 동작 하나로 했는지 작은 것들을 줄줄이 흘렸는지로 그대로 거슬러 올라가.

Progress

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

댓글 0

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

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