Created
July 5, 2026 09:27
-
-
Save hanjae-jea/086e8e6f96f59cf59074249f06d62669 to your computer and use it in GitHub Desktop.
prd.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # PRD: macOS Zsh 환경에서 Gum을 활용한 대화형 Git 단축 함수 구현 | |
| 이 문서는 사용자가 자신만의 대화형 Git 단축 유틸리티 함수(`gss`, `gaa`, `gcm`)를 구성할 수 있도록 시스템의 세부 동작 논리와 요구사항을 정의합니다. | |
| 이 PRD의 목표는 구체적인 코드를 주입하는 대신, 개발자의 AI 코딩 어시스턴트가 논리적 구조를 바탕으로 자유롭고 다양하게 코드를 구현할 수 있도록 **알고리즘 흐름과 단계별 요구 조건**을 명확히 제공하는 것입니다. | |
| --- | |
| ## 1. 개요 및 목표 | |
| 기존의 기본 Git 명령어(`git status`, `git add`, `git commit`)는 강력하지만 텍스트 기반이라 가독성이 낮고, 매 단계마다 타이핑이 번거롭다는 단점이 있습니다. 이 가이드를 통해 다음 기능을 구현합니다: | |
| * **풍부한 비주얼 스타일**: Nerd Font 아이콘과 터미널 색상을 활용해 파일의 변경 상태를 시각화합니다. | |
| * **대화형 스테이징 및 커밋**: 질문 창(confirm)과 다중 선택 메뉴(choose)를 통해 편리하게 파일을 스테이징하고 Conventional Commit 형식의 커밋 메시지를 생성합니다. | |
| * **안정적인 쉘 동작**: macOS Zsh 환경에서 기존 설정과 엉키거나 충돌하지 않고 안정적으로 동작하도록 설계합니다. | |
| --- | |
| ## 2. Zsh 충돌 및 에러 방지 가이드 | |
| 쉘 스크립트나 함수를 로드할 때 가장 자주 발생하는 문제는 기존 별칭(Alias)이나 명령어와의 이름 충돌입니다. 특히 대중적으로 널리 쓰이는 **Oh My Zsh의 `git` 플러그인**은 이미 아래와 같은 단축 별칭들을 선점하고 있습니다. | |
| ### 충돌 매트릭스 | |
| * **`gaa`**: Oh My Zsh에서 `alias gaa='git add --all'`로 미리 정의됨. | |
| * **`gcm`**: Oh My Zsh에서 `alias gcm='git checkout $(git_main_branch)'`로 미리 정의됨. | |
| 이 별칭들이 활성화되어 있으면, Zsh는 사용자가 작성한 커스텀 함수보다 별칭(Alias)을 우선하여 실행합니다. 따라서 기대했던 대화형 UI 대신 기본 단축 명령어가 작동하게 됩니다. | |
| ### 설계 조건 (충돌 방지) | |
| 1. **기존 별칭 강제 해제 (Unalias)**: 작성하려는 단축 명령어(`gaa`, `gcm`)와 동일한 이름을 가진 Zsh 별칭이 있다면, 함수를 정의하기 직전에 먼저 별칭을 해제(`unalias 별칭이름 2>/dev/null`)해야 합니다. | |
| 2. **Git 저장소 유효성 검사**: 사용자가 실행하는 모든 메인 함수는 가장 먼저 현재 위치가 Git 작업 공간 내부인지 확인해야 하며, 작업 공간이 아닐 시 적절한 경고 메시지를 출력하고 종료(exit code 1 등)해야 합니다. | |
| 3. **Zsh 내장 기능 사용**: 1부터 시작하는 Zsh 배열 인덱스 체계와 문자열 변환 기능(예: 확장자 소문자 변환 시 `${(L)variable}` 사용)에 맞게 안전한 Zsh 문법으로 로직을 감싸야 합니다. | |
| --- | |
| ## 3. 구조적 설계 및 세부 로직 사양 | |
| 전체 단축 유틸리티는 1개의 스타일링 헬퍼 함수와 3개의 사용자 명령어로 구성됩니다. | |
| ```mermaid | |
| graph TD | |
| A[gss: 스타일 상태 표시] -->|의존| B[_gum_git_style_line: 라인 스타일링 헬퍼] | |
| C[gaa: 대화형 add] -->|호출| A | |
| D[gcm: 대화형 commit] -->|호출| A | |
| ``` | |
| --- | |
| ### A. 내부 스타일링 헬퍼 함수 (`_gum_git_style_line`) | |
| 이 함수는 `git status --porcelain`이 출력하는 로우(raw) 텍스트 데이터를 분석하여 폰트 아이콘과 전경색(Foreground)이 입혀진 터미널 한 줄 문자열을 생성하여 반환합니다. | |
| #### 1) 입력 매개변수 | |
| * `$1`: 파일 상태 코드 (예: `M `, `A `, `??`, ` M` 등 공백을 포함한 2자리 상태 표식) | |
| * `$2`: 변경된 파일 경로 (이름이 변경된 경우 `이전경로 -> 새경로` 포맷이 들어옴) | |
| #### 2) 조건식 및 처리 흐름 | |
| 1. **이름 변경(Rename) 처리**: | |
| * 만약 상태 코드(`$1`)가 `"R "` (Staged Rename) 이라면, 파일 경로에서 ` -> ` 구분자 뒤쪽의 '새 파일 경로'에서 basename을 추출해 파일명으로 정의합니다. | |
| * 그렇지 않은 보통의 상태 코드인 경우, 파일 경로 전체에서 단순 basename을 추출합니다. | |
| 2. **확장자 추출 및 대소문자 무시**: | |
| * 정의된 파일명에서 확장자를 추출한 뒤 소문자로 일괄 변환합니다. | |
| 3. **아이콘 매핑 조건문**: | |
| * 추출한 확장자 혹은 파일명에 알맞은 Nerd Font 아이콘을 선택합니다. | |
| * *예시 기준*: | |
| * 파일명이 `Dockerfile` 인 경우: `` | |
| * 파일명이 `.gitignore` 인 경우: `` | |
| * 확장자가 `js`, `mjs` 인 경우: `` | |
| * 확장자가 `ts`, `tsx` 인 경우: `` | |
| * 확장자가 `py` 인 경우: `` | |
| * 확장자가 `md` 인 경우: `` | |
| * 확장자가 `json` 인 경우: `` | |
| * 확장자가 `sh`, `zsh` 인 경우: `` | |
| * 기타 일반 파일: 기본 아이콘 `` | |
| 4. **색상 매핑 조건문**: | |
| * Git 상태 코드 문자열(`$1`)에 매칭되는 ANSI 전경색 코드를 설정합니다. | |
| * *추천 색상 가이드*: | |
| * `M ` (Staged 수정), `A ` (Staged 추가): 녹색 계열 (예: ANSI `46`) | |
| * `D ` (Staged 삭제): 적색 계열 (예: ANSI `196`) | |
| * `R ` (Staged 이름 변경): 자주색 계열 (예: ANSI `201`) | |
| * ` M` (Unstaged 수정): 분홍색 계열 (예: ANSI `218`) | |
| * ` D` (Unstaged 삭제): 적색 계열 (예: ANSI `196`) | |
| * `??` (추적되지 않는 파일): 황색 계열 (예: ANSI `220`) | |
| * 기타 기본값: 회색 계열 (예: ANSI `240`) | |
| 5. **텍스트 렌더링 및 출력**: | |
| * `gum style` 명령을 활용하여 상태 코드 부분과 파일 경로 부분 각각에 해당하는 색상을 입힙니다. | |
| * `printf`를 사용하여 `[컬러 상태코드] [아이콘] [컬러 파일경로]` 규격의 포맷팅된 문자열을 출력합니다. | |
| --- | |
| ### B. 사용자 명령어: `gss` (Git Status Styled) | |
| 현재 작업 트리의 변경 내역을 수집하여 Staged 영역과 Unstaged 영역으로 구분한 뒤 테두리가 감싸진 박스 형태로 보기 좋게 인쇄합니다. | |
| #### 1) 처리 흐름 및 조건문 설계 | |
| 1. **저장소 유효성 검사**: 현재 폴더가 Git 저장소 내부인지 검사하고 아닐 시 안전하게 메시지를 남기고 에러 코드로 리턴합니다. | |
| 2. **리스트 변수 선언**: Staged 목록을 보관할 배열과 Unstaged 목록을 보관할 배열을 생성합니다. | |
| 3. **상태 한 줄 읽기 루프**: | |
| * `git status --porcelain` 명령의 결과를 라인 단위로 읽어들이는 반복문(Loop)을 실행합니다. | |
| * 각 라인이 비어있는 경우 생략(continue)합니다. | |
| * 각 라인의 앞 2글자(상태 코드)와 3번째 글자 이후(파일 경로)를 추출합니다. | |
| * **Staged 여부 조건 분기**: | |
| * 상태 코드가 스테이징 완료 상태(첫 글자가 `M`, `A`, `D`, `R` 중 하나로 시작함)인 경우: | |
| * `_gum_git_style_line` 헬퍼 함수를 통해 라인을 예쁘게 꾸민 뒤 **Staged 배열**에 삽입합니다. | |
| * 그 외의 상태 코드(두 번째 글자가 수정/삭제되었거나 신규 추적되지 않는 상태)인 경우: | |
| * 헬퍼 함수를 호출하여 꾸민 뒤 **Unstaged 배열**에 삽입합니다. | |
| 4. **최종 출력 레이아웃 조립**: | |
| * **Staged 영역 추가 조건문**: | |
| * 만약 Staged 배열에 요소가 들어있다면, 녹색의 굵은 글씨로 `'Staged Changes:'` 헤더 타이틀을 추가하고 그 아래에 Staged 배열 전체 내용을 담습니다. | |
| * **Unstaged 영역 추가 조건문**: | |
| * 만약 Unstaged 배열에 요소가 들어있다면, (Staged 변경 사항이 이미 존재했다면 빈 한 줄을 띄워 구별한 뒤) 황색의 굵은 글씨로 `'Unstaged Changes:'` 헤더 타이틀을 추가하고 그 아래에 Unstaged 배열 전체 내용을 담습니다. | |
| 5. **종료 조건 확인**: | |
| * 조립한 전체 출력 배열의 크기가 0이면 "Nothing to commit, working tree clean." 메시지를 남기고 정상 종료합니다. | |
| 6. **박스 그리기**: | |
| * 수집된 모든 표시용 문자열 라인들을 `gum style`에 매개변수로 전달하여, 원하는 색상의 테두리(`--border normal --border-foreground [색상번호]`)와 약간의 좌우 여백을 주어 최종 출력합니다. | |
| --- | |
| ### C. 사용자 명령어: `gaa` (Git Add All - Interactive) | |
| `gss` 화면을 먼저 보여준 다음, 사용자가 스테이징되지 않은 모든 변경 사항을 원클릭으로 간편하게 추가(add)할 수 있는 안전한 대화형 장치를 제공합니다. | |
| #### 1) 처리 흐름 및 조건문 설계 | |
| 1. **저장소 유효성 검사**: 현재 폴더가 Git 저장소 내부인지 검사하고 아닐 시 에러 코드로 리턴합니다. | |
| 2. **변경 사항 유무 검사**: `git status --porcelain` 출력값이 완전히 비어있다면 "추가할 변경 사항이 없다"는 안내 후 즉시 종료합니다. | |
| 3. **현재 상태 표시**: `gss` 함수를 실행하여 현재 워킹 트리 내에 변경된 내역을 시각적으로 보여줍니다. | |
| 4. **확인 창(confirm) 분기**: | |
| * 만약 스테이징되지 않은 파일이 남아있는 상태라면: | |
| * `gum confirm "Stage all unstaged changes?"` 프롬프트를 사용자에게 제공합니다. | |
| * 사용자가 **동의(Yes)**할 경우: `git add .` 명령을 수행하고 완료 메시지(성공 알림 체크표시 포함)를 스타일링하여 터미널에 표시합니다. | |
| * 사용자가 **거절(No) 혹은 취소**할 경우: `"작업이 취소되었습니다."` 메시지를 출력하고 종료합니다. | |
| --- | |
| ### D. 사용자 명령어: `gcm` (Git Commit Menu) | |
| 변경 사항 시각화, 부분적/개별적 파일 스테이징 선택, 그리고 Conventional Commit 구조의 질문지 마법사를 통해 완성도 높은 커밋을 수행합니다. | |
| #### 1) 처리 흐름 및 조건문 설계 | |
| 1. **저장소 유효성 검사**: 현재 폴더가 Git 저장소 내부인지 검사하고 아닐 시 종료합니다. | |
| 2. **변경 사항 유무 검사**: 변경된 파일 내역 자체가 아예 없다면 "커밋할 변경 사항이 없다"는 메시지 출력 후 종료합니다. | |
| 3. **상태 배열 수집 및 표시**: | |
| * `gss`에서와 동일하게 Porcelain 출력을 읽어 Staged와 Unstaged 파일 목록 배열을 채웁니다. | |
| * `gss` 함수를 한 번 실행해 줍니다. | |
| 4. **Unstaged 파일 처리 조건 분기**: | |
| * Unstaged 파일 배열에 항목이 존재하는 경우: | |
| * `gum confirm "Stage all unstaged changes?"`를 호출합니다. | |
| * **전체 스테이징 동의 시**: `git add .`을 실행합니다. | |
| * **전체 스테이징 비동의 시**: | |
| * `gum choose --no-limit`를 띄우며, 이때 선택 후보 리스트로 우리가 앞서 예쁘게 꾸며둔 **Unstaged 배열의 문자열들**을 전달합니다. | |
| * 사용자가 선택을 확정하면, 반환된 스타일 문자열 목록에서 ANSI 컬러 기호나 상태 기호 등을 정제하고 **순수한 원본 파일 경로들만 파싱**해 냅니다. (힌트: 첫 번째 필드인 상태 코드와 두 번째 필드인 아이콘 문자열을 필터링하고 공백을 제거하는 파싱 로직 설계 필요) | |
| * 걸러진 원본 파일 경로 목록을 `xargs git add` 또는 반복문을 통해 하나씩 스테이징 영역에 추가합니다. | |
| * **프롬프트 도중 탈출(ESC 등) 시**: "작업 취소" 메시지를 띄우며 함수 전체를 취소 반환합니다. | |
| 5. **최종 스테이징 변경 사항 무결성 확인**: | |
| * 위의 스테이징 흐름을 거친 뒤에도 Staged 상태에 변경된 내용이 최종적으로 존재하는지 확인합니다 (`git diff --staged --quiet` 등을 활용). | |
| * 만약 스테이징된 내역이 없다면 "No changes staged for commit." 경고 후 안전하게 종료합니다. | |
| 6. **커밋 마법사 작성 프로세스**: | |
| * **단계 1: 커밋 타입 선택** | |
| * `gum choose`를 띄워 아래 스타일 양식의 타입 리스트를 사용자에게 제시하고 하나를 반환받습니다: | |
| * `✨ feat: 새로운 기능 추가` | |
| * `🐛 fix: 버그 수정` | |
| * `📝 docs: 문서 수정` | |
| * `🎨 style: 코드 포맷팅, 세미콜론 누락 등` | |
| * `♻️ refactor: 코드 리팩토링` | |
| * `⚡️ perf: 성능 개선` | |
| * `✅ test: 테스트 코드 추가/수정` | |
| * `🚀 chore: 빌드, 패키지 매니저 설정 등` | |
| * 반환값에서 콜론(`:`) 이전의 접두사 영역(예: `✨ feat`)만 파싱하여 `TYPE` 변수에 저장합니다. | |
| * **단계 2: 커밋 제목 입력** | |
| * `gum input --placeholder "커밋 제목"` 프롬프트를 띄워 사용자가 요약 문구를 적도록 합니다. | |
| * 사용자가 아무것도 입력하지 않고 빈 문자열을 남길 경우 "커밋 제목이 비어 있어 작업을 중단합니다." 경고와 함께 실패 상태로 리턴합니다. | |
| * **단계 3: 커밋 상세 본문 입력** | |
| * `gum write --placeholder "자세한 설명 (Ctrl+D 또는 Esc로 완료)"`를 띄워 긴 형태의 상세 텍스트 설명을 작성하도록 유도합니다. | |
| * **단계 4: 최종 커밋 실행** | |
| * 만약 본문내용(Body)이 비어있다면: `git commit -m "[TYPE]: [SUBJECT]"`를 실행합니다. | |
| * 본문내용(Body)이 입력되었다면: `git commit -m "[TYPE]: [SUBJECT]" -m "[BODY]"`를 실행합니다. | |
| --- | |
| ## 4. 검증 및 테스트 시나리오 | |
| 개발자는 자신이 활용하는 AI 코딩 어시스턴트를 사용해 완성된 Zsh 스크립트를 빌드한 후, 아래 체크리스트로 최종 작동 테스트를 진행해야 합니다. | |
| 1. **별칭 해제 우선권(Alias Priority) 작동 여부**: | |
| * `alias gaa` 또는 `alias gcm`을 입력하여 Oh My Zsh 등의 기존 단축키가 강제로 비활성화되고 정의한 커스텀 함수가 제대로 바인딩되는지 검증합니다. | |
| 2. **저장소 경계 제어 검증**: | |
| * Git 저장소가 아닌 곳에서 `gss` 또는 `gaa`를 실행했을 때 에러 메시지와 함께 비정상적 중단 없이 흐름이 차단되는지 확인합니다. | |
| 3. **터미널 아이콘 깨짐 현상 검사**: | |
| * 파일 확장자 매칭 아이콘이 네모난 빈 박스나 알 수 없는 유니코드 오류 문자 없이 아름답게 로드되는지 확인합니다. (깨지는 현상 발견 시 터미널 전용 폰트 설정을 점검하십시오.) | |
| 4. **개별 선택 스테이징 복구 검사**: | |
| * `gcm` 실행 중 전체 스테이징을 거부한 상황에서, 개별 파일들을 Space로 선택하여 활성화(`gum choose`)했을 때 실제 해당 파일들만 성공적으로 `git add`가 진행되는지 체크합니다. | |
| 5. **최종 커밋 메시지 형식 확인**: | |
| * 완결된 커밋 이후 `git log -1`을 실행하여 `[이모지] [타입]: [제목]` 과 함께 작성한 본문 설명이 안전하게 커밋 이력에 남았는지 로그를 읽어 검증합니다. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment