3회차실습 1315–55분

작업 분해 구조와 주경로

M1 마감일(11월 6일)까지 여유가 있는가. 업무 여섯 개의 목표일만 보면 모두 11월 6일 이전이다. 그러나 QA(LP-05)는 랜딩 페이지, 신청, 알림 업무가 모두 끝나야 시작할 수 있고, 알림은 신청이 끝나야 시작할 수 있다. 목표일 목록으로는 이런 순서의 제약이 보이지 않는다. 이 실습은 출시 목표를 작업 분해 구조(Work Breakdown Structure, WBS)로 묶고, 선행 관계를 따라 가장 긴 경로인 주경로(critical path)를 계산해 실제 여유를 구한다.

진행
설명 10분, 실습 25분, 계산기 연습 5분
결과
상위 이슈와 하위 이슈 6개, 의존성 7개, Start date·Target date·Estimate
명령
gh issue edit --add-sub-issue, cpm.sh, link-deps.sh
cd ~/gh-pm-lab
source pm-lab/env.sh

1작업 분해 구조: 상위 이슈와 하위 이슈

작업 분해 구조는 결과물을 끝내는 데 필요한 일을 계층으로 나눈 목록이다. 두 가지 규칙이 널리 쓰인다. 하위 항목을 모두 끝내면 상위 항목이 끝나야 한다(100% 규칙). 가장 아래 항목은 8시간 이상 80시간 이하로 나눈다(8/80 규칙). Launchpad의 여섯 업무는 12~32시간이므로 두 번째 규칙을 만족한다.

GitHub에서는 상위 이슈(parent)에 하위 이슈(sub-issue)를 연결해 표현한다. 상위 이슈 화면에 하위 이슈 목록과 완료 비율이 표시된다.

gh label create "kind:epic" -R "$PM_REPO" --color 0052CC --description "상위 업무 묶음"
PM_EPIC_URL=$(gh issue create -R "$PM_REPO" \
  --title "[LP-EPIC] 비공개 베타 사전신청" \
  --body "M1 비공개 베타에 필요한 업무 묶음이다. 하위 이슈의 완료 비율로 전체 진행을 본다." \
  --label "kind:epic")
echo "PM_EPIC_URL=\"$PM_EPIC_URL\"" >> pm-lab/env.sh

for key in LP-01 LP-02 LP-03 LP-04 LP-05 LP-06; do
  url=$(awk -F'\t' -v k="$key" '$1 == k {print $3}' pm-lab/backlog-map.tsv)
  gh issue edit "$PM_EPIC_URL" --add-sub-issue "$url"
done
gh issue view "$PM_EPIC_URL" --json subIssuesSummary --jq '.subIssuesSummary'
{"completed":1,"percentCompleted":16,"total":6}

LP-01이 실습 12에서 닫혔으므로 6개 중 1개가 완료로 계산된다. 상위 이슈에는 kind:task 라벨과 마일스톤을 붙이지 않는다. 붙이면 업무 조회와 마일스톤의 이슈 수에 묶음이 한 번 더 세어진다.

2작업일과 선행 관계

주경로 계산에는 업무마다 두 값이 필요하다. 끝내는 데 드는 작업일 수와, 먼저 끝나야 하는 업무다. 키트의 schedule.tsv에 Launchpad의 값이 들어 있다. 선행 업무는 각 업무 본문의 “선행 업무” 절과 같다.

key	days	hours	predecessors
LP-01	3	12	-
LP-02	5	24	LP-01
LP-03	6	32	LP-01
LP-04	4	20	LP-03
LP-05	3	16	LP-02,LP-03,LP-04
LP-06	2	8	LP-05
열뜻
days업무를 끝내는 데 걸리는 작업일 수(월~금). 일정 계산에 쓴다.
hours추정 공수(시간). Project의 Estimate 필드에 넣고, 실습 14의 EVM에서 예산으로 쓴다.
predecessors먼저 끝나야 하는 업무 키. 여러 개면 쉼표로 잇고, 없으면 -.

작업일과 공수는 다르다. LP-03은 6작업일 동안 32시간이 든다. 담당자가 하루 8시간을 모두 이 업무에 쓰지 않기 때문이다.

3주경로 계산

cpm.sh는 두 번 계산한다. 앞에서부터 각 업무의 가장 빠른 시작과 완료를 구하고(전진 계산), 끝에서부터 늦어도 되는 한계를 구한다(후진 계산). 두 값의 차이가 여유(float)이고, 여유가 0인 업무를 이은 것이 주경로다.

bash github-pm-starter-kit/cpm.sh github-pm-starter-kit/schedule.tsv \
  --start 2026-10-12 --deadline 2026-11-06

결과를 읽는 순서는 다음과 같다.

  • 가장 빠른 완료일은 11월 4일(수)이고 마감일까지 2작업일이 남는다. 이 2일이 M1 전체의 일정 여유다.
  • 주경로는 LP-01 → LP-03 → LP-04 → LP-05 → LP-06이다. 이 다섯 업무 중 하나가 하루 늦어지면 완료일도 하루 늦어진다.
  • LP-02의 여유는 5작업일이다. LP-02는 10월 21일 대신 10월 28일에 끝나도 전체 완료일이 바뀌지 않는다.

실습 6에서 정한 Target date(LP-03 10월 23일, LP-04 10월 30일)는 계산된 가장 빠른 완료일보다 하루에서 이틀 늦다. 목표일을 정할 때 이미 여유를 넣어 둔 셈이며, 그 여유가 주경로 위에서 얼마인지가 이 계산으로 드러난다.

4계산기로 바꿔 보기

아래 계산기는 cpm.sh와 같은 계산을 한다. 작업일 수를 바꾸면 완료일, 마감까지의 여유, 주경로가 바로 다시 계산된다.

이 계산기는 자바스크립트로 동작한다.

계산기로 아래 세 질문에 답한다.

  1. LP-03이 6일에서 8일로 늘면 완료일은 언제가 되고, 마감까지 여유는 얼마인가.
  2. LP-02는 며칠까지 늘어나도 완료일이 그대로인가.
  3. LP-04를 4일에서 2일로 줄이면(예: 알림을 메일 한 가지로 제한) 완료일은 며칠 앞당겨지는가.
답 보기
  1. 11월 6일(금). 주경로가 2일 늘어 여유가 0이 된다.
  2. 10일. 여유가 5일이므로 5+5=10일까지는 LP-05의 시작이 늦어지지 않는다. 11일이 되면 완료일이 하루 늦어진다.
  3. 2일. LP-04가 주경로에 있으므로 줄인 만큼 앞당겨져 11월 2일(월)에 끝난다.

5계산 결과를 Project와 이슈에 기록

계산 결과를 Project 필드에 넣어야 로드맵과 다음 실습의 EVM이 같은 일정을 쓴다. 먼저 필드 두 개를 만든다.

gh project field-create "$PM_PROJECT" --owner "$PM_OWNER" --name Estimate --data-type NUMBER
gh project field-create "$PM_PROJECT" --owner "$PM_OWNER" --name "Start date" --data-type DATE

--commands를 붙이면 계산 결과를 Project에 넣는 gh 명령을 출력한다. 파일로 저장해 읽어 본 뒤 실행한다. Target date는 계산된 가장 빠른 완료일로 바뀌며, 이 값이 일정 기준선(baseline)이 된다.

bash github-pm-starter-kit/cpm.sh github-pm-starter-kit/schedule.tsv \
  --start 2026-10-12 --commands > pm-lab/cpm-apply.sh
head -n 5 pm-lab/cpm-apply.sh
bash pm-lab/cpm-apply.sh
# cpm.sh가 만든 명령이다. 내용을 확인한 뒤 작업 폴더에서 bash로 실행한다.
source pm-lab/env.sh
gh project item-edit "$PM_PROJECT" --owner "$PM_OWNER" --url https://github.com/gildong/launchpad-pm-lab/issues/1 --field "Start date" --date 2026-10-12
gh project item-edit "$PM_PROJECT" --owner "$PM_OWNER" --url https://github.com/gildong/launchpad-pm-lab/issues/1 --field "Target date" --date 2026-10-14
gh project item-edit "$PM_PROJECT" --owner "$PM_OWNER" --url https://github.com/gildong/launchpad-pm-lab/issues/1 --field Estimate --value 12

선행 관계도 이슈 의존성으로 기록한다. link-deps.sh는 이미 있는 관계(실습 8의 LP-03 ← LP-01)를 건너뛴다.

bash github-pm-starter-kit/link-deps.sh "$PM_REPO" github-pm-starter-kit/schedule.tsv --dry-run
bash github-pm-starter-kit/link-deps.sh "$PM_REPO" github-pm-starter-kit/schedule.tsv

마지막으로 실습 6의 Release roadmap 보기에서 날짜 필드(Date fields)의 시작을 Start date, 목표를 Target date로 바꾼다. 막대가 계산된 일정대로 이어져 표시된다.

세 점 추정(PERT)으로 넓히기

작업일을 하나의 값 대신 낙관(O), 보통(M), 비관(P) 세 값으로 받으면 기대값 (O + 4M + P) ÷ 6을 쓸 수 있다. LP-03을 O=4, M=6, P=11로 추정하면 기대값은 (4 + 24 + 11) ÷ 6 = 6.5일이다. schedule.tsv의 days 열에 기대값을 반올림해 넣으면 같은 스크립트를 그대로 쓴다.

  • 상위 이슈 화면에 하위 이슈 6개와 완료 비율이 보인다.
  • cpm.sh 결과에서 주경로와 마감까지의 여유를 읽었다.
  • 계산기로 세 질문의 답을 확인했다.
  • Project 표에서 여섯 업무의 Start date, Target date, Estimate가 채워져 있다.
  • link-deps.sh 실행 결과가 “새로 연결 6건, 이미 있던 관계 1건”이다.
막히면
증상확인과 해결
unknown flag: --add-sub-issuegh 2.94.0 미만이다. 업그레이드하거나 웹의 상위 이슈 화면에서 Create sub-issue 옆의 Add existing issue로 연결한다.
오류: 선행 관계에 순환이 있다.schedule.tsv에서 A가 B를, B가 A를 선행으로 가리키는 줄을 찾는다.
오류: jq가 필요하다.수업 전 준비 3단계의 jq 설치 명령을 실행한다.
field "Start date" not found in project5단계의 필드 생성 명령을 먼저 실행한다.
cpm-apply.sh에 “주소가 없어 건너뛴다”pm-lab/backlog-map.tsv에 해당 키가 없다. 실습 5의 등록 스크립트를 다시 실행하면 대응표가 다시 만들어진다.

마치며...

여섯 업무가 상위 이슈 아래 하위 이슈로 묶였고, 선행 관계가 의존성으로 기록되었으며, 주경로 계산 결과(LP-01 → LP-03 → LP-04 → LP-05 → LP-06, 마감까지 여유 2작업일)가 Start date·Target date·Estimate 필드에 들어갔다. 실습 14에서는 이 일정과 추정 공수를 기준선으로 삼아 획득가치를 계산한다.