교육고객사 비공개앱·웹 플랫폼 개발관리자·백오피스

영어 단어 학습 앱 다중 교재 구조 구축

교재 한 권만 운영되던 영어 단어 학습 앱을 여러 교재를 동시에 다루는 구조로 무중단 전환한 앱·서버·관리자 웹 개편

교재 선택, 단어 학습, 챌린지 테스트 화면을 보여 주는 영어 단어 학습 앱 화면 세 장

배경과 목표

어떤 문제에서 시작했나요?

이미 운영 중이던 영어 단어 학습 앱은 교재 한 권을 전제로 만들어져 있었습니다. 챕터 번호도, 시리얼 코드도, 사용자 학습 진도도 모두 교재 구분 없이 저장되는 구조여서 교재를 한 권 더 올리려면 데이터가 서로 부딪히는 상태였습니다. 앱은 이미 iOS·Android 양쪽 스토어에 올라가 있었고, 발급된 시리얼 코드와 학습 기록이 쌓여 있었습니다. 구조를 바꾸는 동안 기존 사용자의 학습이 끊기거나, 업데이트하지 않은 구버전 앱이 동작하지 않는 상황은 허용되지 않았습니다. 여기에 더해 이전 버전(voca2)과 현재 버전(voca3)의 도메인과 인프라가 섞여 있어, 운영 중 어느 쪽을 건드리는지 헷갈리는 문제도 함께 정리해야 했습니다.

목표: 합의된 범위는 ① 교재를 여러 권 동시에 운영할 수 있는 데이터 구조로 전환, ② 그에 맞춘 서버 API·관리자 웹·모바일 앱 수정, ③ 서비스를 멈추지 않고 기존 데이터를 그대로 옮기는 것이었습니다. 완료 기준은 기존 챕터·시리얼 코드·학습 진도 데이터가 기본 교재로 빠짐없이 옮겨지고, 구버전 앱이 업데이트 없이도 그대로 동작하며, 관리자 웹에서 새 교재를 등록해 시리얼 코드를 발급할 수 있는 상태였습니다. 이용자 수나 학습량 같은 운영 성과 목표는 이번 범위에 포함되지 않았습니다.

네오렉트의 역할

어디까지 수행했나요?

네오렉트는 데이터베이스 마이그레이션 설계와 적용, 서버 API 확장, iOS·Android 앱의 교재 선택 흐름 추가, 관리자 웹의 교재 관리 기능 추가를 담당했습니다. 함께 진행한 운영 정리 작업은 이전·현재 버전이 섞여 있던 인프라를 구분하고, 서버·안드로이드·iOS·관리자 웹을 각각 독립 저장소로 분리한 범위까지입니다. 교재 명칭과 표지 자료는 고객이 제공하기로 한 항목이며, 앱 심사 제출 시점은 그 자료 수령 이후로 정리했습니다.

주요 기능

무엇을 만들었나요?

  • 교재 선택 화면 — 학습자가 앱에 들어오면 자신이 보유한 교재 목록을 불러와 학습할 교재를 고릅니다. 아직 등록하지 않은 교재는 잠금 표시로 구분됩니다.
  • 시리얼 코드로 교재 열기 — 학습자가 8자리 시리얼 코드를 입력하면 그 코드에 연결된 교재가 계정에 매핑되어 바로 학습할 수 있게 됩니다.
  • 교재별 학습 진도 — 사용자와 교재를 묶어 진도를 저장하므로, 한 사람이 여러 교재를 각각의 진도로 동시에 학습할 수 있습니다.
  • 일일 학습과 단어 상세 — 하루에 학습할 단어 수를 고르면 그 기준으로 일자별 학습 목록이 구성되고, 단어마다 발음기호·뜻·예문을 확인하며 진행합니다.
  • 북마크와 북마크 테스트 — 학습 중 저장한 단어를 모아 보고, 저장한 단어만으로 테스트를 볼 수 있습니다. 북마크 응답에 예문이 함께 내려가도록 보완했습니다.
  • 챌린지 테스트 — 교재 전체 단어에서 70·100·150개를 무작위로 뽑아 객관식으로 출제합니다.
  • 관리자 교재 등록 — 운영자가 교재명과 설명, 표지 이미지를 넣고 챕터·단어·뜻·예문 CSV 네 개를 올리면 교재 한 권이 통째로 등록됩니다.
  • 관리자 시리얼 코드 발급 — 운영자가 교재를 고르고 수량을 입력하면 8자리 코드가 일괄 생성되고 엑셀 파일로 내려받을 수 있습니다. 단어·뜻·예문·오답 선지는 관리자 웹에서 개별 수정합니다.

해결 과정

제약을 어떻게 풀었나요?

  1. 제약 1

    운영 중인 서비스라 스키마를 바꾸는 동안 서비스를 멈출 수 없었고, 업데이트하지 않은 구버전 앱이 계속 요청을 보내는 상황이었습니다.

    의사결정: 기존 데이터를 모두 기본 교재 한 권에 소속시키고, 교재를 지정하지 않은 요청은 서버가 기본 교재로 처리하도록 정했습니다. 구버전 앱을 강제 업데이트시키지 않기 위한 선택이었습니다.

    구현: 교재 테이블을 만들고 챕터·시리얼 코드·학습 진도에 교재 외래키를 추가한 뒤, 기존 챕터 41건과 시리얼 코드 55,367건, 학습 상태 7,494건을 기본 교재로 옮겼습니다. 마이그레이션은 단계별 SQL로 나누고 롤백 스크립트를 함께 작성해 적용 후 검증했습니다.

  2. 제약 2

    교재가 여러 권이 되면 교재마다 1번 챕터가 생기고, 한 사용자가 교재별로 서로 다른 진도를 갖게 되어 기존의 단일 제약조건과 충돌했습니다.

    의사결정: 중복을 막던 제약을 교재 단위 복합 조건으로 다시 설계했습니다. 데이터 단계에서 교재별 분리를 보장해야 앱과 관리자 웹 양쪽의 예외 처리를 줄일 수 있다고 판단했습니다.

    구현: 챕터는 번호만 보던 제약을 교재와 번호를 함께 보는 제약으로, 학습 진도는 사용자만 보던 제약을 사용자와 교재를 함께 보는 제약으로 바꿨습니다. 그 결과 교재마다 같은 챕터 번호를 쓰면서도 진도는 따로 쌓입니다.

  3. 제약 3

    이전 버전과 현재 버전의 도메인·인프라가 섞여 있어 운영 중 작업 대상을 혼동할 위험이 있었습니다.

    의사결정: 코드와 인프라의 경계를 먼저 나눈 뒤 기능 작업을 진행하기로 했습니다.

    구현: 서버·안드로이드·iOS·관리자 웹을 각각 별도의 비공개 저장소로 분리하고, 서버의 DB 접속 설정을 운영·개발·테스트 환경으로 나눠 로드하도록 정리했습니다.

결과

무엇이 달라졌나요?

기존 데이터 이관
챕터 41건 · 시리얼 코드 55,367건 · 학습 상태 7,494건을 기본 교재로 이관
근거: 고객 제공 개발 완료 보고서의 마이그레이션 적용·검증 기록 (비공개)
배포 준비 상태
iOS 1.1.6(빌드 9) · Android 1.1.0(버전코드 46) 빌드까지 완료, 교재 명칭·표지 자료 수령 후 스토어 제출
근거: 고객 제공 개발 완료 보고서의 산출물 항목 (비공개)

화면

실제 화면과 구조

'책을 선택해주세요' 문구 아래 교재 카드 두 장이 놓여 있고 오른쪽 카드에는 자물쇠 표시가 있는 앱 화면
학습자가 보유한 교재를 고르는 화면. 잠긴 교재는 시리얼 코드로 등록합니다.
영어 단어 한 개와 발음기호, 번호가 매겨진 뜻 세 개, 추가 어휘가 표시된 학습 화면
일자별 학습 화면. 단어마다 발음기호와 뜻, 추가 어휘를 확인합니다.
'챌린지 테스트' 제목 아래 70 단어·100 단어·150 단어 테스트 선택지가 나열된 화면
교재 전체 단어에서 무작위로 출제하는 챌린지 테스트 선택 화면.
교재 관리 목록 위에 '새 교재 추가' 창이 열려 교재명·설명 입력란과 표지 이미지, 챕터·단어·뜻·예문 CSV 선택 항목이 보이는 관리자 웹 화면
관리자 웹의 교재 등록. CSV 네 개를 올리면 교재 한 권이 통째로 등록됩니다.
단어 추가 화면에 단어·음성기호·챕터·뜻·정답·오답 선지·예문 입력란이 차례로 놓인 관리자 웹 화면
단어 하나에 뜻과 예문, 오답 선지를 등록하는 관리자 웹 화면.

사용 기술

SwiftKotlinNode.js · TypeScriptReactMySQLAWS

발행 2026.10.06

비슷한 프로젝트를 준비 중이신가요?

배경과 제약 조건을 알려주시면 이 사례의 경험을 바탕으로 진행 방식과 예상 범위를 제안드립니다.