타자연습을 다시 제품처럼 만든 며칠의 기록
타자연습은 처음부터 큰 제품으로 출발한 기능은 아니었다. oh-my-zhs 안에 넣을 수 있는 실용 도구 중 하나였고, 처음 목표도 단순했다. 지문을 보여주고, 입력을 받고, 타수와 정확도를 계산하면 된다. 겉으로 보면 그 정도면 충분해 보인다.
타자연습은 처음부터 큰 제품으로 출발한 기능은 아니었다. oh-my-zhs 안에 넣을 수 있는 실용 도구 중 하나였고, 처음 목표도 단순했다. 지문을 보여주고, 입력을 받고, 타수와 정확도를 계산하면 된다. 겉으로 보면 그 정도면 충분해 보인다.
그런데 실제로 손을 올려놓고 몇 번 쳐보면 금방 티가 난다. 타자연습은 계산기가 아니다. 결과만 맞으면 되는 도구가 아니라, 입력하는 동안의 리듬이 거의 전부인 도구다. 첫 키를 누르는 순간 화면이 끊기거나, 한 문장을 끝낼 때마다 포커스가 풀리거나, 입력해야 할 글자가 좁은 창 안에서 갑자기 밀려나면 사용자는 더 이상 연습을 하고 있다고 느끼지 않는다.
이번 작업은 그 지점을 다시 보는 과정이었다. 5월 5일 방문자 통계를 붙이는 작업에서 시작해, 타자연습 로비와 집중 화면을 분리하고, 문단형 입력면을 만들고, 한글 자모 진행 표시를 고치고, 장문/필사 콘텐츠를 정리하고, 자리연습과 워드 디펜스까지 손봤다. 마지막에는 메인 화면 문구도 다시 썼다. 기능은 들어갔지만 서비스처럼 말하지 못하는 문장들이 남아 있었기 때문이다.
이 글은 그 며칠간의 작업을 회고하는 기록이다. 한 명의 휴먼 오케스트레이터가 방향과 품질 기준을 계속 던지고, Hermes Agent가 그 요구를 작업 단위로 쪼개고, 코드와 브라우저를 오가며 실제 제품에 가까워지도록 다듬은 과정이다.
시작은 방문자 통계였다
처음 작업은 화려하지 않았다. GA4와 Vercel Analytics를 붙여 방문자 통계를 볼 수 있게 만드는 일이었다. 커밋 메시지도 담백했다. feat: enable ga4 tracking.
하지만 이 작업은 단순히 스크립트 하나를 넣는 일이 아니었다. 공개 사이트를 만들고 있다면, 어느 페이지에 사람이 들어오는지, 어떤 도구가 실제로 쓰이는지, 어느 지점에서 이탈하는지 볼 수 있어야 한다. 감으로만 운영하면 계속 기능을 추가하면서도 정작 사용자가 보는 화면은 나빠질 수 있다.
타자연습도 마찬가지였다. 누군가 /typing에 들어왔을 때 만나는 첫 화면이 중요한데, 당시 화면은 기능이 모여 있는 페이지에 가까웠다. 설명, 입력, 설정, 지표가 한꺼번에 섞여 있었다. 내부적으로는 많은 것이 들어갔지만, 밖에서 들어온 사람에게는 “여기서 무엇을 하면 되는지”가 또렷하지 않았다.
휴먼 오케스트레이터의 첫 방향은 여기서 나왔다. 이제는 방문자가 들어오는 사이트이니, 타자연습도 실험 페이지처럼 두면 안 된다. 실제 서비스처럼 보여야 한다. 입력 화면과 소개 화면의 역할을 나눠야 한다.
로비와 연습 화면을 분리했다
Hermes Agent가 먼저 한 일은 구조를 읽는 것이었다. /typing이 어떤 컴포넌트를 쓰는지, 각 모드가 어디서 렌더링되는지, 세션 상태와 설정 rail이 어디에 붙어 있는지 확인했다. 그 다음 작업을 둘로 나눴다.
하나는 로비였다. 사용자가 처음 들어와서 낱말연습, 단문연습, 장문/필사, 자리연습, 워드 디펜스 중 무엇을 할지 고르는 화면이다. 이 화면은 설명과 선택을 맡아야 한다. 현재 기록이 있다면 대시보드처럼 보여주고, 기록이 없다면 어디서 시작하면 좋을지 알려줘야 한다.
다른 하나는 집중 화면이었다. 실제로 타자를 치는 화면에서는 설명이 적을수록 좋다. 손을 키보드에서 떼게 만드는 장식은 줄이고, 지문과 입력, 현재 지표, 최소한의 설정만 남겨야 한다.
이 분리는 작지만 중요했다. 많은 웹 도구가 여기서 실패한다. 한 페이지 안에 소개문, 기능, 광고성 문구, 설정, 결과를 모두 넣다 보니 사용자는 무엇을 해야 할지 모른다. 타자연습에서는 그 혼란이 더 크게 느껴진다. 입력은 계속 이어져야 하는데 화면이 사용자를 계속 멈춰 세우기 때문이다.
typing.works를 참고했지만 그대로 베끼지는 않았다
다음 요청은 더 구체적이었다. 기존 타자연습은 지문을 현재 줄과 다음 줄 정도만 보여줬다. 사용자는 더 넓은 문단을 보며 입력하고 싶어 했다. 참고 대상으로 typing.works가 언급됐다.
Hermes Agent는 먼저 벤치마크를 했다. typing.works는 큰 textarea를 보여주기보다, 지문 자체가 입력면처럼 느껴지는 구조였다. 단어와 글자를 span 단위로 나누고, 현재 위치와 오타 상태를 문단 위에 바로 표시한다. 사용자는 입력창에 글을 쓰는 느낌보다 지문을 직접 따라 치는 느낌을 받는다.
그대로 복제하지는 않았다. oh-my-zhs의 타자연습은 한글 입력을 다뤄야 했고, IME 조합 중인 글자를 어떻게 보여줄지가 중요했다. 그래서 새 입력면은 MultilineTypingSurface라는 별도 컴포넌트로 분리했다. 실제 textarea는 입력을 안정적으로 받는 역할을 하고, 화면에는 문단형 target overlay가 중심으로 보이게 했다.
결과적으로 낱말, 단문, 장문, 속도측정은 같은 계열의 문단형 입력 경험을 공유하게 됐다. 자리연습은 예외로 남겼다. 자리연습은 문장을 읽는 훈련이 아니라 지금 눌러야 할 키를 몸에 익히는 훈련이기 때문에, 같은 문단형 화면을 억지로 적용하면 오히려 목적이 흐려진다.
이 판단이 이번 작업의 핵심 중 하나였다. 좋은 참고 서비스가 있어도, 그대로 가져오면 좋은 제품이 되지는 않는다. 왜 그 UX가 좋은지 이해한 뒤, 우리 서비스의 입력 방식과 콘텐츠 구조에 맞게 다시 만들어야 한다.
한글은 완성된 글자만 보면 늦다
이번 업그레이드에서 가장 타자연습다운 문제는 한글 자모 진행 표시였다.
예를 들어 목표 글자가 상이라고 해보자. 사용자가 실제로 누르는 것은 한 번의 키가 아니다. ㅅ, ㅏ, ㅇ이 순서대로 들어가고, IME는 그 과정을 거쳐 하나의 음절을 만든다. 일반적인 문자열 비교만 하면 상이 완성되기 전까지는 화면이 애매하게 반응한다. 사용자는 분명 입력하고 있는데, 서비스는 아직 아무것도 모르는 것처럼 보일 수 있다.
휴먼 오케스트레이터가 요구한 것은 이 지점이었다. 상을 치는 동안 그 자리에서 ㅅ, 사, 상으로 진행되는 느낌이 보여야 한다. 완성된 문자만 나중에 밝아지는 방식으로는 한글 타자연습의 손맛이 부족하다.
Hermes Agent는 target과 typed를 자모 단위로 비교하는 쪽으로 문제를 다시 잡았다. 현재 음절 cell에는 partial composition을 보여주고, 이미 입력된 영역과 아직 입력하지 않은 영역, 오타 영역을 분리했다. 이건 단순한 시각 효과가 아니다. 사용자가 “내 입력이 제대로 따라오고 있다”고 느끼게 만드는 피드백이다.
타자연습에서 피드백은 점수보다 먼저 온다. 점수는 끝난 뒤의 기록이지만, 자모 진행 표시는 입력 중인 손을 계속 붙잡아준다.
지표는 많을수록 좋은 게 아니었다
타자연습에는 숫자가 많다. 타/분, 정확도, 정타수, 오타수, 최고타수, 평균타수, 시간. 숫자를 많이 보여주면 더 전문적인 서비스처럼 보일 수 있지만, 범위가 섞이면 오히려 신뢰가 떨어진다.
기존 UI에서는 현재 지문에서 나온 값과 이번 연습 전체의 누적 값이 섞여 보일 여지가 있었다. 사용자는 지금 보고 있는 최고타수가 방금 친 문장의 최고인지, 세션 전체 최고인지 헷갈릴 수 있었다.
그래서 지표를 두 층으로 나눴다.
현재 지문 결과에는 지금 치고 있는 지문에 대한 값만 둔다. 타/분, 순간최고타수, 정타수, 오타수, 정확도, 시간. 이번 연습 결과에는 세션 단위 집계를 둔다. 지문수, 평균타수, 최고타수, 최저타수, 전체 정타수와 오타수, 정확도, 시간.
이 변경은 화려하지 않지만 제품 신뢰도와 관련이 있다. 좋은 도구는 숫자를 많이 보여주는 도구가 아니라, 숫자가 무엇을 뜻하는지 헷갈리지 않게 만드는 도구다.
장문 모드는 긴 글이 있어야 장문 모드다
장문/필사도 다시 봤다. 이름은 장문인데 실제 지문이 100자 안팎이면 사용자가 기대하는 연습과 맞지 않는다. 짧은 글을 많이 넣으면 페이지는 풍성해 보일 수 있지만, 모드의 이름과 경험이 어긋난다.
이번에는 얇은 카테고리를 억지로 유지하지 않는 쪽을 선택했다. 1000자 안팎의 글을 제공할 수 있는 카테고리를 중심으로 남기고, 사용자가 카테고리와 제목을 보고 직접 필사할 글을 고를 수 있게 했다.
이건 콘텐츠 운영의 문제이기도 하다. 사이트를 풍성하게 보이게 하려고 얇은 항목을 많이 늘어놓으면, 처음에는 좋아 보인다. 하지만 사용자가 클릭했을 때 기대한 경험이 없으면 신뢰가 줄어든다. 장문/필사는 “긴 글을 끝까지 치는 호흡”이 핵심이다. 그 핵심을 맞추지 못하는 콘텐츠는 덜어내는 편이 낫다.
자리연습은 누적 입력보다 즉각 피드백이 중요했다
자리연습도 별도로 손봤다. 기존 target은 좌에서 우로, 다시 우에서 좌로 이어지는 식의 단조로운 반복이 강했다. 처음에는 학습 순서처럼 보일 수 있지만, 몇 번 반복하면 손가락 위치를 외운다기보다 화면의 순서를 외우게 된다.
그래서 stage별 target을 seed 기반으로 섞었다. 완전히 무작위로 흐트러뜨리는 것이 아니라, 해당 단계에서 익혀야 할 키를 충분히 포함하면서도 순서 예측이 줄어들도록 했다.
입력 표시도 바꿨다. 자리연습에서는 사용자가 친 자모가 큰 입력란에 계속 쌓일 필요가 없다. 중요한 것은 지금 어떤 키를 눌러야 하는지, 방금 누른 키가 맞았는지다. 그래서 입력할 자리 근처에 작은 입력 표시를 두고, 현재 stroke만 짧게 보인 뒤 다음 target으로 넘어가면 비워지게 했다.
문장 입력과 자리연습은 같은 “타자연습” 안에 있지만 보는 지점이 다르다. 하나는 흐름이고, 다른 하나는 반응이다. 같은 UI를 강제로 쓰지 않는 것이 더 자연스러웠다.
워드 디펜스는 입력창을 없애고 조준감을 살렸다
워드 디펜스는 이번 작업에서 가장 게임에 가까운 부분이었다. 기존에는 Phaser 안에서 절차적으로 그린 우주선과 운석이 있었고, 입력은 하단의 넓은 input에 가까웠다. 기능적으로는 단어를 입력해 운석을 부순다고 말할 수 있었지만, 화면상으로는 입력과 게임 오브젝트가 떨어져 있었다.
휴먼 오케스트레이터의 요구는 명확했다. 하단 full-width 입력창은 빼고, 우주선 근처에 최대 다섯 글자 정도 보이는 작은 입력 박스를 붙여야 한다. 단어 입력을 시작하면 그 단어 아래로 우주선과 입력 박스가 이동해야 한다. 그리고 사용자가 제공한 이미지 파일에서 스프라이트를 분리해서 실제 게임 asset으로 써야 한다.
Hermes Agent는 작업을 asset 분석과 코드 구현으로 나눴다. game-static-sheet.jpeg에서는 우주선, 운석, gem 후보를 분리했다. magenta 배경은 chroma key로 투명 처리했다. space-bg.png는 배경으로 연결했다. explosion.jpeg는 처음에 4×4 grid로 가정했다가 다시 분석했다.
여기서 중요한 실수가 하나 있었다. explosion 이미지는 문제가 있는 파일이 아니었다. 구조가 단순 4×4가 아니었을 뿐이다. 상단에는 128×128 frame 16개가 있고, 하단에는 256×256 frame 12개가 있는 mixed atlas였다. 4×4로 자르면 상단 frame들이 한 칸 안에 여러 개씩 섞여 보인다. 그래서 다시 28개 frame을 추출하고, 모두 256×256 canvas에 맞춰 repack한 뒤 Phaser spritesheet로 재생하도록 고쳤다.
이 과정은 생성 asset을 제품에 넣을 때 자주 생기는 문제를 잘 보여준다. 이미지를 만들었다고 바로 게임 asset이 되는 것은 아니다. crop, 투명 처리, naming, public path, fallback, animation frame 재구성이 필요하다. AI가 만든 이미지든 사람이 만든 이미지든 제품 안에서 쓰려면 제품 asset으로 가공해야 한다.
입력 UX도 바뀌었다. React overlay가 작은 입력 박스를 그리고, Phaser scene은 현재 target의 좌표를 aim event로 전달한다. 사용자가 입력을 시작하면 active target을 잡고, 우주선과 입력 박스가 해당 단어 아래로 이동한다. 이제 사용자는 하단 입력창에 문자를 넣는 것이 아니라, 우주선으로 단어를 조준하고 있다는 느낌을 받는다.
마지막으로 문장 자체를 다시 썼다
기능을 고친 뒤에도 한 가지 문제가 남았다. /typing 메인 화면의 문구였다.
기존 문구는 나쁘다기보다 너무 방어적이었다. “로비에서 고르고, 집중 화면에서 입력하세요” 같은 식이었다. 개발자가 작업 내용을 설명하는 문장이지, 품질 높은 타자연습 서비스를 소개하는 문장은 아니었다. 휴먼 오케스트레이터는 이 지점을 바로 짚었다. 요청한 사항만 반영하기 위해 억지로 만들어놓은 문구처럼 보인다고 했다.
그래서 카피를 다시 썼다. 관점을 바꿨다. “우리가 무엇을 구현했는가”가 아니라 “사용자는 왜 이 서비스를 써야 하는가”를 먼저 놓았다.
새 hero는 이렇게 시작한다.
그리고 설명은 기능 목록이 아니라 학습 순서를 말한다. 두벌식 자리, 낱말 리듬, 문장 정확도, 장문 호흡, 게임형 순발력. 타자 속도는 숫자를 억지로 밀어 올리는 것이 아니라 손이 기억하는 순서를 만드는 일이라는 메시지로 잡았다.
이건 단순한 문장 수정이 아니었다. 제품이 스스로를 어떻게 소개할지 정하는 작업이었다. 좋은 기능도 소개가 어색하면 미완성처럼 보인다. 반대로 서비스가 어떤 문제를 해결하는지 또렷하게 말하면, 같은 기능도 더 믿을 만한 제품처럼 보인다.
Hermes Agent가 한 일과 사람이 계속 봐야 했던 일
이번 작업에서 Hermes Agent가 잘한 것은 넓은 요청을 실행 가능한 단위로 쪼개는 일이었다.
먼저 repo 상태를 확인하고, 브랜치를 나눴다. 관련 파일을 찾고, 기존 구조를 읽었다. typing.works 벤치마크를 문서로 남기고, 문단형 입력면과 자모 진행 표시를 구현했다. 장문 콘텐츠와 자리연습을 분리해 다뤘고, Word Defense는 asset 처리와 Phaser scene 연결을 나눠 접근했다. 수정 뒤에는 lint와 build를 돌리고, production start 상태에서 브라우저 QA를 했다.
하지만 이것만으로는 부족했다. 사람이 계속 봐야 하는 지점이 있었다.
첫째, 요구의 방향이다. “타자연습을 좋게 해줘”만으로는 부족하다. 실제로는 “연습 흐름이 끊기지 않아야 한다”, “문장 결과와 이번 연습 결과는 분리되어야 한다”, “하단 입력창은 게임 감각을 해친다”처럼 제품 판단이 필요했다.
둘째, 품질 감각이다. 카피가 AI가 쓴 것처럼 보인다는 지적은 자동 테스트로 잡히지 않는다. lint도 build도 통과하지만, 사용자가 보면 허술하게 느껴지는 부분이다. 이건 사람이 서비스를 보는 눈으로 잡아야 한다.
셋째, 잘못된 가정의 수정이다. explosion sheet를 4×4라고 가정한 일처럼, 에이전트도 그럴듯한 구조를 빠르게 선택할 때가 있다. 이때 중요한 것은 변명하지 않고 다시 이미지를 보고, 실제 구조에 맞게 pipeline을 고치는 것이다.
AI 에이전트는 손이 빠른 작업자에 가깝다. 하지만 제품의 책임자는 아니다. 이번 작업에서 좋은 결과가 나온 이유는 사람이 계속 “이건 제품처럼 보이지 않는다”, “이 흐름은 어색하다”, “이 asset은 실제로 써야 한다”고 기준을 세웠기 때문이다.
기대하는 효과
이번 업그레이드로 타자연습은 단순 입력 도구에서 조금 더 제품에 가까워졌다.
사용자는 /typing에서 각 모드의 역할을 이해하고 들어갈 수 있다. 실제 연습 화면에서는 설명보다 입력이 중심이 된다. 한글 자모 진행 표시 덕분에 조합 중인 입력도 더 자연스럽게 보인다. 현재 지문과 이번 연습 결과가 분리되어 기록의 의미가 명확해졌다. 장문/필사는 이름에 맞는 긴 글 중심으로 정리됐다. 자리연습은 현재 키에 집중하고, 워드 디펜스는 입력과 게임 오브젝트가 한 화면에서 연결된다.
운영 관점에서도 의미가 있다. 방문자 통계를 붙인 뒤, 사람이 들어왔을 때 가장 오래 머물 수 있는 반복형 기능을 다듬었다. 사이트 안에 한 번 쓰고 떠나는 도구만 있는 것이 아니라, 매일 조금씩 다시 열어볼 수 있는 연습 공간이 생겼다.
그리고 글감도 남았다. 이 작업은 단순 업데이트 공지가 아니라, 실제 제품을 만들어가는 방식에 대한 기록이다. 휴먼 오케스트레이터가 문제를 발견하고, Hermes Agent가 작업을 구체화하고, 코드와 문구와 asset을 모두 제품 맥락 안에서 다시 맞추는 과정이었다.
남은 일
아직 끝난 것은 아니다. 공개 랭킹, 계정 동기화, 약점 키 기반 추천, 장문 콘텐츠 확장, 모바일 입력 검증 같은 과제가 남아 있다. Word Defense도 폭발 animation이나 target priority를 더 다듬을 수 있다. 타자연습 메인 카피 역시 실제 방문자 반응을 보며 계속 손봐야 한다.
그래도 이번 작업으로 기준은 잡혔다. 타자연습은 더 이상 “사이트 안에 들어 있는 작은 기능”이 아니라, oh-my-zhs가 반복 사용을 기대할 수 있는 하나의 연습 제품이 됐다. 앞으로의 개선도 이 기준에서 출발하면 된다.
사람은 방향을 잡고, 에이전트는 실행을 넓힌다. 이번 타자연습 업그레이드는 그 역할 분담이 꽤 잘 맞아떨어진 사례로 남길 만하다.
Related posts
Read →Related tools