한국어 학습을 위한 AI 기반 웹 애플리케이션
오누이 한국어는 한국어 학습자를 위한 종합 학습 플랫폼입니다. AI 기술과 인터랙티브한 학습 게임을 통해 효과적인 한국어 학습 경험을 제공합니다.
- 발음 정확도 평가 (
/speechpro-practice): 녹음 후 AI가 발음 점수와 피드백 제공 - 유창성 평가 (
/fluency-practice): 말하기 흐름·억양·문법을 실시간 평가 - 단계별 발음 학습 (
/pronunciation-stages): 단계/레벨별 발음 가이드 - 발음 규칙 (
/pronunciation-rules): 규칙 이해 ↔ 예제 연습 탭으로 학습
- AI 학습 도구 (
/learning): 질문/주제 입력 후 AI 피드백 - 맞춤형 교재 (
/content-generation): 주제·레벨 맞춤 대화문·단어장 생성 - 작문 테스트 (
/fluency-test): 입력/음성 기반 작문 채점 - 상황별 콘텐츠 생성 (
/media-generation): 상황별 표현·대화 자동 생성
- 단어 삭제 (
/word-puzzle): 드래그 앤 드롭 퍼즐 - 조사 떠다니기 (
/vocab-garden): 조사/어휘 조합 연습 - 오늘의 표현 (
/daily-expression): 매일 갱신 표현 학습 - 타이핑 게임 (
/typing-game): 30초 안에 한글 단어 빠르게 타이핑 (72개 어휘) - 듣고 받아쓰기 (
/listening-dictation): 문장을 듣고 정확하게 받아쓰기 (35개 문장) - 스피드 퀴즈 (
/speed-quiz): 10초 안에 단어의 뜻 맞추기 (72개 어휘)
- 전래동화 읽기 (
/folktales): 10개 한국 전래동화 + 이해도 퀴즈 - 문화 표현 학습 (
/cultural-expressions): 30개 한국 문화 표현 + 문화적 배경 설명
- Backend: FastAPI (Python)
- Frontend: Jinja2 Templates, Tailwind CSS
- AI/ML: Ollama (EXAONE), MzTTS, VOSK
- Audio: MediaRecorder API, MzTTS API, ffmpeg
# 기존 .venv 제거 (선택)
rm -rf .venv
# 새 가상환경 생성 및 활성화
python3 -m venv .venv
source .venv/bin/activate
# pip 및 의존성 설치
python -m pip install --upgrade pip setuptools wheel
python -m pip install -r requirements.txt.env 파일을 생성하거나 환경 변수를 설정하세요:
# Ollama 설정 (로컬 LLM)
export MODEL_BACKEND=ollama
export OLLAMA_URL=http://localhost:11434
export OLLAMA_MODEL=exaone3.5:2.4b
# MzTTS 설정 (한국어 TTS)
export MZTTS_API_URL=http://112.220.79.218:56014
# VOSK 음성 인식 (선택)
export LOCAL_STT=vosk
export VOSK_MODEL_PATH=/path/to/vosk-model
# OpenAI (선택, 기본적으로 비활성화)
# export OPENAI_API_KEY=your-api-keyThis project can use korean-romanizer to produce consistent, accurate Latin-script pronunciations when the model output is absent or unreliable.
Install into the virtualenv:
source .venv/bin/activate
pip install korean-romanizerControl romanization behavior with the ROMANIZE_MODE environment variable:
ROMANIZE_MODE=force(default) — always replace pronunciation fields with the romanizer output for consistent results.ROMANIZE_MODE=prefer— keep model-provided Latin pronunciations when they look valid; otherwise fall back to the romanizer.
Example:
export ROMANIZE_MODE=force# 개발 서버 (자동 재로딩)
source .venv/bin/activate && python -m uvicorn main:app --host 0.0.0.0 --port 9000 --reload
# 또는
python main.py
# 백그라운드 실행
python main.py &pkill -f uvicorn브라우저에서 http://localhost:9000 접속
ngrok을 사용하면 로컬 서버를 외부 인터넷에 공개할 수 있습니다.
# 프로젝트 디렉토리에 ngrok 다운로드 및 설치
cd ~/Projects/onui-ai
curl -Lo /tmp/ngrok.tgz https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-linux-amd64.tgz
tar xzf /tmp/ngrok.tgz -C .
chmod +x ngrok- https://ngrok.com/signup 에서 무료 계정 생성
- 대시보드에서 인증 토큰 확인 (https://dashboard.ngrok.com/get-started/your-authtoken)
- 토큰 설정:
./ngrok config add-authtoken <your-auth-token># 백그라운드에서 실행
./ngrok http 9000 --log=stdout &
# 또는 포그라운드에서 실행 (터미널 창 유지 필요)
./ngrok http 9000터미널에서 https://xxxxxxxx.ngrok-free.app 형태의 URL을 확인할 수 있습니다.
이 URL을 통해 전 세계 어디서든 접속 가능합니다!
실시간 트래픽 모니터링:
http://localhost:4040
pkill -f ngrok- 무료 계정: ngrok 재시작 시마다 URL이 변경됩니다
- 고정 URL: 유료 플랜에서 사용 가능
- 보안: 프로덕션 환경에서는 인증 시스템 추가 권장
- 세션 유지: 애플리케이션(port 9000)과 ngrok이 모두 실행 중이어야 합니다
onui-ai/
├── main.py # FastAPI 메인 앱
├── requirements.txt # Python 패키지
├── README.md # 프로젝트 설명서
├── database_schema_learning_progress.sql # 학습 진도 DB 스키마
│
├── backend/ # 백엔드 모듈
│ ├── models/ # DB 모델 (empty - ORM 미사용)
│ ├── services/ # 비즈니스 로직
│ │ ├── speechpro_service.py # 발음 평가 서비스 (SpeechPro API)
│ │ └── learning_progress_service.py # 학습 진도 추적
│ └── utils/ # 유틸리티 (empty)
│
├── templates/ # Jinja2 HTML 템플릿
│ ├── base.html # 기본 레이아웃 (헤더, 내비게이션)
│ ├── index.html # 홈페이지
│ ├── components/
│ │ └── character-popup.html # 오누이 캐릭터 팝업
│ │
│ ├── 🗣️ 발음 학습
│ │ ├── speechpro-practice.html # 발음 정확도 평가
│ │ ├── fluency-practice.html # 유창성 평가
│ │ ├── pronunciation-stages.html # 단계별 발음 학습
│ │ └── pronunciation-rules.html # 발음 규칙 (NEW!)
│ │
│ ├── 🤖 AI 학습
│ │ ├── learning.html # AI 학습 도구
│ │ ├── content-generation.html # 맞춤형 교재 생성
│ │ ├── fluency-test.html # 작문 테스트
│ │ ├── media-generation.html # 상황별 콘텐츠 생성
│ │ └── essay-test.html # 에세이 평가
│ │
│ ├── 🎲 활동하기
│ │ ├── word-puzzle.html # 단어 삭제 (어순 퍼즐)
│ │ ├── vocab-garden.html # 조사 떠다니기
│ │ ├── daily-expression.html # 오늘의 표현
│ │ ├── typing-game.html # 타이핑 게임
│ │ ├── listening-dictation.html # 듣고 받아쓰기
│ │ └── speed-quiz.html # 스피드 퀴즈
│ │
│ ├── 📖 재미있는 이야기
│ │ ├── folktales.html # 전래동화 읽기
│ │ └── cultural-expressions.html # 문화 표현 학습
│ │
│ ├── 👤 사용자 기능
│ │ ├── login.html # 로그인
│ │ ├── mypage.html # 내 프로필
│ │ ├── learning-progress.html # 학습 진도 (NEW!)
│ │ └── change-password.html # 비밀번호 변경
│ │
│ ├── 🔧 관리자 페이지
│ │ ├── api-test.html # API 테스트
│ │ ├── sitemap.html # 사이트맵
│ │ ├── chatbot.html # 챗봇
│ │ ├── pronunciation-check.html # 발음 점검
│ │ ├── pronunciation-correction.html # 발음 교정
│ │ ├── sentence-evaluation.html # 문장 평가
│ │ └── custom-materials.html # 맞춤 교재
│ │
│ └── 🗂️ 기타
│ ├── index_old.html.bak # 구 홈페이지
│ └── login.html # 인증 페이지
│
├── static/ # 정적 파일
│ ├── css/ # 스타일시트
│ │ ├── pronunciation-practice.css # 발음 연습 UI
│ │ ├── vocab-garden.css # 어휘 학습 UI
│ │ ├── word-puzzle.css # 퍼즐 UI
│ │ └── daily-expression.css # 표현 학습 UI
│ │
│ ├── js/ # JavaScript
│ │ ├── pronunciation-practice.js # 발음 연습 로직
│ │ ├── vocab-garden.js # 어휘 학습 로직
│ │ ├── word-puzzle.js # 퍼즐 로직
│ │ └── daily-expression.js # 표현 학습 로직
│ │
│ ├── img/ # 이미지 (favicon, 캐릭터 등)
│ └── (favicon, manifest 등)
│
├── data/ # JSON 데이터 파일
│ ├── sentences.json # 어순 연습 문장 (35개)
│ ├── expressions.json # 오늘의 표현
│ ├── vocabulary.json # 단어 꽃밭 단어 (72개)
│ ├── pronunciation-words.json # 발음 연습 단어
│ ├── folktales.json # 전래동화 (10개)
│ ├── cultural-expressions.json # 문화 표현 (30개)
│ ├── sp_ko_questions.json # SpeechPro 질문
│ ├── sp_ko_questions.csv # SpeechPro 질문 (CSV)
│ ├── speechpro-sentences.json # SpeechPro 문장
│ ├── landing_intake.json # 랜딩 페이지 데이터
│ └── users.db # SQLite 사용자 DB
│
├── docs/ # 문서
│ ├── design/ # 디자인 자료
│ │ ├── character.png # 오누이 캐릭터
│ │ ├── elsaspeak.png # ELSA Speak 참고 이미지
│ │ ├── tiger_chatbot.svg # 챗봇 캐릭터
│ │ └── HTML 디자인 템플릿들
│ ├── api/ # API 문서
│ └── requirements/ # 요구사항 명세
│
├── scripts/ # 유틸리티 스크립트
│ └── test_speechpro_api.py # SpeechPro API 테스트
│
├── tests/ # 테스트 코드
│ └── (테스트 파일들)
│
├── tools/ # 도구/유틸리티
│ └── (헬퍼 도구들)
│
├── .env # 환경 변수 (로컬)
├── .env.example # 환경 변수 템플릿
├── onui-ai.service # Systemd 서비스 파일
├── start-service.sh # 서비스 시작 스크립트
├── stop-service.sh # 서비스 중지 스크립트
├── ngrok # ngrok 바이너리 (외부 공개용)
│
├── 📋 문서 파일
│ ├── CLAUDE.md # 개발 노트
│ ├── SPEECHPRO_API_WORKFLOW.md # SpeechPro 워크플로우
│ ├── SPEECHPRO_IMPLEMENTATION.md # SpeechPro 구현 가이드
│ ├── CURRICULUM_OPTIMIZATION_REPORT.md # 커리큘럼 최적화 보고서
│ └── MODEL_COMPARISON_REPORT.md # 모델 비교 보고서
│
└── 📁 자동 생성 폴더
├── __pycache__/ # Python 캐시
├── .git/ # Git 저장소
├── .pytest_cache/ # Pytest 캐시
├── htmlcov/ # 테스트 커버리지 리포트
├── logs/ # 로그 파일
├── test_results/ # 테스트 결과
└── .venv/ # Python 가상환경
| 라우트 | 설명 |
|---|---|
/ |
홈페이지 |
/learning |
AI 학습 도구 |
/content-generation |
맞춤형 교재 생성 |
/pronunciation-check |
발음 점검 |
/fluency-test |
작문 테스트 |
/custom-materials |
맞춤 교재 |
/essay-test |
에세이 테스트 |
/pronunciation-correction |
발음 교정 |
/word-puzzle |
단어 삭제 (어순 퍼즐) |
/daily-expression |
오늘의 표현 |
/vocab-garden |
조사 떠다니기 |
/typing-game |
타이핑 게임 |
/listening-dictation |
듣고 받아쓰기 |
/speed-quiz |
스피드 퀴즈 |
/folktales |
전래동화 읽기 |
/cultural-expressions |
문화 표현 학습 |
/pronunciation-practice |
발음 연습 |
/pronunciation-stages |
단계별 발음 학습 |
/pronunciation-rules |
발음 규칙 |
/speechpro-practice |
발음 정확도 평가 |
/fluency-practice |
유창성 평가 |
/api-test |
API 테스트 |
/media-generation |
상황별 콘텐츠 생성 |
/sitemap |
사이트맵 |
/login |
로그인 |
/mypage |
내 프로필 |
/learning-progress |
학습 진도 |
/change-password |
비밀번호 변경 |
/chatbot |
챗봇 |
| 메서드 | 라우트 | 설명 |
|---|---|---|
POST |
/api/signup |
회원 가입 |
POST |
/api/login |
로그인 |
POST |
/api/logout |
로그아웃 |
POST |
/api/landing-intake |
랜딩 페이지 입력 저장 |
GET |
/api/user/profile |
사용자 프로필 조회 |
POST |
/api/user/profile/update |
프로필 업데이트 |
POST |
/api/user/password/change |
비밀번호 변경 |
POST |
/api/log/guest-login |
게스트 로그인 |
POST |
/api/log/activity |
활동 기록 |
| 메서드 | 라우트 | 설명 |
|---|---|---|
POST |
/api/pronunciation-check |
단어 발음 평가 |
POST |
/api/speechpro/gtp |
SpeechPro GTP 분석 |
POST |
/api/speechpro/model |
SpeechPro 모델 평가 |
POST |
/api/speechpro/score |
SpeechPro 점수 계산 |
POST |
/api/speechpro/evaluate |
문장 발음 평가 (전체 워크플로우) |
GET |
/api/speechpro/sentences |
모든 발음 연습 문장 |
GET |
/api/speechpro/sentences/{sentence_id} |
특정 발음 문장 |
GET |
/api/speechpro/sentences/level/{level} |
레벨별 발음 문장 |
GET |
/api/speechpro/config |
SpeechPro 설정 조회 |
POST |
/api/speechpro/config |
SpeechPro 설정 업데이트 |
| 메서드 | 라우트 | 설명 |
|---|---|---|
POST |
/api/fluency-check |
작문 유창성 평가 |
POST |
/api/fluencypro/analyze |
FluencyPro 상세 분석 |
POST |
/api/fluencypro/combined-feedback |
SpeechPro + FluencyPro 복합 피드백 |
GET |
/api/fluencypro/metrics/{user_id} |
사용자 유창성 지표 |
| 메서드 | 라우트 | 설명 |
|---|---|---|
POST |
/api/generate-content |
AI 교재 생성 (주제/레벨 기반) |
POST |
/api/situational-content |
상황별 표현/대화 생성 |
POST |
/api/chat/test |
챗봇 메시지 (Ollama) |
POST |
/api/generate-image |
이미지 생성 (Image API) |
POST |
/api/generate-music |
음악 생성 (Music API) |
| 메서드 | 라우트 | 설명 |
|---|---|---|
GET |
/api/puzzle/sentences |
어순 퍼즐 문장 목록 |
GET |
/api/puzzle/sentences/{sentence_id} |
특정 퍼즐 문장 |
GET |
/api/expressions |
전체 표현 목록 |
GET |
/api/expressions/today |
오늘의 표현 (매일 갱신) |
GET |
/api/vocabulary |
단어 꽃밭 단어 목록 (72개) |
GET |
/api/vocabulary/{word_id} |
특정 단어 상세 정보 |
GET |
/api/pronunciation-words |
발음 연습 단어 목록 |
GET |
/api/pronunciation-words/{word_id} |
특정 발음 단어 상세 정보 |
GET |
/api/folktales |
전래동화 목록 (10개) |
GET |
/api/cultural-expressions |
문화 표현 목록 (30개) |
| 메서드 | 라우트 | 설명 |
|---|---|---|
GET |
/api/tts/info |
MzTTS 서버 정보 조회 |
POST |
/api/tts/generate |
MzTTS로 음성 생성 |
| 메서드 | 라우트 | 설명 |
|---|---|---|
GET |
/api/ollama/models |
Ollama 사용 가능 모델 목록 |
POST |
/api/ollama/test |
Ollama 모델 테스트 |
| 메서드 | 라우트 | 설명 |
|---|---|---|
POST |
/api/learning/pronunciation-completed |
발음 학습 완료 기록 |
POST |
/api/learning/popup-shown |
캐릭터 팝업 표시 기록 |
GET |
/api/learning/user-stats/{user_id} |
사용자 학습 통계 |
GET |
/api/learning/today-progress/{user_id} |
오늘 학습 진도 |
POST |
/api/learning/check-popup/{user_id} |
팝업 표시 여부 확인 |
fastapi- 웹 프레임워크uvicorn- ASGI 서버jinja2- 템플릿 엔진python-multipart- 파일 업로드requests- HTTP 클라이언트vosk- 음성 인식 (선택)pydub- 오디오 처리 (선택)
- Python 3.8+
- ffmpeg (오디오 변환용)
- Ollama (로컬 LLM 사용 시)
- VOSK 모델 (오프라인 STT 사용 시)
rm -rf .venv
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt# macOS
brew install ffmpeg
# Ubuntu/Debian
sudo apt-get install ffmpeg# Ollama 서버 실행 확인
curl http://localhost:11434/api/tags
# 모델 다운로드
ollama pull exaone3.5:2.4b- 브라우저 설정에서 마이크 권한 허용
- HTTPS 환경에서만 MediaRecorder API 사용 가능
- 타이핑 게임: 30초 안에 한글 단어 빠르게 타이핑 (72개 어휘, WPM 측정)
- 듣고 받아쓰기: 브라우저 TTS로 문장 듣고 받아쓰기 (35개 문장)
- 스피드 퀴즈: 10초 안에 단어 뜻 맞추기 (72개 어휘, 타이머 포함)
- 전래동화 읽기: 10개 한국 전래동화 + 이해도 퀴즈 (흥부와 놀부, 토끼와 거북이 등)
- 문화 표현 학습: 30개 한국 문화 표현 + 문화적 배경 설명 (인사 예절, 식사 문화, 명절 등)
- vocabulary.json: 8개 → 72개 단어 (레벨 A1-B2, 카테고리별 분류)
- sentences.json: 4개 → 35개 문장 (TTS용 text 필드 추가)
- folktales.json: 10개 전래동화 + 어휘 + 도덕적 교훈
- cultural-expressions.json: 30개 문화 표현 + 문화적 맥락
- 홈페이지: 새로운 기능 카드 5개 추가 (게임 3개 + 이야기 2개)
- Footer: 회사 이름 "Mediazen" 추가
- 네비게이션: "재미있는 이야기" 메뉴에 실제 기능 링크 추가
- 규칙 이해 / 예제 연습 탭 전환 UI 추가 (기본은 규칙, 클릭으로 연습 전환)
- 연습 카드별 정답 보기/숨기기 토글 개선 (색상/텍스트 동기화)
- 사용자 입력 정답 확인 기능 추가: 입력 → 확인/Enter로 즉시 채점, 피드백 표시
- 연습 카드마다 입력창 자동 생성, 공백/대소문자 무시 비교
- ngrok 설치 및 설정 가이드 추가
- 로컬 서버를 전 세계에 공개 가능
- HTTPS 자동 지원
- 실시간 트래픽 모니터링 대시보드
- 전문 한국어 TTS (한나 화자) 통합
- 발음 연습 페이지에 고품질 음성 추가
- 단어 꽃밭에서 단어/문장 음성 재생 기능
- API 테스트 페이지 추가
- ELSA Speak 스타일의 2단계 학습 인터페이스
- MzTTS 전문 TTS로 네이티브 발음 듣기
- MediaRecorder API 기반 녹음 및 AI 발음 평가
- 20개 한국어 필수 표현 (인사말, 일상 표현)
- 오누이 캐릭터 (👦👧) 적용
- 실시간 검색 및 레벨 필터링 (A1/A2)
- 음소 분해 시각화 및 발음 팁 제공
- 단어 꽃밭: 각 단어에 어울리는 이모지 추가
- AI 학습 도구: 친근한 placeholder 텍스트
- 모델 선택: 기본값 exaone3.5:2.4b 설정
MIT License
이슈 및 PR 환영합니다!
김영훈 (Kim Young-hoon) - Mediazen