2024년 12월, 대전시 진로융합교육원에서 내가 재학 중인 대덕소프트웨어마이스터고등학교에 하나의 의뢰가 들어왔다. 중학생들을 대상으로 한 창업경영 진로체험 수업에서 사용할 모의주식 투자 플랫폼을 만들어달라는 것이었다.
진로융합교육원은 초·중·고등학생들에게 다양한 진로 체험을 제공하는 기관이다. 그 안에 '창업 경영 마을'이라는 프로그램이 있고, 거기서 중학생들이 시나리오 기반으로 주식 투자를 체험하며 경제 개념을 배운다. 우리가 만들 서비스는 그 수업의 핵심 도구가 될 예정이었다.
모의주식의 줄임말, MOZU. 이렇게 산학협력 프로젝트가 시작됐다.
(초기 기획 당시의 유저 플로우)


(진짜 어려웠던 도메인 이해하기..)

v1 개발은 백엔드 3명, 프론트엔드 3명으로 구성된 6인 팀에서 시작됐다. 나는 프론트엔드 리드를 맡았다. 학교 프로젝트와는 결이 달랐다. 단순히 기능을 구현하는 게 아니라, 실제 수업에서 중학생들이 사용할 서비스를 만들어야 했기 때문이다.
선생님 화면(Admin)과 학생 화면(Student)을 나누어 설계했다. 선생님은 수업을 운영하고 학생들의 활동을 모니터링하고, 학생들은 시나리오에 따라 주식을 사고팔며 투자를 체험한다. 실시간 데이터 동기화를 위해 SSE를 도입했는데, 이것이 나중에 나를 밤새우게 만들 줄은 몰랐다.
(FE 리드시절 태스크 백로그 보드)

2025년 8월, v2 프로덕트를 맡게 되면서 모든 게 달라졌다.
프론트엔드 리드에서 PO(Product Owner)이자 팀 리더가 됐다. 팀 규모도 커졌다. 프론트엔드 3명, 백엔드 5명. 총 8명의 팀을 이끌어야 했다. 고등학생이 8명의 개발팀을 통솔한다는 건, 생각보다 훨씬 어려운 일이었다.
나는 프로덕트의 체계화를 위해 많은 것들을 도입했다. 11일 단위 스프린트, Jira로 이슈와 백로그를 관리하고, PR 자동화까지 구축했다. 애자일 기반 프로세스를 직접 설계하고 운영하면서 "개발만 잘한다고 되는 게 아니구나"를 온몸으로 배웠다. 사람마다 일하는 속도가 다르고, 소통의 방식이 다르고, 동기부여의 포인트가 다르다. 코드를 짜는 것보다 사람을 이해하는 게 더 어려웠다.
하지만 이 시기가 나를 가장 성장시켰다. MOZU는 더 이상 과제가 아니었다. 나의 프로덕트였다.
[MOZU] Gemini 2.5 flash로 이슈 -> PR 워크플로우 구축하기
[MOZU] AWS 엔지니어링 도입기 - 타겟 선정과 모델링
(애자일하게 사용했던 Jira, 세팅하는 데 애좀 먹었다..)

가장 독특하고도 어려웠던 경험은 비전공자인 선생님과의 소통이었다.
기관에서 요구사항을 제시해주시는 선생님은 개발을 모르시는 분이었다. 당연한 일이다. 하지만 그 "당연함"이 실제 업무에서 얼마나 큰 간극을 만드는지, 직접 겪어보기 전까지는 몰랐다.
선생님이 "학생들이 주식을 살 때 좀 더 실감나게 해주세요"라고 말씀하시면, 그것이 UI 애니메이션을 의미하는 건지, 실시간 가격 변동 피드백을 의미하는 건지, 아니면 매수 확인 프로세스의 단계를 추가하라는 건지를 파악해야 했다. 모호한 요구사항을 구체적인 도메인 설계로 번역하는 일. 이건 어떤 수업이나 동아리에서도 가르쳐주지 않는 능력이었다.
면담을 거듭하면서 나만의 방식이 생겼다. 선생님의 말씀을 듣고, 화면 흐름으로 다시 그려서 보여드리고, "이런 의미가 맞으실까요?"라고 확인하는 과정을 반복했다. 비전공자의 언어를 코드로 번역하는 번역가. 그게 PO로서 내가 해야 할 가장 중요한 일이었다.
(요구사항과 다양한 문서들을 정리한 파일들)


모주를 진행하면서 가장 기억에 남는 밤이 있다.
장학사님 앞에서 시연하는 날이 다음 날 아침이었다. 그런데 전날 오후, 프론트엔드에서 SSE 요청을 처리하던 중 장애가 터졌다. 실시간 데이터 스트리밍이 끊기면 수업 자체가 불가능하다. 시연에서 이 기능이 작동하지 않으면 전부 무너지는 거였다.
팀원들은 각자의 파트가 있었고, 이건 프론트엔드 SSE 처리의 문제였다. 나 혼자 해결해야 했다.
밤새 코드를 분석하고, 디버깅하고, 재현하고, 수정하고, 또 재현하고. 새벽을 넘기고, 동이 트기 시작할 무렵 드디어 원인을 잡았다. 수정을 마치고 테스트를 돌렸을 때 정상 작동하는 걸 확인한 그 순간의 안도감은 말로 설명하기 어렵다.
그리고 몇 시간 뒤, 시연은 성공했다.
(시연 전날 장애를 발견한 모습)

(시연을 도와주셨던 고마우신 선배님들 ㅎㅎ)

(성공적인 시연 당시의 사진)

(시연 후 선배님들과 선생님과 소고기 회식 ㅎㅎ)

장학사님 시연 외에도 많은 대외 활동이 있었다. 그중 소프트웨이브 전시가 특별했다.
소프트웨이브는 국내 소프트웨어 산업 전시회다. 거기엔 현직 개발자, CEO, CTO 등 실제 업계에서 일하는 사람들이 온다. 그 앞에서 고등학생인 내가 MOZU를 시연하고, 서비스를 소개해야 했다.
솔직히 긴장됐다. "학생 프로젝트"라고 가볍게 볼 수도 있는 자리에서, 나는 이게 가볍지 않다는 걸 보여주고 싶었다. 시나리오 기반 모의투자 시뮬레이션의 구조를 설명하고, 선생님 화면과 학생 화면의 실시간 연동을 직접 시연했다.
반응은 기대 이상이었다. 매우 흥미롭게 봐주셨고, 진지하게 질문도 해주셨다. "나의 프로덕트"를 세상에 꺼내놓고, 그것이 인정받는 경험. 그건 코드를 천 줄 짜는 것보다 더 큰 동기부여가 됐다.

MOZU는 원래 학교의 자체 인프라인 xquare를 통해 클라우드로 운영되고 있었다. 프론트엔드는 Vercel, 백엔드는 자체 인프라로 서비스했다.
그런데 실제 기관 납품을 준비하면서 문제가 생겼다. 예산, 네트워크 환경, 안정성. 복합적인 이유로 기관 자체 데스크톱에 온프레미스로 마이그레이션해야 했다. 클라우드 서비스를 교실 한 대의 컴퓨터 안에 집어넣어야 하는 것이다.
나는 프론트엔드 개발자다. 인프라는 내 영역이 아니었다. 하지만 PO로서 "그건 내 일이 아닙니다"라고 말할 수 없었다. Docker Compose로 MySQL, Redis, Spring Boot 백엔드, nginx를 하나의 스택으로 묶고, nginx 리버스 프록시로 Admin(:80)과 Student(:3001) 두 개의 SPA를 서빙하는 구조를 설계했다.
기관에 직접 출장을 가서 네트워크 환경을 조사했다. 유선과 무선이 서로 다른 서브넷에 있다는 걸 발견했다. 서버 데스크톱은 유선에, 수업용 노트북들은 WiFi에 연결되니 서로 통신이 안 되는 상황. 서버의 WiFi IP를 통해 같은 네트워크에서 접근하도록 아키텍처를 수정했다.
서브넷 마스크를 분석하고, Docker 포트 매핑을 설계하고, SSE 통신의 안정성을 걱정하며 nginx 설정을 만지는 경험. "새로운 과제를 해결해야 한다는 부담"과 "새로운 걸 해볼 수 있다는 설렘"이 동시에 밀려왔다.

온프레미스 전환에서 가장 신경 쓴 건 안정성이었다.
이건 개인 프로젝트가 아니다. 기관에서 수업에 실제 운영되는 서비스다. 수업 중간에 데이터가 유실되거나 서비스가 멈추면, 그건 단순한 버그가 아니라 수업 자체가 망하는 것이다. 중학생 20명이 투자 시뮬레이션을 하다가 화면이 멈추는 상황을 상상해보면, 그 책임감의 무게를 느낄 수 있다.
그래서 서비스 통신 설계에 큰 공을 들였다. SSE 연결이 끊어졌을 때의 재연결 로직, MySQL과 Redis의 헬스체크, 컨테이너 자동 재시작 정책, 데이터 백업 스크립트까지. 기관 담당자분이 개발자가 아니시기 때문에, start.bat 한 번 클릭으로 서비스가 올라가고, backup.bat으로 데이터를 백업할 수 있도록 만들었다.
기술은 결국 사용자를 위해 존재한다. 그리고 여기서 사용자는 중학생들과, 그 수업을 운영하시는 비전공자 선생님이다.
(실제 수업이 이루어지는 공간)

완벽한 프로젝트는 없다. 나에게도 아쉬움이 있다.
v2에서 FSD(Feature-Sliced Design) 아키텍처로 마이그레이션했는데, 더 정교하고 깔끔한 컴포넌트 패턴을 만들고 싶었다. 하지만 납품 일정에 쫓기면서 이상과 현실 사이에서 타협해야 했다. "지금 동작하는 코드"와 "내가 원하는 수준의 코드" 사이의 차이. 이건 아마 모든 개발자가 가지고 있는 영원한 숙제라고 생각한다.
다시 한다면, 초기 설계 단계에서 컴포넌트 컨벤션을 더 엄격하게 잡고 시작했을 것이다. 하지만 그 아쉬움조차 "다음엔 더 잘할 수 있다"는 자산이 된다.

납품 당일, USB 하나에 Docker 이미지와 설정 파일을 담아서 기관으로 향했다.
예상대로 순탄하지만은 않았다. 서버 데스크톱에는 WiFi 어댑터가 없었다. 사전 조사에서 WiFi IP로 통신하려던 계획이 틀어졌다. 서버를 WiFi 공유기의 LAN 포트에 유선으로 연결해서 같은 네트워크에 진입시키는 방식으로 해결했다. Docker 이미지를 로드하는 과정에서 이미지 이름이 매칭되지 않는 문제가 생겼고, 포트 80을 다른 서비스가 점유하고 있어서 nginx가 올라가지 않는 문제도 있었다.
하나씩 해결했다. 이미지에 태그를 다시 달고, 포트를 점유한 서비스를 중지시키고, 컨테이너를 다시 올렸다. 장학사 시연 전날 밤새워 장애를 해결하던 그때와 같았다. 문제는 언제든 생기지만, 해결하지 못할 문제는 없다.
그리고 드디어, 선생님이 데스크톱을 열면 서비스가 자동으로 시작되고, 학생들이 노트북 브라우저에서 주소를 입력하면 모의투자 화면이 뜨는 것을 확인했다. 납품이 완료된 순간이었다.
(기사에 나온 모주 ㅎㅎ)


2024년 12월부터 지금까지 약 15개월. MOZU는 내게 단순한 프로젝트가 아니었다.
프론트엔드 리드에서 시작해 PO이자 팀 리더가 됐다. 8명의 팀을 이끌며 스프린트를 운영하고, 비전공자 선생님의 요구사항을 도메인 설계로 번역하고, 장학사 앞에서 시연하고, 소프트웨이브에서 CTO에게 프로덕트를 소개하고, 클라우드 서비스를 교실 한 대의 데스크톱에 담았다.
기술적으로 SSE, Docker, nginx, 온프레미스 인프라까지 영역을 넓혔고, 그보다 더 크게는 "나의 프로덕트를 성장시킨다는 것"이 무엇인지를 배웠다. 코드를 짜는 건 그 과정의 일부일 뿐이었다. 사용자를 이해하고, 팀을 이끌고, 위기를 넘기고, 아쉬움을 안고도 전진하는 것. 그 전부가 프로덕트를 만드는 일이었다.
MOZU는 내 포트폴리오의 핵심이지만, 그보다 먼저 나라는 개발자를 만든 프로젝트다.
곧 교실에서 중학생들이 모주를 열 것이다. 그 순간을 기대하며, 이 회고를 마친다.