계정 없이 기기에서 도는 말하기 연습 앱 Clarity 뜯어보기
목소리를 다루는 앱은 녹음을 어디에 둘지부터 걸립니다. 말하기 연습 앱 Clarity는 계정도 서버 DB도 없이 기록을 기기 안에만 두는 쪽을 골랐습니다.
저장소 README와 GitHub API 응답, lib/score.ts 같은 소스 파일을 함께 읽었습니다. 구조를 어떤 기준으로 나눴는지, 클론해서 돌릴 때 어디서 막히는지를 정리합니다.
서버 DB 없이 기기에 쌓고, 기기를 바꾸면 끊깁니다
Clarity는 말하기 세션 기록을 기기 안에만 저장합니다. 계정도 서버 데이터베이스도 없다고 README가 못박습니다. 로컬 저장소는 MMKV이고, 목소리와 발화 내용이 운영자 서버에 쌓이지 않는 구조를 먼저 정한 뒤 기능을 얹은 모양새입니다.
저장소 이력은 아직 짧습니다. SchroederNathan/clarity 저장소는 2026년 7월 23일에 만들어졌습니다. 2026년 8월 9일 GitHub API로 확인한 값은 별 268개, 포크 51개, 라이선스 MIT, 주 언어 TypeScript였습니다. 최근 푸시는 2026년 8월 7일입니다. 별 개수는 규모를 재는 값이 아니라 이 글의 확인 시점을 고정해 두는 값으로만 적었습니다.
반대급부는 분명합니다. 기기를 바꾸면 쌓인 세션이 따라오지 않습니다. README에는 동기화나 백업 이야기가 없습니다. 연습 기록을 몇 년 단위
로 들고 가려는 쪽이라면 이 지점부터 걸립니다.발화 데이터는 목소리와 말한 내용을 한꺼번에 담습니다. 서버에 두는 순간 보관 기간과 접근 권한, 삭제 요청 처리까지 전부 설계해야 합니다. 기기 밖으로 내보내지 않으면 그 설계가 통째로 사라집니다. 대신 기능도 기기 안에서 끝낼 수 있는 범위로 좁아집니다.
받아쓰기는 기기, 발음 채점은 선택, 코칭은 외부
Clarity는 처리 위치를 세 갈래로 나눠 두었습니다. 받아쓰기는 expo-speech-recognition으로 기기 안에서 돌고, 단어 단위 발음 채점은 Azure Speech로 나가며, 세션 뒤 코칭 문장은 Expo Router API route와 Vercel AI Gateway를 거칩니다.
나눈 기준은 데이터의 민감도로 읽힙니다. 받아쓰기는 기기를 벗어나지 않습니다. 발음 채점은 다릅니다. 저장소의 services/azure-pronunciation.ts 주석은 Azure Speech의 short-audio REST 엔드포인트를 쓴다고 적어 두었고, 그 엔드포인트는 오디오를 받습니다.
눈에 띄는 대목이 여기 있습니다. 원본 음성이 기기 밖으로 나가는 경로는 발음 채점 하나인데, 그 하나가 유일하게 선택 사항으로 놓였습니다. 코칭 경로가 무엇을 실어 보내는지는 README에 적혀 있지 않습니다.
키를 두는 방식도 갈라집니다. Azure 키는 EXPO_PUBLIC_AZURE_SPEECH_KEY라는 이름이라 클라이언트 번들에 들어가고, 코칭용 AI_GATEWAY_API_KEY는 README 표에 서버 전용으로 표시돼 있습니다. 앞의 것을 켜려면 배포본에 키가 실린다는 점을 감안해야 합니다.
Azure 키가 없어도 점수는 나옵니다
Azure Speech 키를 채우지 않아도 세션 점수는 나옵니다. 키가 없으면 앱이 받아쓴 문장을 지문 원문과 맞춰 보는 자체 정렬로 대체한다고 README가 적어 두었습니다. Azure는 정확도를 단어 단위까지 세밀하게 만드는 선택지입니다.
이 차이는 저장소를 열어 보려는 사람의 판단을 바꿉니다. 유료 클라우드 계정을 먼저 만들지 않아도 점수 흐름 전체를 돌려 볼 수 있다는 뜻입니다. README 환경 변수 표에서 Azure 관련 두 값의 Required 칸은 모두 No입니다. 다만 Azure를 붙였을 때와 아닐 때 점수가 얼마나 벌어지는지 비교한 수치는 저장소에 없습니다.
정렬 로직은 services/alignment.ts에 있습니다. bun test가 history, stats, alignment, WAV 네 가지 순수 로직을 검사한다고 README의 스크립트 절이 밝힙니다. 네이티브 빌드를 세우기 전에 이 테스트만 먼저 돌려 볼 수 있습니다.
환경 변수 표는 무엇이 없으면 무엇이 안 되는지를 항목별로 갈라 둡니다. 코칭에는 AI_GATEWAY_API_KEY가 필요하고, 모델은 AI_COACH_MODEL로 바꾸며 기본값은 google/gemini-3.5-flash-lite입니다. 발음 채점 두 값은 없어도 되지만, 아이콘 패키지 설치에 쓰는 HUGEICONS_TOKEN은 성격이 다릅니다.
점수 다섯 항목의 계산식이 소스에 있습니다
세션마다 100점 만점 발화 점수 하나와 다섯 항목이 붙습니다. Articulation, Flow, Pacing, Fillers, Expression이고, 계산은 lib/score.ts에 순수 함수로 적혀 있습니다. README는 항목 이름까지만 밝히지만 소스는 공식을 그대로 드러냅니다.
공식을 짐작할 필요가 없습니다. 속도 점수는 지문의 목표 속도 대비 0.9배에서 1.1배 사이면 100점이고, 0.4배와 1.7배에서 0점으로 떨어집니다. 목표 속도는 지문마다 따로 박혀 있어서, constants/passages.ts의 한 지문은 분당 179단어로 잡혀 있습니다. 필러 점수는 분당 10개에서 0점이 됩니다.
아래는 저장소의 lib/score.ts에서 그대로 옮긴 일부입니다. 직접 빌드해 실행한 출력이 아니라 소스 인용입니다.
export const MIN_SCORED_MS = 8_000;
export const MIN_SCORED_WORDS = 10;
export function fillerScore(fillerCount: number, durationMs: number): number {
const minutes = Math.max(durationMs / 60_000, 1 / 6);
const perMinute = fillerCount / minutes;
return clampScore(100 - 10 * perMinute);
}
읽을 곳은 위의 두 상수입니다. 8초와 10단어를 넘기지 못한 세션은 연습 시간이나 연속 기록 같은 누적치에는 들어가되 다섯 항목의 표본에서는 빠집니다. 짧게 여러 번 눌러 점수를 흔드는 일을 막는 장치이고, 주석에도 그 의도가 적혀 있습니다.
이렇게 열어 둘 수 있는 이유는 폴더 규칙에 있습니다. lib/과 constants/는 services/를 import하지 않습니다. 부작용이 섞이지 않으니 점수 계산만 떼어 bun에서 돌릴 수 있고, 앱을 빌드하지 않고도 로직을 검증하게 됩니다.
시뮬레이터와 아이콘 토큰에서 먼저 막힙니다
Expo Go로는 이 앱이 돌지 않습니다. 음성 인식과 MMKV가 네이티브 코드를 쓰기 때문에 개발 빌드가 필요하다고 README가 못박습니다. iOS 시뮬레이터에는 음성 인식이 아예 없어서, 한 세션을 끝까지 시험하려면 실기기가 있어야 합니다.
실행 순서 자체는 짧습니다. README가 적어 둔 세 줄이 전부이고, 가운데 줄에서 키를 채우는 일만 남습니다.
bun install
cp .env.example .env.local # 키를 채웁니다
bunx expo run:ios # 또는 bunx expo run:android
세 줄 중 실제로 발이 묶이는 곳은 첫 줄입니다. HUGEICONS_TOKEN은 README 표에서 Required 칸이 Install로 적혀 있고, 아이콘 패키지를 내려받는 데 쓰입니다. 토큰 발급 조건은 저장소 문서에 나와 있지 않습니다.
시뮬레이터만 있는 환경에서도 화면은 볼 수 있습니다. EXPO_PUBLIC_MOCK_PRACTICE=1을 켜면 가짜 세션 엔진으로 UI가 돕니다. 다만 결과가 만들어진 값이라 점수 자체를 평가하는 데는 쓸 수 없습니다. 실기기 없이 훑고 나서 다 봤다고 여기기 쉬운 지점입니다.
막히는 순서를 미리 알면 시간을 아낍니다. 아이콘 토큰이 없으면 설치가 끝나지 않고, 개발 빌드를 세우지 않으면 앱이 뜨지 않으며, 실기기가 없으면 음성 인식이 붙지 않습니다. 세 관문이 차례로 놓여 있어서, 구조만 읽으려는 목적이면 저장소를 클론해 소스를 보는 편이 빠릅니다.
한국어로 쓸 수 있을지는 확인이 더 필요합니다
말하기 연습 앱 Clarity는 영어 발화를 전제로 짜여 있습니다. 내장 지문이 영어이고, services/azure-pronunciation.ts의 기본 로케일은 en-US입니다. 한국어로 쓰려면 지문과 로케일을 함께 손봐야 합니다.
직접 빌드해 돌려 보지는 않았습니다. Hugeicons Pro와 SF Pro Rounded의 사용 조건은 저장소 문서에 없어서, 코드가 MIT인 것과 그대로 배포해도 되는지는 별개입니다. 조건은 Clarity 저장소에서 직접 확인해야 합니다.
먼저 열어 볼 파일은 lib/score.ts입니다. bun test만 돌리면 네이티브 빌드 없이 점수 계산을 확인할 수 있습니다.
