← 전체로 돌아가기
공통 메모 api

Jira hierarchy conversion order

계층 올릴 땐 무조건 밑(leaf)에서부터 위로. 안 그러면 서브태스크 부모 잃고 다 터짐.

jirarest-apimigration

Jira 이슈 타입 계층 변환 (Subtask → Task → Epic)

문제 상황: 작업(Task)을 에픽(Epic)으로 먼저 승격했더니, 그 밑에 있던 하위작업(Subtask)들이 부모를 잃어버림(parentless). 이 상태로 bulk move 돌리면 "Some of the subtask issues do not have parent." 뜨면서 전부 거부됨.

Jira 변환 메커니즘 차이:

작업 ↔ 에픽 (Task ↔ Epic): PUT /rest/api/3/issue/{key} - issuetype만 바꾸면 됨. - editmeta에서 에픽이 안 보여도 실제로는 됨. editmeta 믿지 말 것.

하위작업 ↔ 표준 (Subtask ↔ Task): POST /rest/api/3/bulk/issues/move - PUT으로는 안 됨. 무조건 bulk move API 써야 함. - 비동기 방식이라 taskId 받아서 GET /rest/api/3/task/{id}로 폴링해야 함.

정석 순서 (Bottom-up): 1. 하위작업 → 작업 (bulk move) : 부모가 아직 Task라 통과됨. (이동 후 부모는 해제됨) 2. 작업 → 에픽 (PUT) : 이제 부모(Task)를 에픽으로 승격. 3. ex-하위작업(이제 Task임)을 진짜 부모(Epic) 밑으로 재연결 (PUT parent)

이미 parentless 서브태스크 생겨서 지저분해졌을 때 복구법: 임시 작업(Dummy Task) 생성 → 서브태스크들 parent를 임시 작업으로 지정 (PUT) → bulk move로 작업 변환 → 진짜 에픽 밑으로 재연결 → 임시 작업 삭제

always test with 1 issue first

여기서 배울 것

  1. 계층 올릴 땐 무조건 리프(leaf)부터 위로.
  2. Subtask는 반드시 유효한 부모가 있어야 bulk move 가능.
  3. Subtask ↔ Task 변환은 PUT 말고 bulk move API 써야 함.
원본 파일 보기 (.claude/memory/jira_hierarchy_conversion_order.md)
---
name: Jira 계층 타입 변환 순서와 메커니즘
description: Jira 이슈 타입을 계층 넘어 변환할 때 (하위작업→작업, 작업→에픽) API 방법과 실행 순서
date: 2026-07-03
tags: [jira, rest-api, hierarchy, bulk-move, migration]
---

## What happened
DEE 프로젝트에서 작업 48개→에픽, 하위작업 124개→작업으로 일괄 재구성. 처음에 작업→에픽을 먼저 실행했더니, 그 밑 하위작업들의 부모가 에픽이 되면서 하위작업이 부모를 잃고(parentless), 이어진 하위작업→작업 bulk move가 `"Some of the subtask issues do not have parent."` 로 전부 거부됨. 임시 작업을 하나 만들어 임시 부모로 붙인 뒤 bulk move→진짜 부모(에픽)로 재연결→임시 삭제로 복구.

## Root cause
- Jira에서 서브태스크는 **항상 유효한 표준 이슈(작업) 부모**가 있어야 한다. 부모 작업을 먼저 에픽으로 승격하면 서브태스크의 부모가 에픽(무효)이 되어 detach → parentless subtask.
- bulk move는 소스 서브태스크에 부모가 있어야 통과하는 사전검증이 있어, parentless 서브태스크는 이동 불가.
- 변환 메커니즘도 비대칭:
  - **작업↔에픽**: `PUT /rest/api/3/issue/{key}` 로 `issuetype` 변경 가능(204, 동기). 부모 있으면 자동 해제됨. (editmeta의 allowedValues에는 에픽이 안 보여도 실제로는 됨 — editmeta 신뢰 금물)
  - **하위작업↔표준(작업)**: PUT은 `"선택한 이슈 유형이 올바르지 않습니다"` 로 불가. 반드시 `POST /rest/api/3/bulk/issues/move` (비동기, taskId 반환 → `GET /rest/api/3/task/{id}` 폴링) 사용. 이동 시 부모는 해제됨.

## Next time
계층을 한 단계 올리는 재구성(하위작업→작업, 작업→에픽)은 **반드시 아래(리프)부터**:
1. 변환 전 원본 부모 매핑을 스냅샷으로 저장(롤백맵).
2. 하위작업→작업 먼저(bulk move) — 이때 부모가 아직 유효한 작업이라 통과. 부모는 해제됨.
3. 그다음 작업→에픽(PUT).
4. ex-하위작업(작업)을 원래 부모(이제 에픽) 밑으로 재연결(PUT parent).

이미 parentless 서브태스크가 생겨버렸다면: 임시 작업 1개 생성 → 서브태스크들 parent=임시작업(PUT) → bulk move로 작업 변환 → 진짜 에픽으로 재연결 → 임시 작업 삭제. 대량 변경 전 항상 1건으로 메커니즘 테스트 후 롤백맵 저장하고 진행.