팀 업무·협업

담당자, 위치, 미해결 이슈가 포함된 프로젝트 인수인계 체크리스트 만들기

프로젝트 인수인계 메모를 전달 대상, 담당자, 자료 위치, 미해결 작업이 명확한 체크리스트로 정리합니다. 작은 합성 예제를 이용해 인수인계 전에 누락된 담당자, 위치, 미해결 이슈 정보를 확인합니다.

목차 보기

이런 분께 맞아요프로젝트를 다른 사람에게 넘기면서 담당자, 파일 위치, 미해결 업무를 명확하게 기록해야 하는 팀을 위한 안내입니다.

준비할 것
  • Python 3.12와 해당 버전을 실행하는 터미널 명령이 준비되어 있어야 합니다.
  • UTF-8 CSV를 저장할 수 있는 텍스트 편집기 또는 스프레드시트 프로그램이 필요합니다.
  • 스크립트가 outputs 아래에 새 폴더를 만들 수 있는 작업 폴더가 필요합니다.
  • Python 표준 라이브러리인 csv와 pathlib만 사용합니다.

01모든 인수인계 항목이 답해야 하는 정보 정의하기

유용한 인수인계 체크리스트는 무엇을 넘기는지, 누가 책임지는지, 관련 자료가 어디 있는지, 완료 상태가 무엇인지, 아직 해결되지 않은 것이 무엇인지 알려줘야 합니다. 파일은 드라이브에 있다는 식의 메모만으로는 나중에 프로젝트를 맡는 사람이 실제 자료를 찾기 어렵습니다.

이 예제에서는 item_id, handover_item, owner, location, status, open_issue의 여섯 필드를 사용합니다. status는 READY 또는 OPEN입니다. READY 항목은 open_issue가 비어 있어야 하고, OPEN 항목은 무엇이 미해결 상태인지 설명해야 합니다.

02합성 프로젝트 인수인계 체크리스트 만들기

아래 체크리스트는 이 글을 위해 작성한 합성 데이터입니다. handover_items.csv로 저장하세요. 인수인계 항목 5개가 있고, 실제 인수인계 전에 잡아야 하는 문제 2개를 의도적으로 포함했습니다.

csv
item_id,handover_item,owner,location,status,open_issue
H001,Source code,Min,repo/main,READY,
H002,Test dataset,Jae,shared-drive/project/data,READY,
H003,Calibration procedure,Min,shared-drive/project/docs/calibration.pdf,OPEN,Final approval is still pending
H004,Supplier contact list,,shared-drive/project/admin/suppliers.csv,READY,
H005,Open bug list,Jae,,OPEN,Two export bugs remain under review

H001부터 H003까지는 구조적으로 완전합니다. H004는 READY인데 담당자가 없습니다. H005는 미해결 이슈 설명은 있지만 bug list 위치가 없습니다. 따라서 이 예제의 검증 문제는 2개입니다.

03먼저 손으로 체크리스트 검토하기

item_id예상 결과이유
H001PASS담당자와 위치가 있고 READY이므로 open issue가 없음
H002PASS담당자와 위치가 있고 READY이므로 open issue가 없음
H003PASSOPEN 항목에 담당자, 위치, 미해결 이슈가 모두 있음
H004FAIL담당자 누락
H005FAIL위치 누락

예상 결과는 전체 체크리스트 5개, 정상 3개, 문제 항목 2개입니다. OPEN 상태는 H003과 H005 두 개이며 둘 다 open_issue 내용이 있습니다. 따라서 이 예제의 문제는 미해결 이슈 설명 누락이 아니라 책임자와 위치 정보 누락입니다.

이 구분이 중요한 이유는 미해결 이슈가 존재해도 문제 내용, 담당자, 위치가 명확하다면 프로젝트 자체는 인수인계 가능한 상태일 수 있기 때문입니다.

04Python으로 인수인계 체크리스트 검증하기

다음 스크립트를 check_handover.py로 저장하세요. 필수 열, 중복 ID, 담당자, 위치, 허용 상태, status와 open_issue의 일관성을 검사합니다. 원본 체크리스트는 수정하지 않고 별도의 검토 보고서를 작성합니다.

python
import csv
from pathlib import Path

SOURCE = Path("handover_items.csv")
OUTPUT_DIR = Path("outputs") / "handover_check_result"
REPORT = OUTPUT_DIR / "handover_review.csv"
REQUIRED_COLUMNS = [
    "item_id", "handover_item", "owner", "location", "status", "open_issue"
]
VALID_STATUS = {"READY", "OPEN"}


def add_issue(issues, row_number, item_id, issue):
    issues.append({
        "row_number": row_number,
        "item_id": item_id,
        "issue": issue,
    })


def main() -> None:
    if not SOURCE.is_file():
        raise FileNotFoundError(f"Source CSV not found: {SOURCE}")
    if OUTPUT_DIR.exists():
        raise FileExistsError(f"Output folder already exists: {OUTPUT_DIR}")

    issues = []
    seen_ids = set()
    item_count = 0
    open_count = 0

    with SOURCE.open("r", encoding="utf-8-sig", newline="") as stream:
        reader = csv.DictReader(stream)
        if reader.fieldnames != REQUIRED_COLUMNS:
            raise ValueError(
                f"Header mismatch. Expected {REQUIRED_COLUMNS}, got {reader.fieldnames}."
            )

        for row_number, row in enumerate(reader, start=2):
            item_count += 1
            item_id = row["item_id"].strip()
            handover_item = row["handover_item"].strip()
            owner = row["owner"].strip()
            location = row["location"].strip()
            status = row["status"].strip()
            open_issue = row["open_issue"].strip()

            if not item_id:
                add_issue(issues, row_number, item_id, "MISSING_ITEM_ID")
            elif item_id in seen_ids:
                add_issue(issues, row_number, item_id, "DUPLICATE_ITEM_ID")
            seen_ids.add(item_id)

            if not handover_item:
                add_issue(issues, row_number, item_id, "MISSING_ITEM_NAME")
            if not owner:
                add_issue(issues, row_number, item_id, "MISSING_OWNER")
            if not location:
                add_issue(issues, row_number, item_id, "MISSING_LOCATION")
            if status not in VALID_STATUS:
                add_issue(issues, row_number, item_id, "INVALID_STATUS")
            elif status == "OPEN":
                open_count += 1
                if not open_issue:
                    add_issue(issues, row_number, item_id, "MISSING_OPEN_ISSUE")
            elif open_issue:
                add_issue(issues, row_number, item_id, "READY_HAS_OPEN_ISSUE")

    OUTPUT_DIR.parent.mkdir(parents=True, exist_ok=True)
    OUTPUT_DIR.mkdir()
    with REPORT.open("x", encoding="utf-8", newline="") as stream:
        writer = csv.DictWriter(
            stream,
            fieldnames=["row_number", "item_id", "issue"],
        )
        writer.writeheader()
        writer.writerows(issues)

    affected_items = len({row["item_id"] for row in issues})
    print(f"Checklist items: {item_count}.")
    print(f"Open items: {open_count}.")
    print(f"Validation issues: {len(issues)}.")
    print(f"Affected items: {affected_items}.")
    print(f"Report: {REPORT.as_posix()}")


if __name__ == "__main__":
    main()

05예상 검토 보고서와 비교하기

CSV 헤더가 1행이므로 H004는 실제 5행이고 H005는 실제 6행입니다. 검토 보고서에는 정확히 문제 2개가 기록되어야 합니다.

csv
row_number,item_id,issue
5,H004,MISSING_OWNER
6,H005,MISSING_LOCATION

아래 예상 콘솔 출력은 합성 체크리스트와 스크립트를 바탕으로 손으로 도출한 결과이며 실제 실행 로그가 아닙니다.

text
Checklist items: 5.
Open items: 2.
Validation issues: 2.
Affected items: 2.
Report: outputs/handover_check_result/handover_review.csv

06파일 존재 여부보다 더 많은 항목 확인하기

  • 인수인계 후 담당자가 바뀌더라도 현재 기준의 명확한 담당자가 각 항목에 한 명씩 있는지 확인합니다.
  • 각 location을 직접 열어 다음 담당자가 실제로 접근할 수 있는지 확인합니다.
  • OPEN 항목은 미해결 문제, 현재 상태, 다음 예상 조치를 함께 기록합니다.
  • READY 항목에 채팅, 개인 메모, 주석 등에 숨겨진 미해결 작업이 없는지 확인합니다.
  • 비밀번호나 비밀정보는 체크리스트에 적지 말고 승인된 비밀번호 또는 접근 관리 절차로 전달합니다.
  • OUTPUT_DIR을 바꾸지 않고 다시 실행합니다. 이전 검토 결과를 교체하지 않고 FileExistsError로 중단되어야 합니다.

경로 문자열이 존재해도 권한이 없거나 오래된 파일을 가리키면 인수인계 정보로 쓸모가 없습니다. 따라서 작성한 사람뿐 아니라 받는 사람도 체크리스트를 직접 확인해야 합니다.

07자주 발생하는 인수인계 실패 확인하기

약한 인수인계 항목부족한 이유
Owner: Team특정 사람이나 정의된 역할에 책임이 연결되지 않으면 담당이 불분명합니다.
Location: Drive받는 사람이 실제 파일이나 폴더를 다시 찾아야 합니다.
Status: Done팀에서 완료의 정의가 명확하지 않으면 의미가 모호합니다.
Open issue: Needs work어떤 문제가 있고 다음에 무엇을 해야 하는지 알 수 없습니다.
CSV에 비밀번호 기록일반 인수인계 체크리스트는 비밀번호나 secret을 저장하는 장소가 아닙니다.

파일이 있다는 이유만으로 READY로 표시하지 마세요. 실제로 사용할 수 있는 인수인계에는 접근 권한, 최신 문서, 책임자, 미해결 결정 사항에 대한 이해도 필요합니다.

08큰 프로젝트에서는 체크리스트 확장하기

실제 프로젝트에서는 receiving_owner, due_date, repository branch, access_required, last_verified_date, dependency, contact person, equipment location, approval status, next milestone 같은 필드가 추가로 필요할 수 있습니다. 전달 명확성을 실제로 높이는 경우에만 필드를 추가하세요.

이 스크립트는 입력 정보의 완전성과 내부 일관성을 검사할 뿐 location이 실제로 접근 가능한지, open issue 설명이 기술적으로 정확한지는 판단하지 않습니다. 접근 권한, 파일 최신성, repository 상태, 장비 상태, 지식 전달은 별도로 확인해야 합니다.

체크리스트는 날짜 또는 버전을 부여해 프로젝트 기록과 함께 보관하세요. 받는 사람이 인수인계를 확인한 뒤에는 원래 전달 상태를 조용히 수정하지 말고 수락 여부를 별도로 기록하는 편이 좋습니다.

실행·검증 기록

2026-09-20 · 예제 수동 검토 · 대상: Python 3.12 · 표준 라이브러리: csv, pathlib · 실행하지 않음

  • 합성 인수인계 항목 5개와 OPEN 상태 항목 2개를 수동으로 확인했습니다.
  • H001, H002, H003이 구조적으로 유효한지 손으로 확인했습니다.
  • H004는 담당자가 누락되었고 H005는 위치가 누락되었음을 확인했습니다.
  • OPEN 항목 두 개 모두 open_issue 설명이 비어 있지 않음을 확인했습니다.
  • H004와 H005의 실제 CSV 행 번호가 각각 5와 6임을 수동으로 도출했습니다.
  • 필수 헤더, 중복 ID, owner 및 location 검사, status 일관성, 출력 충돌 방지, 원본 CSV 보존 로직을 코드로 검토했습니다.
검증 한계
  • 이 응답의 작성자는 코드를 실행하지 않았으며, 검토 CSV를 실제로 만들지 않았습니다.
  • 스크립트는 기록된 경로가 실제로 접근 가능하거나 최신이거나 정확한지 확인하지 않습니다.
  • 합성 담당자, 위치, 이슈는 예시이며 실제 프로젝트를 설명하지 않습니다.
  • 비밀정보 전달, 권한 이전, repository 상태, 장비 상태, 실제 지식 전달 품질은 시험하지 않았습니다.
  • 공식 문서 URL은 알려진 문서 위치를 사용했지만 실시간으로 접속해 확인하지 않았습니다.

사이트 전체 작성·검증 원칙

참고 출처

설명과 예제는 직접 작성했습니다. 관련 동작과 개념은 아래 공식 자료에서 확인할 수 있습니다.