9,000개의 콘텐츠, 1초 안에 추천하기
안녕하세요, 코드넛 개발팀 KIM.S입니다.
지난 글 「넷플릭스에는 '이것'이 없다」에서 저희는 교육 추천이 엔터테인먼트 추천과 왜 근본적으로 다른지를 이야기했어요. 그리고 마지막에 약속을 하나 드렸죠 — 싱가포르 myGooRoo LMS 사례를 다음 글에서 좀 더 풀어보겠다고요. 오늘이 그 글입니다. 기능 목록이 아니라, 실제로 막혔던 지점과 그때 내린 결정들에 대한 기록이라고 봐주시면 좋겠어요.
시작은 아주 단순한 문제였습니다
myGooRoo에서 튜터(선생님)는 학생에게 비대면 학습을 배정하고, 그 안에 콘텐츠를 담아 레슨을 설계합니다. 문제는 그 콘텐츠가 약 9,000개라는 것이었어요. 퀴즈, PDF 워크시트, 유튜브 기반 동영상, 게임, 튜터가 직접 만든 것까지 형식도 제각각이고요.
튜터가 이 9,000개를 일일이 뒤져서 "이 학생에게 지금 필요한 것"을 찾아내는 건 사실상 불가능합니다. 그래서 저희가 만든 추천 시스템의 목표는 명확했습니다.
튜터가 레슨을 짜는 그 순간, 추천이 즉시 떠야 한다. 응답은 1초 미만.
이 한 문장이 이후 모든 설계 결정을 지배했습니다.
콘텐츠를 개념으로 연결하는 좌표계로는 3단계 분류 — 대분류(도메인) → 중분류(스킬 스트랜드) → 소분류(서브토픽) — 를 세웠습니다. 스킬 스트랜드는 수학 22개, 영어 14개로, 학생 한 명은 이 36차원의 역량 벡터로 표현됩니다.

이야기 ①: 콘텐츠에 '순서'를 입히기
영화나 드라마 OTT에서는 액션영화를 봤다고 다음 액션 영화가 해금되지는 않습니다. 하지만 교육은 다릅니다. 분수를 모르면 약분을 배울 수 없어요. 순서와 선수관계가 콘텐츠의 본질입니다.
그런데 현실의 9,000개 콘텐츠는 순서가 이렇게 뒤섞여 있었습니다.
- 워크시트 순서와 온라인 액티비티 순서가 서로 따로 존재
- 어떤 콘텐츠는 순서가 아예 없고
- 어떤 건 1번부터 n번까지 단방향으로 일렬
- 어떤 건 선행이 충족돼야 후행이 열리는 커스텀 선후 그래프
그래서 저희가 한 일은, 같은 과목 안에서 워크시트 순서와 액티비티 순서를 하나의 선후 관계로 병합하는 것이었습니다. 흩어진 순서 데이터를 하나의 방향성 그래프(DAG)로 재정의한 거죠. 순서가 아예 없는 콘텐츠는 스킬 스트랜드 수준에서 위치를 부여하고, 커스텀 선수관계는 그래프 엣지로 그대로 태웠습니다.
그 위에 레벨업/해금 구조를 얹었습니다. 스킬 스트랜드마다 레벨(대략 학년 수준에 대응)이 있고, 일정 점수 이상(예: 10점 만점에 7점)을 받으면 다음 레벨에 도전할 수 있게 열립니다. 반대로 상위 레벨에서 점수가 낮으면 하위 학습을 재학습(Relearn)으로 추천해 다시 다지게 합니다.
여기서 개발하며 얻은 감각 하나.
순서는 콘텐츠가 혼자 가진 속성이 아닙니다. 학습자의 '지금 위치'와 만나야 비로소 의미가 생깁니다.
같은 "3학년 덧셈"이라도, 2학년에서 막힌 학생과 4학년으로 넘어가려는 학생에게는 완전히 다른 의미를 갖는다는 뜻이에요.
이야기 ②: 콘텐츠를 '읽어내기' — 메타데이터 추출

추천 품질의 8할은 결국 콘텐츠를 얼마나 깊이 이해하느냐에서 갈립니다. 제목과 분류만으로 추천하면 그건 그냥 문자열 매칭이지, 추천이 아니거든요. 그래서 콘텐츠의 내용까지 분석해 "이게 어떤 콘텐츠인가"를 파악하도록 만들었습니다.
PDF 워크시트는 영어 쪽은 텍스트가 대부분이라 그나마 수월했습니다. 문제는 수학이었어요. 기하 도형처럼 텍스트로 표현되지 않는 요소가 많아서, 이걸 어떻게 의미 있는 메타데이터로 뽑아낼지가 별도의 숙제였습니다.
유튜브 동영상은 더 까다로웠습니다. myGooRoo의 영상 링크는 영상 전체를 가리키는 게 아니라, 한 영상 안의 특정 구간을 가리켰거든요.
https://www.youtube.com/embed/xxxx?start=21&end=78
즉 하나의 유튜브 영상 안에 여러 개의 학습 조각이 들어 있고, 각 콘텐츠는 그중 한 구간이었던 겁니다. 그래서 링크가 가리키는 그 구간의 스크립트만 잘라내어 메타데이터로 분석하는 방식으로 접근했습니다. 처음엔 예상 못 한 지점이라 시간이 꽤 갔지만, 결국 구간 단위 추출·분석 파이프라인으로 정리해 동작하게 만들었습니다.
이야기 ③: 왜 우리는 '추천 시점'에 AI를 쓰지 않았나
앞서 말했듯 목표는 1초 미만 응답이었어요. 그런데 추천 요청이 들어올 때마다 9,000개 콘텐츠를 AI로 스코어링한다면? 튜터가 레슨을 짜다가 매번 몇 초씩 기다려야 하고, 튜터가 결과를 조금 손보면 레이턴시는 더 크게 흔들립니다. 현재 기술로는 현실적이지 않았습니다.
그래서 저희는 방향을 뒤집었습니다.
계산은 미리, 응답은 즉시.
추천 시점에 계산하는 대신, 콘텐츠별 점수와 학습 로드맵을 사전에 계산해 깔아둡니다. 각 추천 관점(진척도, 유사도 등)에 따른 가중치도 미리 반영해 두고요. 그다음 학생의 스킬 벡터가 대입되면, 시스템은 무거운 계산을 다시 하지 않습니다. 단지 "이 학습자가 로드맵 어디에 서 있는가"만 판단해서 즉시 답을 내놓습니다.
덕분에 학습 이력만 연동되면 추가적인 AI 연산 없이 바로 추천이 가능해졌습니다. 이게 이 시스템의 핵심 강점이에요.
물론 트레이드오프가 있습니다. 실시간 유연성 일부를 내주는 대신 예측 가능한 속도를 얻은 것이고, 콘텐츠가 바뀌면 사전 계산을 갱신해야 한다는 숙제가 남습니다. 이 지점을 어떻게 자동화할지가 지금 저희가 붙들고 있는 다음 과제입니다.

우리는 선생님을 가장 우선하여 개발합니다
추천을 자동으로 던지고 끝냈다면 훨씬 쉬웠을 겁니다. 하지만 교육에는 사람이 판단해야 하는 영역이 분명히 있어요.
그래서 스킬 점수는 시작값 4점에서 튜터가 ±로 직접 조정할 수 있게 했습니다(원본은 보존하고 조정분만 반영). 순서 역시 시스템이 정리하되 튜터가 통제할 수 있게 열어뒀고요. 무엇보다 모든 추천에는 '왜 이 콘텐츠인가'가 근거로 따라붙습니다. 도메인 → 스킬 스트랜드 → 학년으로 이어지는 경로와 학생의 약점 점수가 선으로 연결돼, 추천이 블랙박스가 아니라 눈으로 추적 가능한 결과가 됩니다.
우리는 튜터를 대체하려는 게 아니라, 튜터의 눈을 넓히려는 겁니다.
교육 콘텐츠 추천은 결코 쉬운 문제가 아닙니다. 순서, 이해, 즉답 — 이 세 가지를 동시에 만족시켜야 하고, 하나라도 놓치면 추천은 그럴듯한 제목 매칭으로 무너집니다. 그래서 많은 추천 시스템이 교육 앞에서 멈춰 섭니다.
이번 myGooRoo 개발을 거치며, 저희는 이 어려운 문제를 실제로 풀어낼 수 있다는 확신을 얻었습니다. OTT는 다음에 볼 것을 추천하지만, 저희는 다음에 배울 것을 추천합니다. 그 차이를 메우는 방법을, 이제 코드넛은 손에 쥐고 있습니다.
그리고 이 자신감은 교실 안에만 머물지 않습니다. 코드넛은 지금 공공 AX 프로젝트를 통해 직업훈련과 HRD(인재개발) 영역에도 같은 엔진으로 도전하고 있습니다. "학습자가 지금 어디에 있고, 다음에 무엇을 배워야 하는가" — 이 질문은 초·중등 교육이든 성인의 직무 역량 개발이든 본질이 같기 때문입니다.
배움에는 순서가 있고, 그 순서를 사람마다 다르게 짚어주는 일. 코드넛은 그 일을 학교에서, 그리고 이제 일터에서 이어갑니다.