@extends('layouts.app') @section('title', 'Git 정책') @push('styles') @endpush @section('content')
{{-- ============================================================ --}} {{-- 히어로 배너 --}} {{-- ============================================================ --}}
아카데미 Git 정책

Git 정책

버전 관리의 기초부터 SAM 프로젝트 Git 정책까지 — 비개발자도 이해하는 Git 가이드

버전 관리의 필요성
{{-- ============================================================ --}} {{-- 좌측 고정 목차 (TOC) --}} {{-- ============================================================ --}} {{-- ============================================================ --}} {{-- 우측 콘텐츠 --}} {{-- ============================================================ --}}
{{-- 모바일 목차 --}} {{-- ============================================================ --}} {{-- 1. 버전 관리란? --}} {{-- ============================================================ --}}

1 버전 관리란?

파일 혼돈의 시대 ?버전 관리 시스템(VCS)이 없던 시절, 대부분의 팀은 파일명에 날짜나 버전 번호를 붙여 관리했다. 이 방식은 파일이 늘어날수록 어떤 것이 최신인지 알 수 없게 된다.

비유: 견적서_최종_진짜최종.xlsx의 악몽

엑셀 파일을 수정할 때마다 "견적서_수정.xlsx", "견적서_최종.xlsx", "견적서_최종_수정.xlsx", "견적서_진짜최종_v3.xlsx"... 이렇게 파일이 불어난 경험이 있을 것이다. 어느 것이 진짜 최종인지 아무도 모른다. Git은 이 악몽을 완전히 해결한다.

버전 관리란 파일의 변경 이력을 체계적으로 기록하고 관리하는 것이다. 누가, 언제, 무엇을, 왜 변경했는지를 자동으로 추적하며, 필요하면 과거의 어떤 시점으로든 되돌릴 수 있다.

Git이 해결하는 3가지 문제

1. 이력 추적

모든 변경이 기록된다.
누가, 언제, 왜 바꿨는지
언제든 확인 가능.

2. 동시 작업

여러 사람이 같은 파일을
동시에 수정해도
안전하게 합칠 수 있다.

3. 되돌리기

실수해도 과거 시점으로
자유롭게 복원 가능.
파일이 깨질 걱정 없음.

Git vs 클라우드 동기화: Google Drive나 OneDrive도 파일 이력을 보여주지만, Git과는 근본적으로 다르다. 클라우드는 자동 저장이지만, Git은 의미 있는 단위로 직접 기록한다. "견적 금액 10% 인상 반영"처럼 변경 이유까지 남길 수 있다.

버전 관리의 필요성

버전 관리 전후 비교 — 파일명 혼돈 vs Git 타임라인

{{-- ============================================================ --}} {{-- 2. Git 기초 개념 --}} {{-- ============================================================ --}}

2 Git 기초 개념

Git의 3단계 구조 ?Git은 파일을 3개 영역으로 관리한다. Working Directory(작업 공간), Staging Area(준비 영역), Repository(저장소). 각 영역의 역할을 이해하면 Git의 핵심을 파악한 것이다.

비유: 책상 → 봉투 → 캐비닛

Working Directory는 작업 중인 책상이다. 파일을 자유롭게 수정한다. Staging Area는 보낼 서류를 담는 봉투다. git add로 봉투에 넣는다. Repository는 최종 보관하는 캐비닛이다. git commit으로 캐비닛에 저장한다.

# 1. 책상에서 파일 수정 (Working Directory) 파일을 수정한다 # 2. 봉투에 넣기 (Staging Area) git add 파일이름.php # 3. 캐비닛에 보관 (Repository) git commit -m "feat: [order] 주문 기능 추가"
Git 3단계 구조

Git 3단계 — Working Directory → Staging → Repository

커밋과 해시

Commit은 특정 시점의 스냅샷이다. 각 커밋에는 커밋 해시라는 고유 ID가 자동 부여된다. 예: a1b2c3d. 이 해시로 어떤 커밋이든 정확히 찾아갈 수 있다.

명령어 역할 비유
git status 현재 상태 확인 책상 위 정리 상태 확인
git add 스테이징에 추가 서류를 봉투에 넣기
git commit 변경 기록 저장 봉투를 캐비닛에 보관
git log 커밋 이력 조회 캐비닛 보관 목록 열람
git diff 변경 내용 비교 수정 전후 대조
{{-- ============================================================ --}} {{-- 3. 원격 저장소와 클론 --}} {{-- ============================================================ --}}

3 원격 저장소와 클론

Push와 Pull ?원격 저장소(Remote)는 팀원 모두가 접근할 수 있는 중앙 서버에 있는 저장소다. GitHub, GitLab, Gitea 등이 원격 저장소 서비스를 제공한다.

비유: 팀 공용 캐비닛

로컬 저장소가 내 책상의 캐비닛이라면, 원격 저장소는 팀 공용 캐비닛이다. Push는 내 서류를 공용 캐비닛에 올리는 것이고, Pull은 다른 사람이 올린 서류를 내 책상으로 가져오는 것이다.

# 내 작업을 원격에 업로드 git push origin develop # 원격의 최신 변경을 가져오기 git pull origin develop
원격 저장소

원격 저장소 — 로컬 ↔ 중앙 서버 동기화

Clone과 Origin

Clone은 원격 저장소를 통째로 내 PC에 복사하는 것이다. 프로젝트에 처음 참여할 때 한 번만 실행한다. Clone하면 원격 저장소에 자동으로 Origin이라는 이름이 붙는다.

# 프로젝트 처음 참여 시 — 전체 복사 git clone https://gitea.example.com/sam/mng.git # 이후에는 pull로 최신 변경만 동기화 git pull

SAM의 원격 저장소: SAM은 자체 호스팅 Gitea 서버를 사용한다. GitHub처럼 웹 브라우저에서 코드를 보고, PR을 만들고, 이슈를 관리할 수 있다.

{{-- ============================================================ --}} {{-- 4. 브랜치 --}} {{-- ============================================================ --}}

4 브랜치

브랜치란? ?브랜치(Branch)는 '가지'라는 뜻이다. 나무 줄기(main)에서 가지가 뻗어나가듯, 메인 코드에서 분기하여 독립적으로 작업한 뒤 다시 합친다.

비유: 생산라인 분기점

공장의 메인 생산라인(main)에서 시험 생산라인을 따로 만들어 새 제품을 테스트하는 것이다. 테스트가 성공하면 메인 라인에 합류시키고(merge), 실패하면 시험 라인만 폐쇄하면 된다. 메인 라인은 영향 없이 계속 가동된다.

브랜치 역할 예시
main 운영 서버에 배포된 안정 코드 실제 서비스 중인 코드
develop 개발 통합 브랜치 다음 릴리즈 준비 코드
feature/* 새 기능 개발 feature/file-upload
hotfix/* 긴급 버그 수정 hotfix/login-session-bug
브랜치 전략

브랜치 전략 — main / develop / feature / hotfix

브랜치 만들기와 머지

# 새 기능 브랜치 만들기 git checkout -b feature/file-upload # 작업 후 커밋 git add . git commit -m "feat: [file] 파일 업로드 기능 추가" # develop 브랜치로 돌아와서 머지 git checkout develop git merge feature/file-upload

Merge는 분기된 작업을 다시 하나로 합치는 것이다. feature 브랜치에서 개발을 완료하면 develop에 merge하고, develop이 안정화되면 main에 merge한다.

{{-- ============================================================ --}} {{-- 5. 커밋 메시지 작성법 --}} {{-- ============================================================ --}}

5 커밋 메시지 작성법

SAM 커밋 메시지 컨벤션 ?커밋 메시지 컨벤션이란 팀 전체가 동일한 형식으로 커밋 메시지를 작성하는 약속이다. 통일된 형식은 이력 검색과 코드 리뷰를 빠르게 만든다.

비유: 작업 일지

커밋 메시지는 공장의 작업 일지다. "작업함"이라고 적으면 나중에 아무도 내용을 알 수 없다. "셔터 A라인 모터 교체 완료 — 소음 문제 해결"처럼 구체적으로 적어야 한다.

SAM 프로젝트 커밋 메시지 형식:

type: [scope] 작업 내용 - 세부 항목 (선택) - 세부 항목 2
커밋 메시지

좋은 커밋 메시지 vs 나쁜 커밋 메시지

7가지 커밋 타입

타입 설명 예시
feat 새로운 기능 추가 feat: [file] 파일 업로드 기능 추가
fix 버그 수정 fix: [auth] 세션 만료 오류 수정
refactor 코드 구조 개선 refactor: [user] 서비스 메서드 분리
docs 문서 변경 docs: API 문서 업데이트
chore 설정/빌드 변경 chore: composer 패키지 업데이트
style 코드 스타일 수정 style: Pint 포맷팅 적용
test 테스트 추가/수정 test: Product API 테스트 추가

fix = 깨진 것을 고친다

버그, 오류, 잘못된 결과

feat = 없던 것을 만든다

신규 기능, 기능 확장

refactor = 같은 것을 더 좋게

구조 개선, 중복 제거

커밋 빈도: "논리적 단위"로 커밋한다. 파일 하나 수정마다 커밋하는 것은 너무 잦고, 몇 시간 작업을 한 번에 커밋하면 되돌리기 어렵다. 하나의 의미 있는 변경이 완성되면 커밋한다.

{{-- ============================================================ --}} {{-- 6. 협업 워크플로우 --}} {{-- ============================================================ --}}

6 협업 워크플로우

Pull Request와 코드 리뷰 ?Pull Request(PR)란 내가 만든 변경 사항을 팀 브랜치에 합쳐달라고 요청하는 것이다. 다른 개발자가 코드를 검토(리뷰)한 후 승인하면 머지된다.

비유: 품질검사 신청서

Pull Request품질검사 신청서다. 생산라인에서 만든 제품을 바로 출하하지 않고, 품질검사 부서에 "검사해주세요"라고 신청한다. 검사관(리뷰어)이 확인하고 "합격"을 주면 출하(merge)된다.

PR 워크플로우

PR 워크플로우 — 브랜치 → 커밋 → PR → 리뷰 → 머지

팀 워크플로우

SAM 프로젝트의 일반적인 작업 흐름:

1 develop에서 feature 브랜치를 만든다
2 기능을 개발하고 커밋한다
3 Pull Request를 생성하여 코드 리뷰를 요청한다
4 리뷰 승인 후 develop에 머지한다
5 develop이 안정되면 main에 머지하고 배포한다
# 1. 브랜치 생성 git checkout -b feature/file-storage-system # 2. 작업 및 커밋 git add . git commit -m "feat: [file] 파일 저장 시스템 구현" # 3. 원격에 푸시 후 PR 생성 git push origin feature/file-storage-system # → Gitea에서 PR 생성
{{-- ============================================================ --}} {{-- 7. 충돌 해결 --}} {{-- ============================================================ --}}

7 충돌 해결

충돌이란? ?충돌(Conflict)은 두 사람이 같은 파일의 같은 줄을 다르게 수정했을 때 발생한다. Git이 어떤 변경을 채택해야 할지 모르기 때문에 사람이 직접 선택해야 한다.

비유: 공동 엑셀 편집

A씨와 B씨가 같은 엑셀 파일의 같은 셀을 동시에 다른 값으로 수정한 상황이다. A씨는 "100,000"으로, B씨는 "150,000"으로 바꿨다. 누구 것을 쓸지는 사람이 판단해야 한다.

// 충돌 마커 — Git이 파일에 표시해주는 형태 <<<<<<< HEAD $price = 100000; // 내가 수정한 내용 ======= $price = 150000; // 상대방이 수정한 내용 >>>>>>> feature/price-update
충돌 해결

머지 충돌 — 두 브랜치가 같은 부분을 수정했을 때

충돌 해결 3단계

1단계: 충돌 파일 확인

git status로 "both modified" 표시된 파일을 찾는다.

2단계: 내용 선택

에디터에서 <<<<<<<, =======, >>>>>>> 마커를 찾고 원하는 내용만 남긴다.

3단계: 커밋

git add로 해결된 파일을 추가하고 git commit으로 머지를 완료한다.

{{-- ============================================================ --}} {{-- 8. SAM 프로젝트 Git 정책 --}} {{-- ============================================================ --}}

8 SAM 프로젝트 Git 정책

3개 독립 저장소 ?SAM은 멀티레포 전략을 사용한다. 하나의 거대한 저장소(모노레포) 대신, 역할별로 분리된 3개 저장소를 운영하여 각 팀이 독립적으로 작업할 수 있다.

비유: 공장 3개 부서

SAM의 3개 저장소는 공장의 3개 독립 부서와 같다. MNG(관리부)는 관리자 화면, API(생산부)는 데이터 처리, React(영업부)는 고객용 화면을 담당한다. 각 부서는 독립적으로 작업하지만, 하나의 공장(DB)을 공유한다.

저장소 경로 역할
mng /home/aweso/sam/mng 관리자 웹 (Laravel + Blade)
api /home/aweso/sam/api API 서버 (Laravel)
react /home/aweso/sam/react 프론트엔드 (Next.js)
SAM 멀티레포

SAM 멀티레포 구조 — mng / api / react

# 각 저장소에서 개별 커밋 (중요!) cd /home/aweso/sam/mng git add . && git commit -m "feat: [order] 주문 화면 추가" cd /home/aweso/sam/api git add . && git commit -m "feat: [order] 주문 API 추가"

푸시 정책과 Pre-commit

푸시 정책

  • - main/master에서 직접 작업 금지
  • - develop 브랜치를 기본으로 사용
  • - 사용자(팀장)가 수동으로 push
  • - Claude는 커밋까지만 수행

Pre-commit Hook

  • - 커밋 전 Pint 자동 실행
  • - 코드 포맷팅 자동 정리
  • - Claude 서명 자동 제거
  • - 포맷 오류 시 커밋 차단

커밋 전 체크리스트: ./vendor/bin/pint 실행 → git diff로 변경 검토 → 불필요 파일(.env 등) 제외 → git addgit commit

{{-- ============================================================ --}} {{-- 9. .gitignore와 보안 --}} {{-- ============================================================ --}}

9 .gitignore와 보안

.gitignore란? ?.gitignore는 Git이 추적하지 않을 파일 목록이다. 여기에 등록된 파일은 git add 해도 스테이징되지 않는다. 비밀번호, 대용량 파일, OS 임시 파일 등을 제외할 때 사용한다.

비유: 캐비닛 반입금지 목록

.gitignore는 캐비닛(저장소)에 넣으면 안 되는 물건 목록이다. 비밀문서(비밀번호), 임시 메모(로그 파일), 개인 물건(IDE 설정) 등은 공용 캐비닛에 넣지 않는다.

# SAM .gitignore 주요 항목 # 환경 설정 (비밀번호 포함) .env .env.* !.env.example # 양식만 추적 # 외부 패키지 (용량 큼) /vendor/ /node_modules/ # IDE 설정 (개인별 다름) .idea/ .vscode/ .cursor/ # 로그, 백업, 바이너리 *.log *.sql *.zip
.gitignore 보안

.gitignore — 민감 파일을 저장소에서 차단하는 방패

.env 파일 보안

절대 금지: .env 파일을 Git에 커밋

.env 파일에는 데이터베이스 비밀번호, API 키, 암호화 키가 들어 있다. 이 파일이 Git에 올라가면 모든 이력에 비밀번호가 남게 되어 삭제해도 이력에서 복구할 수 있다. 한 번 유출되면 모든 비밀번호를 교체해야 한다.

Git에 올리면 안 되는 파일

.env, credentials.json, *.key
storage/secrets/, auth.json

Git에 올려야 하는 파일

.env.example (양식만, 값은 비움)
.gitignore, .gitattributes

{{-- ============================================================ --}} {{-- 10. 배포와 CI/CD --}} {{-- ============================================================ --}}

10 배포와 CI/CD

Git 기반 배포 ?CI/CD는 코드 변경 시 자동으로 빌드→테스트→배포하는 자동화 파이프라인이다. CI(Continuous Integration)는 코드 통합, CD(Continuous Deployment)는 자동 배포를 뜻한다.

비유: 자동화 컨베이어 벨트

CI/CD는 공장의 자동화 컨베이어 벨트다. 원재료(코드)를 올려놓으면 가공(빌드) → 품질검사(테스트) → 포장(패키징) → 출하(배포)가 자동으로 진행된다. 사람이 각 단계를 직접 실행할 필요가 없다.

SAM의 배포 흐름:

1 개발자가 코드 작성 후 git commit
2 팀장이 git push로 원격 저장소에 업로드
3 서버에서 git pull로 최신 코드 받기
4 composer install → migrate → config:clear
5 서비스 정상 동작 확인
CI/CD 파이프라인

CI/CD 파이프라인 — 코드에서 배포까지의 자동화 흐름

롤백: revert vs reset

배포 후 문제가 발생하면 이전 버전으로 되돌려야 한다. Git에서는 두 가지 방법이 있다.

Revert (권장)

  • - 되돌리는 새 커밋을 생성
  • - 이력이 보존되어 안전
  • - 팀 작업에 영향 없음
  • - git revert <해시>

Reset (주의)

  • - 커밋 이력 자체를 삭제
  • - 되돌린 기록이 남지 않음
  • - 팀 작업에 혼란 가능
  • - 로컬에서만 사용 권장
# 안전한 롤백 — revert (권장) git revert a1b2c3d # 해당 커밋을 되돌리는 새 커밋 생성 # 위험한 롤백 — reset (주의!) git reset --soft HEAD~1 # 직전 커밋 취소 (변경은 유지) git reset --hard HEAD~1 # 직전 커밋 + 변경 모두 삭제 (위험!)

SAM 배포 참고: SAM에서는 React(Next.js) 빌드를 서버에서 실행하지 않는다. 서버 스펙(2코어, 3.8GB RAM)으로는 빌드 시 메모리 부족이 발생하므로, 반드시 로컬에서 빌드 후 결과물만 배포한다.

@include('components.academy-glossary', ['domain' => 'git-policy']) @endsection