개발자라면 누구나 한 번쯤 “타자 속도가 빠르면 코딩도 빨라질까?”라는 생각을 해봤을 겁니다. 물론 코딩은 생각하는 시간이 더 많지만, 막힘없이 코드를 쳐내려가는 느낌은 꽤나 중독적이죠.
하지만 일반적인 타자 연습 사이트의 문장들은 개발자에게 큰 도움이 되지 않습니다. 우리는 function, return, import 같은 키워드와 괄호 {}, ()를 훨씬 더 많이 쓰니까요.
그래서 만들었습니다. 개발자를 위한, 개발자에 의한 타자 연습기!
🎮 직접 해보세요
아래 창에서 바로 시작할 수 있습니다. 실제 코드(JavaScript, Python, Java 등)가 무작위로 나옵니다.
DevTyper
Type the code exactly as shown.
Press Tab to restart quickly (not implemented yet)
0 / 252 chars
🛠️ 어떻게 만들었나요?
이 프로젝트는 React와 Framer Motion을 사용하여 만들었습니다. 초보자도 이해할 수 있도록 단계별로 설명하겠습니다.
전체 구조
먼저 타자 연습기가 어떻게 동작하는지 전체적인 흐름을 살펴보겠습니다.
graph TD
A[게임 시작] --> B[코드 스니펫 선택]
B --> C[사용자 입력 대기]
C --> D{입력한 문자가<br/>정답과 일치?}
D -->|일치| E[초록색 표시<br/>콤보 증가]
D -->|불일치| F[빨간색 표시<br/>콤보 초기화]
E --> G{모든 문자를<br/>입력했는가?}
F --> G
G -->|아니오| C
G -->|예| H[결과 화면 표시<br/>속도/정확도]
H --> I{다시 시작?}
I -->|예| B
I -->|아니오| J[종료]
1. 상태 관리 (State Management)
React에서 가장 중요한 것은 상태(state) 관리입니다. 타자 게임에서 관리해야 할 상태들은 다음과 같습니다.
const [gameState, setGameState] = useState('start'); // 'start', 'playing', 'finished'
const [selectedLanguage, setSelectedLanguage] = useState('All'); // 선택된 언어
const [input, setInput] = useState(''); // 사용자가 입력한 텍스트
const [wpm, setWpm] = useState(0); // 타자 속도
const [accuracy, setAccuracy] = useState(100); // 정확도
const [combo, setCombo] = useState(0); // 현재 콤보
이 상태들이 어떻게 연결되어 있는지 다이어그램으로 이해해봅시다.
graph LR
A[사용자 입력] --> B[input 상태 업데이트]
B --> C[정확도 계산]
B --> D[속도 계산]
B --> E[콤보 계산]
C --> F[화면에 표시]
D --> F
E --> F
2. 실시간 피드백 시스템
사용자가 타이핑하는 순간마다 즉각적인 피드백을 제공합니다. 이것이 타자 게임의 핵심입니다!
sequenceDiagram
participant 사용자
participant 입력필드
participant 비교로직
participant 화면
사용자->>입력필드: 문자 입력 (예: 'c')
입력필드->>비교로직: 입력값 전달
비교로직->>비교로직: 타겟 코드와 비교
alt 정답
비교로직->>화면: 초록색 표시
비교로직->>비교로직: 콤보 +1
else 오답
비교로직->>화면: 빨간색 표시
비교로직->>비교로직: 콤보 초기화
end
화면->>사용자: 시각적 피드백
코드로 구현하면 다음과 같습니다:
const handleInput = (e) => {
const value = e.target.value;
const targetCode = currentSnippet.code;
setInput(value);
// 각 문자마다 정답 확인
for (let i = 0; i < value.length; i++) {
if (value[i] === targetCode[i]) {
// 정답: 초록색 표시
correctChars++;
} else {
// 오답: 빨간색 표시
isError = true;
}
}
};
3. 자동 들여쓰기 기능
코드를 칠 때 가장 번거로운 것이 바로 들여쓰기입니다. 엔터를 누를 때마다 자동으로 들여쓰기를 채워넣는 기능을 추가했습니다.
flowchart TD
A[사용자가 Enter 입력] --> B{다음 줄에<br/>공백이 있나?}
B -->|있음| C[공백의 개수 계산]
C --> D[자동으로 공백 추가]
D --> E[커서를 들여쓰기 뒤로 이동]
B -->|없음| F[그냥 줄바꿈만]
구현 코드:
if (lastChar === '\n') {
// 다음 줄의 들여쓰기 확인
const targetSubstring = targetCode.substring(lastCharIdx + 1);
const match = targetSubstring.match(/^ +/); // 공백 찾기
if (match) {
const indentation = match[0]; // 공백 개수
setInput(value + indentation); // 자동으로 추가!
}
}
4. 속도 계산 (WPM → CPM)
타자 게임에서 가장 중요한 속도 측정! 우리는 CPM(분당 타수)을 사용합니다.
graph LR
A[시작 시간 기록] --> B[현재 시간 - 시작 시간]
B --> C[경과 시간 계산]
C --> D[입력한 문자 수 / 경과 시간]
D --> E[분당 타수 CPM 계산]
E --> F[화면에 'XXX타' 표시]
useEffect(() => {
if (gameState === 'playing' && startTime) {
const interval = setInterval(() => {
const timeElapsed = (Date.now() - startTime) / 60000; // 분 단위
const wordsTyped = input.length / 5;
const currentWpm = Math.round(wordsTyped / timeElapsed);
setWpm(currentWpm);
}, 500); // 0.5초마다 업데이트
return () => clearInterval(interval);
}
}, [gameState, startTime, input]);
5. 컴포넌트 구조
React 컴포넌트가 어떻게 구성되어 있는지 살펴봅시다.
graph TD
A[TypingGame 메인 컴포넌트] --> B[언어 선택 버튼]
A --> C[게임 상태 표시<br/>속도/정확도/콤보]
A --> D[코드 표시 영역]
A --> E[숨겨진 입력 필드]
A --> F[결과 화면]
D --> D1[문자별 색상 표시]
D --> D2[커서 위치 표시]
D --> D3[엔터 기호 표시]
F --> F1[최종 속도]
F --> F2[정확도]
F --> F3[최대 콤보]
6. 주요 기능들
개발자들의 피드백을 반영하여 다음과 같은 기능들을 추가했습니다.
| 기능 | 설명 | 구현 방법 |
|---|---|---|
| 언어 선택 | JavaScript, Python, Java, CSS 중 선택 | 버튼 클릭 시 필터링된 스니펫 로드 |
| 자동 들여쓰기 | Enter 시 다음 줄 공백 자동 입력 | 정규식으로 공백 감지 후 자동 추가 |
| 스킵 기능 | 마음에 안 드는 코드 건너뛰기 | 새로운 랜덤 스니펫 선택 |
| 한글 표시 | 속도를 “200타”로 표시 | CPM 계산 후 “타” 문자 추가 |
7. 기술 스택
graph LR
A[React] --> B[상태 관리 & UI]
C[Framer Motion] --> D[애니메이션]
E[TypeScript] --> F[타입 안정성]
G[Tailwind CSS] --> H[스타일링]
B --> I[TypingGame 컴포넌트]
D --> I
F --> I
H --> I
💡 배운 점
이 프로젝트를 만들면서 배운 것들:
- React의 상태 관리: 여러 상태가 서로 어떻게 영향을 주는지 이해
- 실시간 UI 업데이트:
useEffect와setInterval을 활용한 동적 화면 갱신 - 사용자 경험(UX): 자동 들여쓰기 같은 작은 기능이 큰 차이를 만듦
- 정규식 활용: 공백 감지에 정규식
^ +사용
🚀 앞으로의 계획
지금은 간단한 프로토타입이지만, 앞으로 이런 기능들을 추가해보고 싶습니다.
- 사용자 커스텀 스니펫: 내가 연습하고 싶은 코드를 직접 등록
- 언어별 리더보드: 누가 가장 빠른지 경쟁
- 통계 그래프: 시간대별 타자 속도 변화 추이
- Vim 모드:
hjkl로 이동하며 수정하기 (이건 좀 어렵겠네요 😅)
재미있게 즐기셨다면 댓글로 최고 기록을 공유해주세요!