Files
basket_utils/농구 전술보드 웹앱 MVP 작업지시서.md

16 KiB

농구 전술보드 웹앱 MVP 작업지시서

코드 작업 담당 모델

실제 코드 구현·수정·리팩터링·테스트 코드 작성은 **GPT-5.6 Luna (gpt-5.6-luna)**에게 지시한다. 주 에이전트는 조사·설계·작업 지시·검토·검증을 담당하며, 문서는 직접 수정할 수 있다. 구체적인 작업 규칙은 AGENTS.md를 따른다.

1. 프로젝트 목표

Three.js 기반의 웹 농구 전술보드 MVP를 구현한다.

편집 화면은 전체 코트를 보기 편한 쿼터뷰 2.5D 스타일로 제공하되, 내부 월드 좌표는 실제 3D 좌표계를 사용한다.

사용자가 선수별 이동 경로와 시선을 간단하게 지정하면 이를 Sequence 단위로 저장하고, 재생 시 전체 전술 또는 특정 선수의 POV(Player View)로 확인할 수 있어야 한다.

핵심 방향은 다음과 같다.

  • 사용자가 입력해야 하는 정보는 최소화
  • 선수 이동 위치만 지정해도 기본 전술 재생 가능
  • Facing, LookAt, Duration 등은 가능한 한 자동 계산
  • 동일한 전술 데이터를 쿼터뷰와 선수 POV에서 함께 사용
  • 추후 패스, 스크린, Read/Decision 등으로 확장 가능한 구조

2. 기술 스택

기본 기술 스택은 다음을 사용한다.

  • Vanilla JavaScript
  • Three.js
  • HTML
  • CSS
  • Vite
  • ES Module

초기 MVP에서는 별도의 React/Vue 등의 프레임워크를 사용하지 않는다.

Three.js의 Scene/Object3D 구조와 앱 상태 관리를 명확하게 분리한다.


3. 핵심 데이터 모델

전체 구조는 다음 개념으로 구성한다.

Play
 ├─ Players
 ├─ DefenseType
 └─ Sequences[]
      └─ PlayerTracks
           └─ Actions[]

Play

하나의 완성된 전술.

예시:

{
  id: "play-001",
  name: "Horns Entry",
  defenseType: "man-to-man",
  sequences: []
}

Sequence

Sequence는 하나의 프레임이 아니다.

여러 선수가 동시에 행동하는 하나의 전술 구간으로 정의한다.

예:

Sequence 1

1번
- 4번에게 접근
- 우측 엘보 방향으로 이동

4번
- 볼 캐치
- 핸드오프 준비

2번
- 코너 유지

5번
- 엘보 유지

각 Sequence의 모든 선수 행동이 종료되면 다음 Sequence로 넘어간다.


PlayerTrack

하나의 Sequence 내부에서 특정 선수가 수행하는 행동 묶음.

{
  playerId: "offense-1",
  actions: []
}

Action

기존의 move보다 포괄적인 단위로 사용한다.

기본 구조는 다음과 같이 설계한다.

{
  id: "action-001",

  location: {
    x: 0,
    z: 0
  },

  facing: null,

  lookAt: null,

  type: "move",

  targetPlayerId: null
}

초기 MVP에서는 다음 필드 위주로 구현한다.

  • location
  • facing
  • lookAt
  • type

향후 다음 Action Type을 확장할 수 있도록 설계한다.

move
pass
screen
dribble
shoot
hold

4. 코트 좌표계

화면 pixel 좌표를 데이터에 직접 저장하지 않는다.

실제 농구 코트 기준 좌표계를 사용한다.

예:

X축 = 코트 좌우
Z축 = 코트 길이 방향
Y축 = 높이

Three.js에서는:

player.position.set(x, y, z);

형태로 그대로 사용할 수 있도록 한다.

MVP에서는 하프코트를 우선 구현해도 된다.

코트 위치를 선택할 때 내부적으로 Grid Snap을 적용할 수 있도록 한다.

Grid는 화면에 항상 표시할 필요는 없다.


5. Three.js Scene

Scene은 하나만 사용한다.

Three.js Scene
      │
      ├─ Tactical Camera
      │
      └─ Player POV Camera

Tactical Camera

전술 편집 및 전체 플레이 재생용 카메라.

쿼터뷰 형태로 제공한다.

카메라는 고정된 각도를 기본으로 한다.

예:

높은 위치
+
골대 방향을 내려다보는 Perspective View

MVP에서는 자유로운 3D 카메라 회전 기능은 필요하지 않다.


Player POV Camera

특정 선수의 시점에서 전술을 재생하기 위한 카메라.

선택한 선수 위치를 기준으로 한다.

개념:

camera.position =
  player.position + eyeHeight

시선은 해당 Action의 lookAt 데이터를 기준으로 계산한다.


6. 선수 표현

초기 MVP에서 현실적인 3D 인간 모델은 사용하지 않는다.

다음과 같이 단순화한다.

Court
→ 3D Plane

Players
→ Billboard Sprite 또는 단순 Capsule/Cylinder

Ball
→ Sphere

Basket
→ 간단한 Low-poly Object

Move Path
→ Three.js Line

LookAt
→ Arrow 또는 Cone

공격과 수비는 명확하게 구분될 수 있어야 한다.

선수에는 번호를 표시한다.

예:

O1
O2
O3
O4
O5

D1
D2
D3
D4
D5

7. 전술 생성 UX

새 전술을 생성할 때 다음 정보를 받는다.

전술 이름

수비 형태
- Man to Man
- 2-3 Zone
- 3-2 Zone

전술 생성 시 자동으로:

Sequence 1

을 생성한다.

공격 5명과 수비 5명도 기본 배치한다.

수비 전술 선택에 따라 초기 수비 위치를 자동 배치한다.


8. 기본 LookAt 자동 설정

사용자가 모든 Action마다 시선을 직접 입력하지 않도록 한다.

기본 규칙을 구현한다.

공격

볼 핸들러:

lookAt → Rim

오프볼 공격자:

lookAt → Ball

수비

Man to Man:

기본적으로 매치업 상대 또는 Ball 방향

Zone Defense:

Ball / 자신의 담당 Zone 방향

MVP에서는 수비 LookAt 로직을 단순화해도 된다.

사용자가 LookAt을 직접 설정한 경우 자동값보다 사용자 설정값이 우선한다.


9. Facing 자동 계산

사용자가 Facing을 직접 입력하지 않아도 되도록 한다.

Action N에서 Action N+1로 이동하는 경우:

현재 위치
→
다음 위치

벡터를 계산해서 기본 Facing을 자동 지정한다.

예:

direction = nextPosition - currentPosition
rotationY = atan2(...)

이동하지 않는 선수의 기본 Facing은 LookAt 방향을 사용할 수 있다.

사용자 override 기능은 추후 쉽게 추가 가능하도록 데이터 구조만 준비한다.


10. Action 입력 UX

사용자가 선수 하나를 선택한다.

이후 코트 위치를 계속 클릭하면 해당 선수의 Action이 연속 생성된다.

예:

1번 선택

코트 클릭
→ Action 1

코트 클릭
→ Action 2

코트 클릭
→ Action 3

즉 사용자가 별도의:

Action 추가
Move 추가
Duration 입력

같은 작업을 반복할 필요가 없어야 한다.

가능한 한:

선수 선택
→ 위치 클릭
→ 위치 클릭
→ 위치 클릭

만으로 경로를 만든다.


11. LookAt 입력 UX

LookAt은 기본 자동값을 사용한다.

사용자가 특정 Action의 LookAt을 수정하고 싶은 경우에만 설정한다.

예:

선수 선택
→ 특정 Action 선택
→ LookAt 모드
→ 다른 선수 또는 코트 위치 클릭

LookAt target은 다음을 지원할 수 있도록 설계한다.

rim
ball
player
location

예:

lookAt: {
  type: "player",
  targetId: "offense-4"
}

또는:

lookAt: {
  type: "location",
  x: 4.2,
  z: 6.1
}

12. Sequence 편집

화면 하단 또는 측면에 Sequence UI를 둔다.

예:

[Sequence 1] [Sequence 2] [Sequence 3] [+]

현재 Sequence를 선택하면 해당 Sequence의 선수 위치와 Action 경로를 편집한다.

새 Sequence 생성 시:

직전 Sequence의 마지막 위치를 새로운 Sequence의 시작 위치로 자동 상속한다.

즉 사용자가 선수 위치를 다시 배치할 필요가 없어야 한다.


13. Sequence Duration 자동 계산

사용자가 Duration을 직접 입력하지 않게 한다.

각 PlayerTrack의 예상 수행시간을 자동 계산한다.

기본적으로:

이동거리 / 기본 선수 이동속도

를 기반으로 한다.

예:

Player 1 = 2.8초
Player 2 = 0.9초
Player 3 = 0초
Player 4 = 1.4초
Player 5 = 0초

Sequence Duration은:

max(PlayerTrack duration)

으로 자동 결정한다.

위 예에서는:

Sequence Duration = 2.8초

이다.

Player 2는 0.9초에 Action이 끝난 후:

0.9초 ~ 2.8초
마지막 위치 유지

한다.

모든 선수는 동시에 다음 Sequence로 넘어간다.


14. Action Playback

Action 사이의 위치는 부드럽게 보간한다.

Three.js의 Vector3.lerp 또는 유사 interpolation을 사용한다.

예:

Action 1
   ↓
interpolation
   ↓
Action 2

Facing 역시 갑자기 회전하지 않고 자연스럽게 보간한다.

LookAt 역시 Action 사이에서 가능한 경우 자연스럽게 변화시킨다.


15. 전체 전술 재생

Play 버튼을 누르면:

Sequence 1
↓
Sequence 2
↓
Sequence 3
↓
...

순서대로 자동 재생한다.

UI:

▶ Play
⏸ Pause
⏹ Reset

정도만 우선 구현한다.

Playback은 기본 Tactical Camera에서 실행한다.


16. Player POV 재생

공격 선수를 선택한 후:

Player View

버튼을 누르면 해당 선수 POV로 전환한다.

예:

[ Tactical View ]

[ Player 1 POV ]
[ Player 2 POV ]
...

Player POV 재생 중 카메라는 선수 이동을 따라간다.

Camera Position:

player location
+
eye height

Camera Direction:

lookAt

을 기준으로 한다.

lookAt이 없는 경우:

facing

을 사용한다.


17. 시야 시각화

편집 화면에서 선택된 선수의 시야를 시각적으로 표현한다.

예:

       ╱────────
      /
    Player ───────→ LookAt
      \
       ╲────────

구현 방식은:

  • Arrow
  • Line
  • Sector
  • Cone

중 간단한 방식으로 먼저 구현한다.

MVP에서는 LookAt 방향 Arrow만 구현하고, 이후 Vision Cone으로 확장해도 된다.


18. 상태 관리

Three.js Object 자체를 전술 데이터의 Source of Truth로 사용하지 않는다.

반드시:

Application State
        ↓
Three.js Renderer

형태로 분리한다.

즉:

play.sequences[0].playerTracks...

가 실제 데이터이고,

Three.js Scene은 이를 렌더링하는 역할만 한다.

사용자가 선수를 이동하면:

UI Interaction
→ State 변경
→ Scene 업데이트

순서를 따른다.

이 구조는 추후:

  • 저장
  • 불러오기
  • Undo/Redo
  • 서버 연동
  • 공유
  • Replay

구현을 쉽게 하기 위함이다.


19. 파일 구조

과도하게 복잡하게 만들지 말고 기능 기준으로 분리한다.

예:

src/
├─ main.js
│
├─ three/
│   ├─ scene.js
│   ├─ court.js
│   ├─ player.js
│   ├─ cameras.js
│   └─ renderer.js
│
├─ domain/
│   ├─ play.js
│   ├─ sequence.js
│   ├─ action.js
│   └─ player.js
│
├─ playback/
│   ├─ playbackController.js
│   ├─ interpolation.js
│   └─ durationCalculator.js
│
├─ editor/
│   ├─ playerSelection.js
│   ├─ actionEditor.js
│   ├─ lookAtEditor.js
│   └─ sequenceEditor.js
│
├─ state/
│   └─ playStore.js
│
└─ ui/
    ├─ toolbar.js
    ├─ sequenceBar.js
    └─ controls.js

불필요한 클래스화나 추상화는 피한다.


20. MVP 화면 구성

하나의 메인 화면으로 시작한다.

┌───────────────────────────────────────┐
│ Play Name        Defense: Man to Man  │
├───────────────────────────────────────┤
│                                       │
│                                       │
│          THREE.JS COURT               │
│                                       │
│                                       │
├───────────────────────────────────────┤
│ Sequence 1 | Sequence 2 | +           │
├───────────────────────────────────────┤
│ Move | LookAt | Play | Player View    │
└───────────────────────────────────────┘

편집 화면이 최대한 넓게 보이도록 한다.


21. 구현 우선순위

다음 순서대로 구현한다.

Phase 1

Three.js 기본 Scene 구축.

  • Court
  • Basket
  • 공격 5명
  • 수비 5명
  • Tactical Camera
  • Player Selection

Phase 2

전술 데이터 모델 구현.

  • Play
  • Sequence
  • PlayerTrack
  • Action
  • State ↔ Renderer 연결

Phase 3

Action 편집.

  • 선수 선택
  • 코트 클릭
  • Action.location 추가
  • 이동 경로 표시
  • Action 삭제

Phase 4

Sequence.

  • Sequence 추가
  • Sequence 선택
  • 직전 Sequence 위치 상속
  • Sequence 삭제

Phase 5

Playback.

  • Action interpolation
  • PlayerTrack duration 자동 계산
  • Sequence duration 자동 계산
  • Sequence 순차 재생
  • Play/Pause/Reset

Phase 6

Facing / LookAt.

  • 자동 Facing 계산
  • 기본 LookAt
  • 사용자 LookAt override
  • LookAt Arrow 표시

Phase 7

Player POV.

  • Player Camera
  • 선수 위치 추적
  • LookAt 기반 Camera rotation
  • Tactical / Player View 전환

22. MVP에서 제외

현재 단계에서는 다음 기능을 구현하지 않는다.

  • 로그인
  • 서버 DB
  • 팀 관리
  • 전술 공유
  • 영상/GIF Export
  • 실제 사람 3D 모델
  • 수비 AI
  • 자동 수비 움직임
  • Read / Decision 분기
  • 패스 물리
  • 드리블 애니메이션
  • 슛 애니메이션
  • 복잡한 Timeline Editor
  • 개별 Action Duration 직접 입력
  • Multiplayer
  • WebSocket

MVP 완성 후 단계적으로 추가한다.


23. 핵심 UX 원칙

가장 중요한 요구사항이다.

사용자가 전술 하나를 만들기 위해 입력해야 하는 값을 최소화한다.

기본적으로 사용자는:

전술 생성
→ 수비 형태 선택
→ 선수 선택
→ 이동 위치 연속 클릭
→ 필요한 경우에만 LookAt 수정
→ 다음 Sequence
→ Play

정도만 수행하면 전술이 만들어져야 한다.

다음 항목은 사용자에게 기본적으로 입력시키지 않는다.

  • Facing angle
  • Duration
  • Velocity
  • Action weight
  • Sequence duration
  • Camera rotation
  • 정확한 좌표값

이 값들은 앱이 자동 계산한다.


24. 구현 원칙

  1. 먼저 동작 가능한 MVP를 만든다.
  2. UI 디자인보다 편집 UX와 Playback 로직을 우선한다.
  3. 데이터 모델과 Three.js 렌더링 로직을 분리한다.
  4. 모든 전술 위치는 실제 Court 좌표로 저장한다.
  5. Player POV 확장을 고려해 처음부터 실제 3D Scene을 사용한다.
  6. Action/Sequence 데이터는 JSON Serialize 가능한 형태로 유지한다.
  7. 하드코딩된 전술에 종속된 구조를 만들지 않는다.
  8. 사용자의 Action 개수가 선수마다 달라도 정상 재생되어야 한다.
  9. Action이 먼저 끝난 선수는 Sequence 종료 시점까지 마지막 State를 유지한다.
  10. 모든 PlayerTrack이 완료된 후 다음 Sequence로 넘어간다.

25. 최초 완료 기준

다음 시나리오가 정상 동작하면 1차 MVP 완료로 판단한다.

  1. 웹페이지 실행
  2. 하프코트 표시
  3. 공격 5명 / 수비 5명 표시
  4. Man to Man / 2-3 / 3-2 중 하나 선택
  5. Sequence 1 자동 생성
  6. 공격 1번 선택
  7. 코트상의 세 위치를 클릭
  8. Action 3개 자동 생성
  9. 공격 2번 선택
  10. 위치 하나 클릭
  11. Sequence 2 추가
  12. Sequence 1의 마지막 위치가 Sequence 2 시작 위치로 유지
  13. Sequence 2에서 추가 Action 작성
  14. Play 실행
  15. Sequence 1 → Sequence 2 자동 재생
  16. 선수별 Action 개수가 달라도 Sequence 종료 타이밍 정상 처리
  17. Tactical View에서 정상 재생
  18. Player 1 POV로 전환
  19. Player 1 이동을 카메라가 따라감
  20. 기본 LookAt 방향에 맞춰 카메라가 회전

이 상태까지 우선 구현한다.

구현 중 기존 요구사항과 충돌하지 않는 범위에서는 합리적인 기술적 판단으로 진행하되, 기능을 임의로 추가해 MVP 범위를 확대하지 않는다.