개요
사이드 프로젝트에서 계속 Pull Request를 사용하다 보니 어느 “순간 작업 내역에 대한 요약을 보는 게 애매하다” 는 생각을 가지게 됐다.
중간중간 Commit 내역으로 하여금 무슨 작업을 했는지는 파악할 수는 있어도 2% 부족하다는 심상이었다.
그러던 중 Pull Request가 Open 되면 해당 작업 내역을 AI로 요약해주는 무언가를 만들면 괜찮지 않을까 싶어 조사를 했고 Github Action을 이용해 해당 부분을 처리할 수 있었다.
좋은 Pull Request란?
지난 글에서는 PyCharm의 Plugin을 활용해 Commit Message를 자동으로 생성하는 과정에서 “좋은 Commit Message”란 무엇일까를 고민하게 됬고 “좋은 Commit Message”는 어떻게 작성해야 하는지에 대해 다루는 많은 자료를 참고할 수 있었다.
이번 주제도 마찬가지로 “좋은 Pull Request”를 고민하면서 “좋은 Pull Request”는 무엇인지에 대해 조사해 봤다. 여러 글을 읽고 나서 종합했을 때 하기 항목으로 정리했다.
- PR은 작고 논리적인 단위로 나눠라
- 하나의 PR에 너무 많은 변경사항을 넣지 말 것
- 이상적인 PR은 리뷰어가 한 번에 이해 가능한 수준의 변경만 포함
- 큰 작업은 여러 단계로 나누어 PR을 보내는 것이 좋음
- 좋은 제목과 설명을 작성하라
- 변경 이유(Why), 변경 내용(What), 구현 방식(How), 테스트 방법(How to test)
- 리뷰어의 시간을 존중하라
- PR을 올리기 전에 스스로 코드를 한 번 더 읽어보고 정리하라.
- Dead Code, 디버깅 로그, 불필요한 파일은 제거
- 변경된 코드가 기존 시스템에 미칠 영향도 고려하라.
- 변경 사항에 대한 문맥을 제공하라
- 변경의 이유와 의도를 명확히 설명하여 리뷰어가 배경을 쉽게 이해하게 함
- 필요시, 링크, 문서 , 스크린 숏 등을 활용해도 좋음
- 자주 빠르게 PR을 날려라
위 내용은 PR을 요청하는 사람의 입장에서 정리한 내용이다. 내가 “리뷰어”라고 한다면 PR은 어떻게 바라봐야 할까?
- 리뷰어는 “내가 이 코드를 운영환경에서 유지보수해야 한다면?”이라는 관점으로 리뷰
- 피드백은 구체적이고 친절하게 전달할 것
Pull Request는 어떻게 작성하면 좋을까 ?
상술한 내용에서는 “좋은 Pull Request”에 대한 특징을 간단히 나열해 봤다. 이 글의 “개요”에서 언급했듯 Pull Request를 수기로 작성하기보단 AI에게 위임할 것이다. 다시 말해 해당 특징을 활용해 AI에게 Pull Request가 Open 되면 요약해달라고 할 것이다.
필자의 경우 다음의 양식을 통해 Pull Request를 요약해 달라고 prompt를 작성했다.
# Summary
- 무엇을, 왜 수정했는지 간단하게 요약합니다.
# What's Changed
- 핵심 변경 사항을 취합 및 요약해주세요, bullet point를 활용해 3줄 정도로 정리해주세요
# Side Effects
- 시스템에 어떤 문제 생길 수 있는지 짚어주세요.
# Suggest
- 이 PR에서 잘 처리된 부분은 무엇이고 잘 처리되지 않은 부분이 무엇인지 짚어주세요.
## 잘 처리된 부분
- 예시
- XXX 모듈의 책임 분리 → 유지보수성과 가독성 향상
- 불필요한 의존성 제거 → 코드 간결성 증가
- 인터페이스 분리 및 추상화 계층 도입 → 테스트 및 확장성 고려한 설계
## 잘 처리되지 않은 부분
- "예시"에 맞춰서 여러 항목을 입력해도 좋습니다.
- 예시
---
문제: 어떤 부분이 잘 처리되지 않았는지 명확히 서술합니다.
개선안: 구체적으로 어떻게 개선하면 좋을지 제안합니다.
참고 파일/위치: 수정이 필요한 코드의 위치나 파일 경로를 명시합니다.
추천 등급: (P1 ~ P5 중 하나 선택)
P1: 꼭 반영해주세요 (Request Change)
P2: 적극적으로 고려해주세요 (Request Change)
P3: 웬만하면 반영해주세요 (Comment)
P4: 반영해도 좋고 넘어가도 좋습니다 (Approve)
P5: 그냥 사소한 의견입니다 (Approve)
등급 사유: 왜 해당 등급을 부여했는지 논리적으로 설명합니다.
---
위 내용에서 P1~P5라고 넘버링이 붙은 부분을 확인할 수 있다. 이는 뱅크샐러드의 Pn룰을 참조했고 AI에게 이러한 부분을 짚어달라고 할 것이다.
AI를 활용해 Pull Request 요약 처리하기
이제 Github Action를 이용해 AI가 Pull Request를 어떻게 요약할 수 있는지 정리해보려 한다. 필자는 Gemini를 사용하고 있기에 Gemini의 API Key와 관련 라이브러리를 활용했다.
1. Github Action 스크립트 설정하기
Pull Request가 Open 되면 Github Action가 동작하며 이 과정에서 Pull Request를 요약해 주는 Python Script의 위치를 지정하는 방식이다.
name: Gemini PR Summary and Explanation
on:
pull_request:
types: [opened, synchronize]
jobs:
pr-summary:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- name: Checkout Repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.9.16'
- name: Install Python Packages
run: |
pip install google-generativeai
- name: Fetch and Generate Git Diff for PR
run: |
git fetch origin "${{ github.event.pull_request.base.ref }}"
git fetch origin "${{ github.event.pull_request.head.ref }}"
git diff --unified=0 "origin/${{ github.event.pull_request.base.ref }}" > diff.txt
- name: Generate PR Summary with Gemini
env:
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
run: |
python3 deployment/generate_summary.py
- name: Format PR Review Summary for Comment
id: store
run: |
COMMENT_STRING=$(cat review_result.txt)
echo "comment<<EOF" >> $GITHUB_OUTPUT
echo "# AI PR 요약" >> $GITHUB_OUTPUT
echo "$COMMENT_STRING" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Post PR Summary Comment
uses: mshick/add-pr-comment@v2
with:
message: ${{ steps.store.outputs.comment }}
repo-token: ${{ secrets.GITHUB_TOKEN }}
위 스크립트 중간에 “python3 deployment/generate_summary.py”라는 라인이 이에 해당한다.
2. generate_summary는 어떻게 생겼는가?
generate_sumamry.py는 다음과 같이 작성되었다. 코드에서 확인할 수 있다시피 GEMINI_API_KEY가 환경변수에 등록되어있어야 한다.
import os
import google.generativeai as genai
def main():
# Gemini API 키 읽기
gemini_api_key = os.getenv("GEMINI_API_KEY")
if not gemini_api_key:
raise Exception("GEMINI_API_KEY 환경변수가 설정되지 않았습니다.")
# Gemini API 초기화
genai.configure(api_key=gemini_api_key)
# diff.txt 읽기
with open('diff.txt', 'r', encoding='utf-8') as f:
diff_output = f.read()
# 프롬프트 텍스트 구성
prompt_text = f"""
다음은 깃허브 PR 에 올라온 수정된 코드들 입니다.
Git diff를 분석하고 이 PR이 뭘 변경했는지 하기 Template으로 요약해주세요.
# Recommand
- 이 PR의 제목을 추천해주세요
# Summary
- 무엇을, 왜 수정했는지 간단하게 요약합니다.
# What's Changed
- 핵심 변경 사항을 취합 및 요약해주세요, bullet point를 활용해 3줄 정도로 정리해주세요
# Side Effects
- 시스템에 어떤 문제 생길 수 있는지 짚어주세요.
# Suggest
- 이 PR에서 잘 처리된 부분은 무엇이고 잘 처리되지 않은 부분이 무엇인지 짚어주세요.
## 잘 처리된 부분
- 예시
- XXX 모듈의 책임 분리 → 유지보수성과 가독성 향상
- 불필요한 의존성 제거 → 코드 간결성 증가
- 인터페이스 분리 및 추상화 계층 도입 → 테스트 및 확장성 고려한 설계
## 잘 처리되지 않은 부분
- "예시"에 맞춰서 여러 항목을 입력해도 좋습니다.
- 예시
---
문제: 어떤 부분이 잘 처리되지 않았는지 명확히 서술합니다.
개선안: 구체적으로 어떻게 개선하면 좋을지 제안합니다.
참고 파일/위치: 수정이 필요한 코드의 위치나 파일 경로를 명시합니다.
추천 등급: (P1 ~ P5 중 하나 선택)
P1: 꼭 반영해주세요 (Request Change)
P2: 적극적으로 고려해주세요 (Request Change)
P3: 웬만하면 반영해주세요 (Comment)
P4: 반영해도 좋고 넘어가도 좋습니다 (Approve)
P5: 그냥 사소한 의견입니다 (Approve)
등급 사유: 왜 해당 등급을 부여했는지 논리적으로 설명합니다.
---
결과는 반드시 한국어로 번역해주세요.
<git diff>{diff_output}</git diff>
"""
# 모델 설정
generation_config = {
"temperature": 0.9,
"top_p": 1,
"top_k": 1,
"max_output_tokens": 2048,
}
# Gemini 모델 생성
model = genai.GenerativeModel('gemini-1.5-pro', generation_config=generation_config)
response = model.generate_content(prompt_text)
# 결과 파일로 저장
with open('review_result.txt', 'w', encoding='utf-8') as f:
f.write(response.text)
if __name__ == "__main__":
main()
3. 환경변수 설정하기
앞선 내용에선 “GEMINI_API_KEY”라는 환경변수가 필요하다고 언급했는데 이는 Github Action이 실행되는 와중에 참조하는 환경변수다. Github Repo의 다음 위치에서 설정할 수 있다.
Settings > Secrets and Variables > Actions
마치며
필자는 위 내용을 사이드 프로젝트에 적용했다. 진행 중인 사이드프로젝트가 실 사용자가 있는 상황이고 프로젝트 구조를 유출할 수 있기 때문에 스크린숏은 첨부할 수 없지만 개인적으로는 만족하며 잘 사용 중이다.
AI가 요약해 주는 내용을 보고 무엇을 해결하고 무엇을 그대로 가져갈지에 대해서는 늘 고민할 부분이지만 스스로 놓칠 수 있는 부분을 한번 더 점검한다는 의미에서는 이만한 도구도 없는 듯하다.
아쉬운 점은 Pull Request Prompt를 더 개선시켜야 하는 부분이다. 계속 다른 형식으로 요약 결과를 내기 때문에 “일관성”이 떨어지는 것이 단점이다.
계속 수정을 시도해 보고 맞는 방법을 찾아가 보도록 하자.
Reference
'개발 노트' 카테고리의 다른 글
[Arduino] WeMos D1&R2 (0) | 2022.07.27 |
---|---|
MQTT, Message Queuing Telemetry Trasnport (0) | 2022.07.17 |
[Postman] Cookie header 자동 셋업 끄기 (0) | 2022.05.15 |
React && DJango 파일 업로드 (0) | 2020.12.14 |
DRF&React로 REST API 체험기 (0) | 2020.11.18 |