🎥 웹 서비스 시연 영상
* 편의를 위해 시연 영상에서는 분석 대기 공백을 편집으로 잘랐습니다.
🏀 🚀 우테코 오픈미션 도전기
농구 슛폼 분석 프로그램
⏳ 영상 분석 중입니다. 분석은 보통 1~2분 가량 소요됩니다. 절대 새로고침 하지마세요! 분석 중이던 영상 작업이 초기화됩니다.
basketball-coach.up.railway.app
GitHub - yuncic/BASKETBALL-COACH
Contribute to yuncic/BASKETBALL-COACH development by creating an account on GitHub.
github.com
"토이 프로젝트를 넘어 실제 사용자에게 닿는 서비스로"
이번 우테코 슬로건은 한 단어였다.
도전.
나는 이 말을 곱씹으며 이번 미션에서 어떤 도전을 해야 할지 고민했다.
프리코스 때도, 여러 토이 프로젝트를 할 때도 늘 "이 정도면 됐지"라는 선에서 만족하곤 했다.
하지만 이번만큼은 그런 식으로 끝내고 싶지 않았다.
2주라는 시간 동안, 내가 정말로 원했던 프로젝트를
"토이 프로젝트"가 아닌 실제로 동작하는 서비스로 만들어보고 싶었다.
그래서 나는 그동안 머릿속에서만 상상하고 메모장에만 적어두던 프로젝트를 꺼내 들었다.
"사용자의 슛 영상을 분석하여 효율성과 타이밍을 로 평가하는 웹 서비스."
스포츠전공자이고, 농구부 활동을 중학교, 고등학교, 대학교까지 꾸준히 하고 있기에 언젠가 꼭 해보고 싶던 아이디어였다.
이번만큼은 이걸 기필코 구현하고 배포해보자는 마음으로 미션을 시작했다.
프로젝트 소개
꾸준히 농구를 해오면서 가장 많이 고민하고, 가장 자주 흔들리는 부분은 바로 ‘슛 자세’ 였습니다.
슛폼은 사람마다 다르고 정답이 없습니다.
하지만 모두가 공통적으로 해결하고 싶어하는 질문은 하나입니다.
“지금 내 슛폼이 역학적으로 효율적인가?”
감각이나 감정에 의존한 연습만으로는 이를 알기 어렵습니다.
코치가 항상 옆에 있는 것도 아니고, 영상을 찍어도 막상 무엇을 기준으로 평가해야 할지 알기 어렵습니다.
그래서 저는 슛 동작을 정량적으로 분석해주는 서비스를 만들고 싶었습니다.
이 프로젝트는
사용자가 업로드한 슛 영상을 기반으로
1. 관절 각도 변화 타이밍 분석
(무릎 → 허리 → 어깨 → 팔꿈치 → 릴리즈의 흐름이 얼마나 일관적인가?)
2. 힘 전달 방향 벡터 분석
(팔과 공의 이동 방향, 질량중심과 공의 이동 방향의 정렬 정도는 어떤가?)
이 두 가지 핵심 지표를 바탕으로
슛폼의 힘 전달 효율성과 타이밍의 정확성을 평가합니다.
즉, 이 서비스는 “이 자세가 좋다 / 나쁘다”처럼 정답을 강요하지 않습니다.
대신 역학적 관점에서 얼마나 효율적인지를 정량적인 수치와 피드백으로 알려 줍니다.
“내 슛폼이 객관적으로 어떤 상태인지 알고 싶다”
“비효율적인 부분만이라도 잡아주면 좋겠다”
라는 농구 유저의 현실적인 니즈를 해결하기 위해 탄생한 프로젝트입니다.
1. 첫 번째 벽
프로젝트 초반부터 솔직히 말해 무서웠다.
"과연 내가 이걸 만들 수 있을까?"
왜냐하면 이 프로젝트의 핵심은 단순한 CRUD도, 로직 분기 처리도 아니었다.
바로 '슛폼 분석 로직' 이었다.
여기엔 너무 많은 기술이 필요했다.
- 각 관절별 각도 계산
- 시계열 smoothing
- 프레임 기반 타이밍 분석
- 속도 회귀(linear regression)
- 벡터 정렬도 계산
- 릴리즈 타이밍 탐색
- 손-공-몸 중심의 관계 분석
나는 지금까지 이런 걸 제대로 공부해본 적이 없었다.
그럼에도 불구하고 서비스의 핵심인 이 부분은 반드시 구현해야 했다.
2. AI 의존에 대한 감정 - 도전의 또 다른 형태
분석 로직을 어느 정도 이해하고 직접 구현하고 싶었지만,
현실적으로는 2주 안에 이 모든 이론을 정리하고 구현하기엔 너무나 버거웠다.
결국 나는 ChatGPT와 Cursor AI의 도움을 받아 로직을 구현했다.
처음에는 너무 떨리고 불편했다.
"내가 한 게 아닌 것 같아."
"이 정도면 그냥 AI가 만든 프로그램을 제출하는 거 아니야?"
"나는 뭘 한 거지?"
솔직하게 말해 현타도 많이 왔다.
하지만 계속 프로젝트를 진행하면서 생각이 조금 달라졌다.
AI가 코드를 대신 치는 건 맞다.
하지만 그 코드를 만들어내기 위해
내가 수십 번 질문하고,
수백 줄의 코드를 이해하려고 애쓰고,
영상 처리부터 배포까지 모든 어려움을 해결하려 한 것 역시 나였다.
AI는 도구일 뿐이고,
이 도구를 가장 치열하게 사용한 건 결국 나였다.
이 경험 덕분에
"AI를 잘 쓰는 것도 개발자의 능력"이라는 걸
조금은 인정하게 되었다.
3. 기술적 설계 - 프리코스때의 경험들..
이번 프로젝트에서 내가 배우고 적용한 것들은 많았다.
1) 프리코스에서 배운 MVP 패턴
프리코스 때는 항상 애매하게만 이해했던 디자인 패턴을
이번엔 웹 앱 전체에 적용했다.
Model: 분석 결과 저장
View: 영상 업로드/리포트 화면
Controller: 전체 흐름 관리
이 구조를 직접 내 프로젝트에 적용해보니
이제야 "아, 이런 느낌이구나."를 체감하게 되었다.
2) TDD 도입
분석 로직 외 부분에서는 테스트 코드를 먼저 작성하면서
안정적인 틀을 만들려고 노력했다.
3) 책임 분리
백엔드 FastAPI, 프론트 JS, 분석 로직, 비동기 통신 등을 분리하고
서버 구조도 정리했다.
프리코스에서 배웠던 개념들이
실제 서비스 개발에서 이렇게 강력한 무기가 되는구나 하는 걸
몸으로 깨달았다.
4. 아쉬웠던 점 - 다음 도전을 위한 숙제들
① 로그인/영상 저장 기능
원래 구현하고 싶었던 기능들은
- 유저별 계정 관리
- 업로드한 영상 히스토리 저장
- 맞춤형 피드백 제공
이렇게 더 있었다.
하지만 이 기능을 위해선 스토리지 서버(AWS S3 등)까지 붙여야 하기에 배포 경험도 없는 상태에서 이건 무리라고 판단했다.
그래서 이번엔 MVP 기능에 집중했다.
② 분석 로직 분할 실패
슛폼 분석 로직은 얽혀 있는 연산이 너무 많아서
책임별로 나누는 것이 사실상 불가능했다.
이 부분은 이론이 더 탄탄해져야 해결 가능한 문제다.
③ 이론 공부 부족
타이밍 분석, 각속도, 벡터 정렬 같은 것들을
완전히 내 힘만으로 구현하지 못했다.
이론 공부를 다시 하고
다음에는 이걸 온전히 내 힘으로 구현해보고 싶다.
그래도 각 관절이 펴지는 타이밍과, 힘의 전달 효율성에 관해선 정말 많이 고민해보고 분석해서 스스로 적용했다.
5. 드디어 배포
이 프로젝트의 마지막 도전은 배포였다.
누군가에겐 별거 아닐 수 있겠지만, 항상 토이프로젝트를 하거나 강의를 들어서 무언가를 만들었을 때
"나중에 제대로 만들면 배포해야지" , "실제 수익성이 없어보이는데 굳이 지금 배포해서 뭐해" 등과 같은 핑계를 대며
지레 겁을 먹어 배포를 시도하지 못했었다.
그래서 나에게 가장 큰 도전이 배포였다.
서버 빌드 오류, PyTorch 버전 충돌, ffmpeg 오류, 파이프라인 제한 초과…
정말 별의별 오류가 다 났다.
진짜 수십 번은 다시 배포한 것 같다.
하지만 결국
에서 내 서비스가 돌아가는 걸 보는 순간
그동안의 고생이 한 번에 녹아내렸다.
"아… 진짜 만든 거구나."
이건 단순히 기능 하나 만든 것이 아니라
내가 상상했던 서비스가 실제로 세상에 나온 순간이었다.
6. 이번 미션에서 얻은 가장 큰 성취
이번 도전에서 내가 얻은 것은 단순한 기술이 아니다.
'지금 내 실력으로는 불가능해 보이는 프로젝트를
실제로 동작하는 서비스까지 밀고 나갈 수 있다'는 자신감.
물론 모든 로직을 100% 이해한 건 아니다.
모든 부분을 직접 짠 것도 아니다.
하지만
해낼 수 있는 환경을 만들고,
문제를 끝까지 풀고,
마침내 배포까지 성공한건
100% 내 도전의 결과라고 생각한다.
나는 이번 프로젝트로
내가 개발자로서 더 큰 도전을 할 수 있다는 걸 깨달았다.
마무리
이번 우테코 오픈미션은 나에게 분명한 전환점이었다.
프리코스에서 배운 개념들이
실제 서비스에서 어떻게 쓰이는지 깨달았고,
AI와 함께 문제를 해결하는 방식에도 익숙해졌고,
무엇보다도
"불가능해 보였던 프로젝트도 끝까지 하면 완성할 수 있다"는
믿음을 얻게 되었다.
다음에는 더 이론을 공부하고,
더 완성도 높은 분석 로직을 만들고,
유저 맞춤형 슛 코칭 서비스까지 만들어보고 싶다.
이번 경험은 분명
내가 더 큰 개발자로 성장하는 발판이 될 것이다.
프로젝트 기술 스택 선택 과정 및 이유
이번 오픈 미션에서 나는 단순히 작동하는 프로젝트를 만드는 것을 넘어,
왜 특정 기술을 선택했는지 스스로 설명할 수 있어야 한다는 목표를 세웠다.
개발에는 정답이 없고, 항상 내가 처한 상황과 환경에 따라
같은 기능을 구현하더라도 사용할 수 있는 기술 스택이 천차만별이다.
이번 프로젝트를 진행하면서 내가 선택한 기술과 이유를 작성해보았다.
1. FastAPI를 백엔드로 선택한 이유
고려했던 다른 선택지
Django, Flask, Node + Express, Spring Boot 등 다양한 백엔드 기술을 고려할 수 있었다.
FastAPI를 선택한 배경
첫째, 이번 프로젝트는 영상 업로드, 파일 입출력, 분석 결과 반환 등 I/O 작업이 많은 구조이다. FastAPI는 비동기 기반이기 때문에 이러한 작업을 빠르고 안정적으로 처리할 수 있었다.
둘째, Pydantic 기반의 강력한 데이터 검증을 제공한다. 분석 결과는 구조가 복잡하기 때문에 타입을 명확하게 정의하는 것이 중요했다.
프리코스에서 배운 "명확한 타입과 책임 분리"의 개념과도 잘 맞았다.
셋째, Swagger를 통한 API 문서가 자동으로 생성되어 기능을 테스트하고 확장하는 과정이 쉬웠다.
넷째, 백엔드는 이번 미션의 핵심이 아니었기 때문에 빠르게 구성할 수 있는 기술이 필요했다.
FastAPI는 개발 속도가 빠르다는 점에서 목적에 적합했다.
결론적으로, FastAPI는 적은 코드로 비동기 처리와 데이터 검증을 동시에 만족시키는 가장 현실적인 선택이었다.
2. 프론트엔드를 Vanilla JavaScript와 MVC로 구현한 이유
고려했던 다른 선택지
React, Vue, Svelte, Next.js 등 현대적인 프레임워크들을 사용할 수 있었다.
프레임워크를 사용하지 않은 이유는..
이번 프로젝트는 영상 분석 로직 자체가 복잡했고, 해당 부분을 이해하고 구현하는 것만으로도 시간과 에너지가 충분히 필요했다.
프론트엔드까지 프레임워크를 도입하면 전체 구조를 이해하기 어려워질 것이라 판단했다.
또한 프리코스에서 배웠던 JavaScript로의 사고 방식을 실제로 활용해보고 싶었다.
Model, View, Controller를 스스로 분리하며 데이터 흐름을 직접 설계하는 경험이 필요하다고 느꼈다.
전체적으로 프론트엔드에서는 내가 만든 코드가 전부 눈에 보이고, 스스로 통제하고 있다는 감각을 얻는 것을 중요하게 생각했다.
3. YOLOv8 Pose와 OpenCV를 선택한 이유
고려했던 다른 기술
Mediapipe, OpenPose, DeepLabCut, 자체 모델 학습 등이 있었다.
YOLOv8 Pose 선택 이유
YOLOv8은 설치가 간단하고 프레임 처리 속도도 빠르며, 슛폼 분석에 필요한 관절 포인트들을 정확하게 추정하는 데 적합했다.
경량 모델인 YOLOv8n-pose는 분석 속도와 정확도 모두 안정적인 수준이었다.
OpenCV 선택 이유
OpenCV는 영상 프레임 처리, 패널 합성, 최종 mp4 저장 등 필요한 기능을 모두 제공한다.
다양한 이미지 라이브러리가 존재하지만, 프레임 단위로 조작하고 바로 영상으로 저장하는 흐름을 자연스럽게 연결해주는 것은 OpenCV뿐이었다.
4. VideoWriter를 사용해 영상 결과물을 생성한 이유
다른 라이브러리로는 moviepy, imageio, ffmpeg CLI 등이 있었다.
그러나 moviepy는 속도가 느리고 메모리 사용량이 많았고, ffmpeg 직접 호출은 배포 환경마다 설정이 달라 유지보수가 어려웠다.
OpenCV의 VideoWriter는 YOLO로 처리한 프레임을 그대로 받아 자연스럽게 mp4 파일로 저장할 수 있어 가장 현실적인 선택이었다.
5. 서버 배포 과정에서 Render 대신 Railway를 선택한 이유
처음 Render를 선택한 이유
FastAPI용 템플릿이 제공되고, 무료 플랜이 있으며, UI가 친절하고 GitHub 기반 자동 배포가 가능했다. 개발 편의성만 놓고 보면 Render가 적합해 보였다.
Render에서 겪은 문제들
그러나 실제 배포 과정에서는 여러 문제를 겪었다.
1. PyTorch와 Ultralytics 모델 설치 시간이 매우 오래 걸림
2. Pipeline 시간이 초과되어 자동 종료됨
3. Python 버전과 PyTorch 버전 충돌
4. OpenCV 인코더가 지원되지 않아 VideoWriter가 동작하지 않음
5. CPU 성능이 다소 부족한 탓에 영상 분석 속도가 느림
여러 차례 재배포와 패키지 버전 조정을 시도했지만 끝내 안정적으로 동작하지 않았다.
Railway로 이동한 이유
Railway는 CPU 성능이 Render보다 훨씬 충분했고, PyTorch와 YOLOv8 설치도 별다른 충돌 없이 진행되었다. OpenCV 인코더도 정상적으로 동작했으며, 빌드 속도도 빠르고 무료 크레딧으로 필요한 만큼 테스트할 수 있었다.
결과적으로 실제로 영상 분석이 가능한 서버 환경은 Railway였다.
6. PyTorch safe_globals 설정이 필요했던 이유
PyTorch 2.1 이후부터는 torch.load의 동작이 강화되어 외부 모델을 로드할 때 해당 모델이 사용하는 클래스들을 명시적으로 허용해야 한다. YOLO 모델은 다양한 내부 모듈(C2f, Bottleneck, SPPF 등)을 사용하기 때문에 safe_globals에 모든 관련 클래스를 추가해줘야 했다.
대안으로는 PyTorch 버전을 낮추거나, 모델을 다른 포맷(ONNX, TensorRT 등)으로 변환하는 방식이 있었지만, 설정이 복잡하거나 배포 환경에서 더 많은 문제가 발생할 가능성이 컸다.
따라서 YOLO 내부 모듈을 자동으로 탐색해 safe_globals에 등록하는 방식을 선택했고, 이 방식은 실제 배포 환경에서 안정적으로 모델을 로드할 수 있었다.
마무리
이번 기술 선택 과정의 핵심 기준은 다음과 같았다.
1. 지금의 나에게 맞는 기술인지
2. 2주 안에 배포까지 가능한지
3. 유지보수가 가능한지
4. 분석 로직이라는 핵심을 방해하지 않는지
나는 완벽한 기술을 선택한 것이 아니라, 지금의 나에게 가장 맞는 기술을 선택했다.
그 과정에서 기술적 난관도 많았고, 여러 번 방향을 바꾸기도 했지만, 결국 영상이 분석되고 결과가 나오는 실제 서비스를 배포하는 데 성공했다. 이 경험은 앞으로 더 나은 프로젝트를 만들기 위한 중요한 발판이 될 것이다.
추가 (25.11.26)
성능 최적화를 마치고 그에 대한 내용을 정리한 글 입니다.
https://blog091.tistory.com/28
🏀 Basketball Coach 성능 최적화 기록
서버 비용 67% 절감, 처리 속도 73% 향상까지 Basketball Coach 서비스를 운영하면서, Railway 비용과 성능 문제를 정면으로 마주하게 되었다. 그 과정에서 어떤 문제가 있었고, 무엇을 어떻게 바꿨는지,
blog091.tistory.com
'우테코' 카테고리의 다른 글
| 우아한 테크코스 8기(FE) 1차 합격 후기 (2) | 2025.12.29 |
|---|---|
| [우테코] 프리코스 3주차 회고 (0) | 2025.11.05 |
| [우테코] 프리코스 2주차 회고 (0) | 2025.10.28 |
| [우테코] 프리코스 1주차 회고 🛸 (2) | 2025.10.23 |
