ID: key_26_22_05_25_P2_2_1 Created date: 5월 25 2026 월요일

연관 문서


개요

칸반 보드 데이터 조회 및 이슈 위치 업데이트 API를 구현한다.
카드 순서는 Lexorank 알고리즘으로 관리하여 재정렬 최소화를 달성한다.

  • 예상 소요: 3~5일
  • 선행 조건: Phase 1 전체 완료
  • 완료 기준: 이슈 D&D 후 서버에 위치 저장, 재기동 후 순서 유지 확인

API 목록

MethodPath설명
GET/api/v1/projects/{projectId}/board보드 전체 조회 (컬럼 + 카드)
PUT/api/v1/issues/{issueId}/position이슈 위치 업데이트
GET/api/v1/projects/{projectId}/board/columns컬럼 목록
POST/api/v1/projects/{projectId}/board/columns컬럼 추가
PUT/api/v1/board/columns/{columnId}컬럼 수정 (WIP 제한 등)

Claude Code 작업 수행서

작업 지시

CIRA 서버에 칸반 보드 API를 구현해줘.

[프로젝트 경로]
- C:\workspace\tsh\boilerplate\be\befw-app-server

[수행 작업]

1. Lexorank 유틸리티 구현
   파일: src/main/java/.../common/util/LexorankUtil.java
   - between(String rank1, String rank2): String
     → 두 rank 사이의 중간값 계산
   - initial(): String
     → 첫 번째 카드의 초기값 (예: "0|hzzzzz:")
   - before(String rank): String
     → 주어진 rank보다 앞의 값
   - after(String rank): String
     → 주어진 rank보다 뒤의 값
   - rebalance(List<String> ranks): List<String>
     → rank 공간 부족 시 전체 재계산
   참고: https://github.com/Brendonovich/lexorank 구현 참조

2. 보드 조회 API
   GET /api/v1/projects/{projectId}/board
   Response:
   {
     "columns": [
       {
         "id": "uuid",
         "name": "To Do",
         "statusId": "uuid",
         "wipLimit": 5,
         "issues": [
           { "id", "key", "title", "priority", "assignee", "storyPoints", "issueType", "rankString" }
         ]
       }
     ]
   }
   구현:
   - board_columns LEFT JOIN issue_positions LEFT JOIN issues
   - issues는 rank_string ASC 정렬
   - deleted_at IS NULL 조건 필수
   - 성능: 단일 쿼리로 전체 조회 (N+1 방지)

3. 이슈 위치 업데이트 API
   PUT /api/v1/issues/{issueId}/position
   Request:
   {
     "columnId": "uuid",
     "rankString": "0|hzzzzz:"   ← 클라이언트가 계산한 새 rank
   }
   또는 (서버 계산 방식):
   {
     "columnId": "uuid",
     "previousIssueId": "uuid",  ← null이면 컬럼 맨 앞
     "nextIssueId": "uuid"       ← null이면 컬럼 맨 뒤
   }
   
   구현 (서버 계산 방식 권장):
   - previousIssueId의 rank_string 조회
   - nextIssueId의 rank_string 조회
   - LexorankUtil.between()으로 새 rank 계산
   - issue_positions 업데이트 (column_id, rank_string)
   - 상태 전이: columnId와 연결된 status로 issue.status_id 자동 변경

4. WIP 제한 검증
   - 이슈 이동 시 대상 컬럼의 wip_limit 확인
   - 초과 시: CiraException(BOARD_WIP_LIMIT_EXCEEDED)
   - wip_limit = 0 이면 무제한

5. 보드 초기화 (프로젝트 생성 시)
   ProjectService.createProject() 에 추가:
   - 기본 컬럼 4개 자동 생성 (To Do, In Progress, In Review, Done)
   - 각 컬럼에 해당 status 연결

6. 단위/통합 테스트
   - 이슈 A, B, C 순서로 삽입 후 A를 B와 C 사이로 이동 → rank 검증
   - WIP 제한 초과 시 에러 검증

완료 기준

항목기준
보드 조회컬럼 + 카드 전체 단일 응답
이슈 이동rank 업데이트 + 상태 자동 변경
WIP 제한초과 시 400 반환
Lexorank10,000회 연속 이동 후 rank 고갈 없음

후행 작업