// project
AI STT앱 개발 시도기, Project L mate
강의를 녹음하면 자동으로 글로 변환하고 요약해 주는 앱은 이미 많았습니다. 다만 월 구독에 사용량 제한이 붙고, 사용량 대비 학생이 한학기 내내 사용하기엔 비쌌고, 그래서 직접 최대한 싸게 만들어 나도 쓰고 주변도 쓰면 되지 않을까, 라고 생각을 하고 개발을 시도했었습니다.
기술 스택
우선적으로 안드로이드와 IOS를 둘다 지원하고, 빌드와 배포가 간단하고, 디바이스의 네이티브 기능에 쉽게 접근할 수 있어야 했습니다. 결정적으로, 실제 사용을 위해 빠른 개발과 배포가 필요한 상황이였습니다. 이에 결정된 기술 스택은 Expo와 React Native로 프론트엔드를, 백엔드는 Supabase, 상태관리 라이브러리로는 zustand를 선택했습니다. AI API는 최초 개발때 openai의 whisper와, 핵심 요약 API로는 claude의 sonnet-4를 이용했었습니다.

디자인의 형태는 사용자 경험을 생각해서, 당시 유행하던 형태의 디자인을 따라갔었습니다. 물론 저런 디자인을 좋아하기는 하지만, 지금 보고계시는 이 사이트처럼(특히 Lab) 제 취향이 100% 반영된건 아니였습니다. 아이콘들은 저작권 문제가 없는 무료들을 사용했습니다. 지금이나 그때나 저는 프론트엔드 디자인은 할 줄 알아도 이미지 디자인은 할줄도 모르고, 매우 못 했었습니다.
상세 구현 구조
놀랍게도, 앱 자체는 사실상 당장도 배포가 가능하고, 실제 서비스가 가능한 수준까지 제작되었습니다.
녹음과 시간표
녹음은 expo-av의 Audio.Recording, HIGH_QUALITY 프리셋을 씁니다. idle에서 recording, paused, stopped로 이어지는 상태 머신이고, 당연하게도 녹음 일시정지와 재개를 지원합니다. iOS는 무음 모드에서도 녹음되도록 오디오 세션을 따로 설정했습니다.
시간표 이미지를 캡쳐해서 업로드하면, 자동으로 인식해서 lecturemate 내부에 시간표를 따로 그리며 저장합니다. 이후, useTodaySchedule 훅이 1분마다 오늘 스케줄을 갱신하고, 녹음을 시작할 때 현재 시각이 어떤 강의 시간의 앞뒤 10분 안에 들어가면 그 강의를 미리 선택합니다. 녹음본 저장 시 제목도 자동으로 강의가 있으면 강의명 날짜, 없으면 녹음 HH:MM 형식으로 저장되게 해두었습니다.
알림
expo-notifications로 스케줄마다 주간 반복 알림을 겁니다. 여섯 종류를 켜고 끌 수 있습니다. 매일 아침 8시, 30분 전, 10분 전, 시작 시각, 종료 10분 전, 종료 시각. 기본값은 앞의 네 개가 켜져 있습니다. 문구는 상황별로 다릅니다. “10분 후 수업입니다. 준비하세요.”, “수업 시작 시간입니다. 출석체크를 해주세요.” 처럼.
사실 알림 기능을 만든 이유는 제가 필요해서 만들었습니다. 종종 개발이나 일을 하다보면 시간 지나는걸 인지하지 못하고 수업 시간을 놓치거나, 열심히 강의실에 도착했는데, 모바일 출석체크를 하지 않은 경우가 종종 있었어서요.
전사와 요약
STT는 OpenAI Whisper(whisper-1, 한국어)에 m4a 파일을 그대로 업로드하고, 성공하면 transcripts에 저장하고 녹음 상태를 done으로, 실패하면 error로 반환합니다.
요약은 Claude(claude-sonnet-4, 최대 3000토큰)에 STT 텍스트를 6만 자까지 잘라서 넘깁니다. 프롬프트는 여섯 섹션으로 고정돼 있습니다. 강의 핵심 요약, 주요 개념과 용어, 세부 내용 정리, 시험 출제 가능 포인트, 추가 학습 권장. 강의가 아니면 형식을 무시하고 핵심만 추리도록 폴백, 의문형이나 짧은 삽입 발언은 요약에서 제외하도록 설계했습니다.
재생과 목록
재생 화면에는 진행바와 10초 뒤로 감기, STT와 요약 탭, 마크다운 렌더로 구성했고, 제목은 탭하면 바로 편집되고 포커스가 빠지면 저장됩니다. 클립보드 복사도 되며, txt 내보내기 또한 설계했습니다.
녹음 목록은 강의별로 묶고 미지정은 따로 모읍니다. 상태 뱃지는 변환 전, 변환 중, 완료, 오류 네 단계로 색이 다르고, 화면으로 돌아올 때마다 새로고침됩니다.
크레딧과 플랜
크레딧은 두 종류입니다. 전사는 분 단위, AI 요약은 횟수. 매월 리셋되고 보너스 크레딧은 따로 계산됩니다. 플랜은 다섯 개로, free가 300분에 15회, fulltime이 14,000분에 무제한입니다. 14000분인 이유는 주변 사람들의 한달간 수업 시간을 계산, 평균치에서 올림하여 계산했습니다.
테마
라이트와 다크를 메인 색상으로 사용하고, 각 객체 역할에 맞추어 메인 테마(다크모드, 라이트모드)에 맞게 각각 구성했습니다. 최초 테마는 시스템 설정을 따르고, 사용자가 변경하면 다시 변경하기 전까지 고정됩니다. 단어장 카테고리는 essential 주황, technical 파랑, important 초록 세가지 색으로 구성했습니다.
구현하지 않은 설계
타입 정의에는 있지만 실제로는 안 쓴 것들도 있습니다. TranscriptSegment의 화자 분리(교수, 학생, 미상), Summary의 구조화된 필드(핵심 개념, 시험 주제, 객관식과 단답과 서술형 퀴즈), Vocabulary의 강의를 넘나드는 등장 횟수 카운트와 문맥 스니펫 자동 축적을 구현하고자 하였는데, 이것들이 가능한 API의 가격(당시 whisper는 단순 STT만 가능했습니다.)과, API가 없이 독자적 구현의 비용을 구현하기 전에 계산하였고, 이 계산 결과가 아래 포기 결정으로 이어집니다.
왜 접었는가
앱을 만들기 시작한 이유는 그거였습니다. 최소한의 이익으로, 최대한 싸고 좋은 품질을 내놓자. 구현하고자 하는 기능들이 가능한 API를 사용하면 타 업체들과 비슷한 시간을 서비스해도 가격이 비쌌고, 단독으로 STT와 화자 분리등등을 돌릴 수 있는 AI를 구축하는건 막대한 초기비용이 들었고, 그 초기비용을 개인이 충당하기 위해서는 이용자들이 부담하게 만들어야했고, “싸게”가 목적이었는데 그게 성립하지 않았습니다.
기술적으로 막힌 것은 아니었습니다. 만들 수는 있었지만 만들 이유가 사라진 경우였고, 거기서 멈추는 게 맞다고 판단했습니다.