Elipair
← 프로젝트 목록

완익세종

2025.12.23 – 2025.12.24 · React · Next.js

SW-AI 해커톤 장려상

AI 기반 진로-교과목 로드맵 추천 서비스 · 팀 완익세종

React · Next.js

배경

제13회 세종대학교 SW-AI 해커톤에서 "AI 기반 진로-교과목 로드맵 추천 시스템" 주제를 골랐습니다. 어떤 과목을 듣고 방학에 무엇을 할지는 저희 팀도 하던 고민이었습니다.

완익세종은 성적표 Excel 파일과 희망 진로를 입력하면, Google Gemini가 학기별 추천 과목과 방학별 활동을 담은 로드맵을 만들어 주는 서비스입니다. 팀 완익세종(홍의민·이정연·박성열)으로 2025년 12월 23일 오후부터 24일 아침까지 개발했고, 저는 프론트엔드를 맡았습니다. 백엔드는 별도 저장소의 Spring Boot 서버였습니다.

맡은 역할

  • 프론트엔드 전담 — Next.js 저장소의 모든 커밋
  • 화면과 UI 컴포넌트 — 성적표 업로드, 역량 분석, 학기별 타임라인, 애니메이션
  • Next.js API Routes — xlsx 기반 성적표 파싱, Gemini 기반 로드맵 생성
  • AI 챗봇 '세박사' — 과목·교수 검색, Gemini 실패 시 로컬 검색으로 전환
  • 백엔드 연동 — 데이터 구조 불일치 분석 문서, 응답 변환 어댑터

과정

오후에 시작해 저녁 전에 첫 로드맵을 띄웠습니다. 업로드부터 로드맵 생성까지 이어지는 첫 흐름을 2시간이 채 안 돼 완성했습니다.

밤 10시, 백엔드 문서와 프론트엔드 타입이 다르다는 것을 발견했습니다. 그대로 붙이면 학점과 과목 코드가 화면에서 빠지는 상황이었습니다. 바로 고치기 전에 필드 차이를 분석한 문서부터 썼습니다.

새벽 3시에는 원인을 알 수 없는 400 에러를 만났습니다. 백엔드는 상태 코드 외에 아무 정보도 주지 않았습니다. 추적해 보니 실패 시 로컬 모드로 폴백하는 경로가 여전히 백엔드 주소로 요청을 보내고 있었습니다.

고치고 나니 이번에는 로드맵이 비어 있었습니다. 응답 필드명이 명세와 달라 어댑터가 모든 과목을 걸러 내고 있었습니다. 시간이 없어 두 형식을 모두 받는 임시 처리를 넣었습니다.

기술적 결정

Mock·Local·Backend 3가지 운영 모드

  • 상황백엔드가 별도 저장소에서 동시에 개발되고 있었습니다.
  • 결정UI용 Mock, Gemini를 직접 부르는 Local, Spring Boot를 쓰는 Backend 모드를 두고 환경 변수로 전환했습니다.
  • 결과백엔드가 준비되기 전에도 화면과 AI 흐름을 먼저 완성할 수 있었습니다.

Backend 모드에서는 폴백하지 않기

  • 상황백엔드 실패 시 로컬로 넘어가는 폴백이 백엔드 주소를 그대로 써서, 진짜 원인이 400 에러 뒤에 가려졌습니다.
  • 대안폴백 주소를 로컬로 바로잡거나, 폴백 경로에도 어댑터를 적용하는 방법을 검토했습니다.
  • 결정Backend 모드에서는 폴백을 없애고 백엔드 오류를 그대로 반환하게 했습니다.

백엔드 응답은 어댑터에서 프론트엔드 타입으로 변환

  • 상황백엔드 명세와 프론트엔드 구조가 달랐고, 실제 응답은 명세와도 달랐습니다.
  • 결정응답을 프론트엔드 타입으로 바꾸는 어댑터를 두고, 명세와 다른 형식은 받되 경고 로그를 남겼습니다.
  • 결과백엔드 수정을 기다리지 않고 로드맵을 표시했고, 호환 처리는 임시 조치로 문서에 남겼습니다.

결과

  • 제13회 세종대학교 SW-AI 해커톤 장려상
  • 성적표 업로드 → 역량 분석 → 학기별 로드맵 → Markdown 저장 → 챗봇 상담까지 이어지는 흐름을 해커톤 기간 안에 구현했습니다.
  • 백엔드-프론트엔드 API 불일치, 400 에러 원인, 응답 형식 불일치 분석을 문서로 남겼습니다.

배운 점

  • 명세 문서만 믿고 연동하면 안 됩니다. 문서와 코드, 실제 응답이 세 갈래로 달랐습니다.
  • 폴백은 실패를 숨길 수 있습니다. 안전장치로 넣은 폴백이 원래의 실패를 가리고 원인 모를 400 에러만 남겼습니다.