IchiMozzi 프로젝트 시작 - JLPT 학습 앱 기획과 기술 스택 선정
들어가며
2024년 초, 일본어 학습자들의 실질적인 고민을 해결하고자 IchiMozzi 프로젝트를 시작했습니다. JLPT 시험 준비 과정에서 느꼈던 “내 실력이 정확히 어느 정도인지 모르겠다”, “어떤 부분을 더 공부해야 할지 명확하지 않다”는 문제점들을 기술적으로 해결하고 싶었습니다.
이 글에서는 6개월간 개발한 IchiMozzi 프로젝트의 시작점과 핵심 기술 스택을 선정한 배경을 공유합니다.
프로젝트 목표와 문제 정의
해결하고자 한 핵심 문제들


IchiMozzi의 메인 화면과 실력 분석 기능
1. 객관적 실력 측정의 어려움
- 기존 학습 자료들은 단편적인 문제 제공에만 집중
- 사용자의 전체적인 일본어 실력을 종합적으로 평가하는 도구 부족
- JLPT 등급별 실력 예측 기능의 필요성
2. 개인화된 학습 경로 부재
- 획일적인 학습 콘텐츠로 인한 비효율성
- 개인별 취약점 분석 및 맞춤형 학습 자료 제공 시스템 필요
- 학습 진도에 따른 적응적 난이도 조절 필요
3. 체계적인 복습 시스템 부족
- 틀린 문제들을 효과적으로 관리하고 복습할 수 있는 시스템 부재
- 망각 곡선을 고려한 반복 학습 알고리즘 필요
기술 스택 선정 과정
프론트엔드: React Native 선택 이유
// frontend/package.json - 핵심 의존성
{
"dependencies": {
"@react-navigation/native": "^7.0.14",
"@react-navigation/stack": "^7.1.1",
"expo": "~52.0.27",
"react": "^18.3.1",
"react-native": "0.76.6",
"react-native-paper": "^4.11.2",
"typescript": "^5.3.3"
}
}
React Native + Expo 조합을 선택한 핵심 이유:
- 크로스 플랫폼 개발 효율성
- 하나의 코드베이스로 iOS/Android 동시 개발
- 개인 프로젝트에서 개발 리소스 최적화
- 빠른 프로토타이핑과 배포
- Expo의 개발 도구로 빠른 반복 개발 가능
- OTA(Over-The-Air) 업데이트로 즉시 배포
- 풍부한 UI 컴포넌트
- React Native Paper로 Material Design 구현
- 일관성 있는 사용자 경험 제공
백엔드: NestJS 아키텍처
// backend/src/app.module.ts - 모듈 구조
@Module({
imports: [
TypeOrmModule.forRoot(typeORMConfig),
AuthModule, // 사용자 인증 관리
UsersModule, // 사용자 정보 관리
AnalysisModule, // 학습 분석 시스템
LearningModule, // 학습 콘텐츠 관리
WebhookModule, // 외부 서비스 연동
WrongNoteGroupModule,// 오답 노트 관리
NotificationsModule, // 푸시 알림 시스템
],
controllers: [AppController],
providers: [],
})
export class AppModule {}
NestJS 선택의 핵심 이유:
- TypeScript 네이티브 지원
- 프론트엔드와 백엔드 간 타입 일관성 확보
- 컴파일 타임 오류 검출로 안정성 향상
- 모듈 기반 아키텍처
- 기능별 모듈 분리로 코드 관리 용이성
- 테스트 가능한 구조와 의존성 주입
- 풍부한 생태계
- TypeORM, Passport, JWT 등 검증된 라이브러리 통합
- 데코레이터 기반의 직관적인 API 설계
데이터베이스: PostgreSQL + TypeORM
// backend/src/entities/user.entity.ts - 사용자 모델
@Entity()
export class User {
@PrimaryGeneratedColumn()
id!: number;
@Column({ unique: true })
email!: string;
// 사용자 레벨 관리
@Column({ default: 'N5' })
currentLevel!: string;
// 영역별 점수 (각 최대 1000점)
@Column({ default: 0 })
vocabScore!: number;
@Column({ default: 0 })
grammarScore!: number;
@Column({ default: 0 })
readingScore!: number;
// 총합 점수 (최대 3000점)
@Column({ default: 0 })
score!: number;
@OneToMany(() => WrongNoteGroup, (group) => group.user, { cascade: true })
wrongNoteGroups!: WrongNoteGroup[];
@Column({ nullable: true })
pushToken!: string; // Expo 푸시 토큰
@CreateDateColumn()
createdAt!: Date;
@UpdateDateColumn()
updatedAt!: Date;
}
PostgreSQL + TypeORM 조합의 장점:
- 복잡한 관계형 데이터 모델링
- 사용자, 학습 기록, 오답 노트 간 복잡한 관계 효율적 관리
- ACID 트랜잭션으로 데이터 일관성 보장
- 타입 안전한 ORM
- TypeScript와 완벽한 통합
- 컴파일 타임 쿼리 검증
- 확장성과 성능
- 인덱싱과 쿼리 최적화 지원
- 대용량 학습 데이터 처리 가능
프로젝트 아키텍처 설계
전체 시스템 구조
// backend/src/main.ts - 서버 설정
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// CORS 설정: React Native 앱과의 통신
app.enableCors({
origin: '*',
});
// GitHub Webhook 시그니처 검증을 위한 rawBody 확보
app.use(bodyParser.json({
verify: (req: any, res, buf) => {
req.rawBody = buf;
},
}));
const port = 3000;
await app.listen(port);
console.log(`Server running on http://localhost:${port}`);
}
클라이언트-서버 통신 구조
// frontend/src/api/auth.ts - 인증 API
const API_URL = 'https://ichimozzi.com';
export async function registerUser(name: string, email: string, password: string, level: string) {
const response = await axios.post(`${API_URL}/auth/register`, {
name,
email,
password,
level,
});
return response.data;
}
export async function loginUser(email: string, password: string) {
const response = await axios.post(`${API_URL}/auth/login`, {
email,
password,
});
return response.data;
}
// 게스트 로그인 기능도 지원
export async function guestLogin() {
const response = await axios.post(`${API_URL}/auth/guest`);
return response.data;
}
개발 방법론과 도구
타입 안전성 확보
프로젝트 전반에 걸쳐 TypeScript를 적극 활용하여 다음과 같은 이점을 얻었습니다:
- 컴파일 타임 오류 검출: 런타임 오류를 사전에 방지
- IntelliSense 지원: 개발 생산성 크게 향상
- 리팩토링 안전성: 대규모 코드 변경 시 안정성 확보
모듈화된 개발 구조
프로젝트 구조:
├── backend/src/
│ ├── auth/ # 사용자 인증 및 권한 관리
│ ├── users/ # 사용자 프로필 및 정보 관리
│ ├── learning/ # 학습 콘텐츠 및 진행 관리
│ ├── analysis/ # 학습 데이터 분석 시스템
│ ├── webhook/ # 외부 서비스 연동
│ └── notifications/# 푸시 알림 시스템
└── frontend/src/
├── api/ # 백엔드 API 연동
├── components/ # 재사용 가능한 UI 컴포넌트
├── contexts/ # 전역 상태 관리
├── navigation/ # 화면 전환 및 라우팅
├── screens/ # 앱 화면 구성
└── types/ # 타입 정의
다음 단계 preview
이번 글에서는 IchiMozzi 프로젝트의 전체적인 기획과 핵심 기술 스택 선정 과정을 다뤘습니다.
다음 글에서 다룰 내용들:
- NestJS 백엔드 아키텍처 상세 설계와 TypeORM 데이터 모델링
- React Native 모바일 앱의 UI/UX 구현 과정
- JWT 기반 사용자 인증 시스템 구현
- 개인화된 학습 분석 알고리즘 개발
- Firebase 푸시 알림 시스템 구축
- 실제 배포와 운영 경험
각 단계에서 마주했던 기술적 도전과 해결 과정을 실제 코드와 함께 상세히 공유할 예정입니다.
IchiMozzi는 일본어 학습자들의 실질적인 고민을 해결하기 위해 시작된 프로젝트로, 기술적 완성도와 사용자 경험 모두를 고려한 풀스택 개발 경험을 제공했습니다.
Enjoy Reading This Article?
Here are some more articles you might like to read next: