🏀 Basketball Coach 성능 최적화 기록

2025. 11. 26. 15:20·etc

서버 비용 67% 절감, 처리 속도 73% 향상까지

 

Basketball Coach 서비스를 운영하면서, Railway 비용과 성능 문제를 정면으로 마주하게 되었다.
그 과정에서 어떤 문제가 있었고, 무엇을 어떻게 바꿨는지, 그리고 실제로 얼마나 효과가 있었는지 정리해보았다.

 

목표는 두 가지였다.

 

  1. 서버 비용을 줄이면서
  2. 영상 분석 속도와 안정성을 동시에 끌어올리는 것

 

최종적으로는 메모리 사용량 약 67% 감소, 처리 속도 약 73% 향상

 

 

1. 처음 마주한 문제 상황

 

 

 초기 상태 요약

 

Basketball Coach는 사용자가 올린 농구 슛 영상을 분석해 리포트를 만들어주는 서비스다.

초기 버전은 기능적으로는 동작했지만, 운영 측면에서 문제가 많았다.

 

  • Railway 월 예상 비용: 약 38달러 (15달러 한도는 금방 소진)
  • 3초짜리 영상 하나 처리 시간: 약 1분 40초
  • 평균 메모리 사용량: 약 2.6GB
  • CPU 사용률: 평균 85~95%

 

혼자 개발자가 취미로 운영하는 서비스에는 부담스러운 수준이었다. 사용자가 조금만 늘어나도 서버가 바로 벽에 부딪힐 구조였다.

 

 

원인 분석

 

대략적인 원인은 세 가지였다.

 

  1. YOLOv8x(Extra Large) 모델 사용
    • 131MB짜리 대형 모델을 그대로 올려서 사용하고 있었고, 메모리와 CPU 사용량이 높을 수밖에 없는 구조였다.
  2. Pose + Detection 이중 추론 구조
    • 한 프레임을 처리할 때, 포즈 추론 한 번, 공 탐지 한 번, 이렇게 YOLO 추론을 두 번 돌리고 있었다.
  3. 공 탐지 기반의 릴리즈 타이밍 분석
    • 공이 손에서 떨어지는 순간을 기준으로 릴리즈 타이밍을 잡는 방식이라, 공이 가려지거나 조명, 배경에 따라 정확도가 크게 흔들렸다.

성능, 비용, 정확도 세 가지를 모두 갉아먹는 설계였다.

 

 

2. 무엇을 어떻게 바꿨는지

YOLOv8n-pose(포즈용 경량 모델)와 YOLOv8x(대형 Detection 모델)를 함께 쓰고 있었다.

여기서 YOLOv8x를 완전히 제거했다.

# Before
POSE_MODEL = "yolov8n-pose.pt"  # 6.5MB
DET_MODEL = "yolov8x.pt"        # 131MB
# After
POSE_MODEL = "yolov8n-pose.pt"  # 6.5MB만 유지
# Detection 모델은 제거

 

공 탐지에 쓰이던 YOLOv8x를 빼면서, 메모리와 CPU 부담이 크게 줄었다.

공 탐지 자체를 없애기

기존에는 프레임당 YOLO를 두 번 돌리고 있었다.

# Before
pose_out = pose_model(frame)  # 약 25ms
det = det_model(frame)        # 약 80ms
total = 105ms/frame

 

Detection 모델을 제거한 뒤에는 포즈 추론만 수행한다.

# After
pose_out = pose_model(frame)  # 약 25ms
total = 25ms/frame

 

프레임당 추론 시간이 약 4분의 1 수준으로 줄었다.

 

릴리즈 검출 기준을 공에서 관절로

이전에는 공의 위치 변화를 기준으로 릴리즈 타이밍을 잡았다.

 

즉, 공이 손에서 떨어지는 순간, 혹은 공의 움직임이 바뀌는 순간을 찾는 방식이었다.

 

그래서 기준을 아예 바꿨다.

공이 아니라, 어깨 각도의 각속도가 가장 크게 폭발하는 순간을 릴리즈에 가깝다고 보는 방식이다.

 

공을 기준점으로 잡지 않아도 릴리즈 시점을 파악할 수 있다.

그렇다보니 굳이 무거운 8x 모델을 사용할 필요가 없어졌고 프로그램이 더 가벼워졌다. 

 

효율성 지표도 관절 기반으로 재설계

공 탐지를 제거하면서, 효율성 평가 기준도 바꾸었다.

공 대신, 관절 간 벡터 정렬을 보는 방식으로 재설계했다.

 

def joint_vector_alignment(kps, idx, j1, j2, j3, j4):
    # 첫 번째 관절 세그먼트: j1 → j2 (예: 발목 → 무릎)
    # 두 번째 관절 세그먼트: j3 → j4 (예: 무릎 → 허리)
    v1 = [kps[idx][j2] - kps[idx][j1]]
    v2 = [kps[idx][j4] - kps[idx][j3]]
    return cosine_similarity(v1, v2)

align_knee_hip = joint_vector_alignment(kps, release_idx, ANK, KNE, KNE, HIP)
align_hip_shoulder = joint_vector_alignment(kps, release_idx, KNE, HIP, HIP, SHO)
align_shoulder_elbow = joint_vector_alignment(kps, release_idx, HIP, SHO, SHO, ELB)
power_transfer = mean([align_knee_hip, align_hip_shoulder, align_shoulder_elbow])

 

즉, 하체에서 상체, 상체에서 팔로 에너지가 얼마나 곧게 전달되고 있는지를 “관절 벡터 정렬도”로 보는 구조로 바꾸었다.

이렇게 바꾸고 나니, 공이 보이지 않아도 폼 자체의 효율성을 충분히 평가할 수 있게 되었다.

 

 

3. YOLOv8x 대신 YOLOv8n을 선택한 이유

두 모델의 차이

모델 YOLOv8x YOLOv8n 효과
파일 크기 131MB 6.5MB -95%
파라미터 수 68.2M 3.2M -95%
런타임 메모리 사용량 약 1.8GB 약 0.5GB -72%
CPU 추론 시간(프레임당) 80~100ms 20~25ms -75%

 

YOLOv8x는 매우 강력한 모델이지만, 이 프로젝트의 목적에는 과한 수준이었다.

실제로 포즈 검출 정확도는 YOLOv8n만으로도 충분했다.

 

 이번 최적화에서 얻은 것들

  1. 모델 크기가 성능을 보장해주지는 않는다
    • YOLOv8x 같은 대형 모델은 분명 강력하지만,YOLOv8n 정도로도 충분했다.
    • 이 프로젝트처럼 “한 명의 사용자가 업로드한 슛 영상”을 분석하는 정도의 규모에서는 YOLOv8n 정도로도 충분했다.
  2. 불필요한 기능을 과감히 버리는 것이 오히려 정확도를 올릴 수 있다
    • 처음에는 “공 궤적까지 다 보면 더 좋은 서비스”라고 생각했다.
    • 어깨-팔꿈치의 관절 타이밍만 따져도 릴리즈 타이밍을 알 수 있는데,
      더 정확한 분석을 위해 공이 몸에서 떨어지는 순간도 잡으려고 했던게 화근이었다.
    • 오히려 이 기능이 전체 분석의 신뢰도를 떨어뜨리고 있었고 메모리와 CPU사용량만 늘리고 있었다.
  3. 도메인 지식이 들어간 지표 설계가 중요하다
    • 스포츠 생체역학에서는 운동 연쇄(kinetic chain)라는 개념이 중요하다.
    • 이론을 바탕으로 “관절 벡터 정렬도” 같은 지표를 설계하니,실제 코칭 관점에서도 설명 가능한 결과가 나왔다.

 

 

'etc' 카테고리의 다른 글

[2025년 회고록] 나의 20대 초반을 보내주면서...  (0) 2025.12.31
Jest 에 대한 이해  (0) 2025.10.24
인삿말  (7) 2024.11.04
'etc' 카테고리의 다른 글
  • [2025년 회고록] 나의 20대 초반을 보내주면서...
  • Jest 에 대한 이해
  • 인삿말
yun_cic
yun_cic
  • yun_cic
    체대생의 개발 기록
    yun_cic
  • 전체
    오늘
    어제
    • 분류 전체보기 (22)
      • 백엔드 (1)
      • 프로젝트 (5)
      • etc (4)
      • 대외활동 (1)
      • 강의자료 (5)
      • 프론트엔드 (1)
      • 우테코 (5)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • GitHub
    • 포트폴리오 페이지
  • 공지사항

  • 인기 글

  • 태그

    크몽
    Python
    fastapi
    KUCC
    개발자 #코딩 #체대생
    bs4
    Selenium
    메모
    Crawling
    외주
    해커톤
    todo
    채널톡
    크롤링
    백엔드
    MySQL
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
yun_cic
🏀 Basketball Coach 성능 최적화 기록
상단으로

티스토리툴바