1년째 개발하던 LMS, 마감 챌린지 덕분에 드디어 완성.

발행: (2026년 6월 8일 AM 01:02 GMT+9)
6 분 소요
원문: Dev.to

출처: Dev.to

이 글은 GitHub Finish‑Up‑A‑Thon 챌린지에 제출한 작품입니다.
Training Theatre (TTT)는 멀티 테넌트 LMS로, 강사가 가르치는 방식에 따라 세 가지 형태로 강의를 만들 수 있습니다:

  • Story — 에세이 작가가 글을 쓰듯이 긴 형식의 텍스트 콘텐츠.
  • Video — 모두가 익숙한 전통적인 LMS 방식: 동영상을 업로드하고, 챕터를 나누고, 배포한다. Udemy·Coursera 형태.
  • Slide — 20개가 넘는 템플릿 카탈로그에서 조합 가능한 덱. TTT 디자인 예산의 대부분이 여기 쓰이며, 다른 LMS와 차별화되는 부분이기도 합니다.

슬라이드가 만들어지기 전, 사용자는 설정 흐름을 거칩니다. 무엇을 만들고 있는지(독립 강좌인지 번들 프로그램인지), 강좌 구조가 어떻게 되는지(다중 포맷 모듈인지 반복 패턴인지), 어떤 교육 패턴이 콘텐츠에 맞는지를 선택합니다. 슬라이드 편집기에 도착했을 때 강좌 형태는 이미 결정된 상태입니다.

슬라이드 측면의 워크플로는 다음과 같습니다. 강사는 슬라이드 편집기를 열고, 카탈로그에서 레이아웃을 고릅니다(예: hero‑text, three‑column, comparison, team, closing‑cta 등). 그러면 캔버스가 나타납니다. 각 템플릿은 이름이 지정된 zone 집합을 노출합니다—예: 헤드라인 zone, 아이템 zone, CTA zone 등—그리고 각 zone은 어떤 섹션 타입을 받아들일 수 있는지(text, list, image, callout, quote, stats, table)와 몇 개의 섹션을 담을 수 있는지를 선언합니다. 강사는 zone을 채우고, 편집기는 그 결과를 SlideGroup 레코드(템플릿 선택, zone 할당, 배경, 강조 색, 강사 노트)로 저장합니다. 학습자는 LearnerSlideDeck 안의 SlideCanvas를 통해 동일한 데이터를 렌더링해서 보게 됩니다. 전체 카탈로그는 선언형이며, 새 템플릿을 추가한다는 것은 zone을 정의하고, 편집기 캔버스를 만들고, 학습자 렌더러를 구현한다는 뜻입니다.

스택: Next.js (App Router) + TypeScript + Prisma/PostgreSQL, 프론트엔드에서는 Zustand와 React Query, 풍부한 텍스트 편집을 위해 Tiptap, 스타일링은 Tailwind.

TTT는 나에게 첫 번째 실전 프로젝트이기도 합니다. 9‑5 직장인 기술 지원 업무와 병행해 1년 넘게 개발해 왔으며, 여기서 처음 실수를 겪으며 배운 것이 현재 내가 소프트웨어를 배포할 때 가장 많이 쓰는 지식입니다. 잘못된 스키마 선택을 마이그레이션한 경험, 코드베이스 전체에 감사 로깅을 뒤늦게 적용한 일, 두 번이나 재구축한 모더레이션 흐름 등 말이죠. 그래서 절반만 완성된 부분을 마무리하는 일은 단순히 코드를 정리하는 것이 아니라, TTT를 포트폴리오 작품으로 만들어 계약 제안이나 정규 엔지니어 직무 인터뷰에서 자신 있게 보여줄 수 있게 하는 작업이었습니다. Finish‑Up‑A‑Thon은 그런 마감일을 제공해 주었습니다.

챌린지를 위해 나는 슬라이드 템플릿 시스템에 집중했습니다—내가 가장 자부심을 느끼는 제품 부분이죠. 목표는 강사에게 더 많은 레이아웃 옵션을 제공하는 것이었고, 이를 위해 closing‑cta, feature‑list, agenda‑grid 세 가지 템플릿을 작업했습니다. 일부는 새로 만든 것이고, 일부는 기존 템플릿을 수정해 원래 구현이 지원하지 못했던 레이아웃 패턴을 다루게 했습니다.

🔗 프로젝트: Training Theatre on GitHub
🔗 라이브 URL: Training Theatre

Before & After — Slide Templates

Before

(이미지)

After

(이미지)


🎥 Video Walkthrough

Before

*(이미

0 조회
Back to Blog

관련 글

더 보기 »