# **Git Bisect로 깨진 데이터베이스 마이그레이션을 빠르게 찾아내는 방법**

*(SEO 키워드: 데이터베이스 마이그레이션, git bisect, 버그 추적)*

---

# # 서론 – “왜 마이그레이션이 깨졌을까?”

프로젝트가 커지고 팀원이 늘어나면 **데이터베이스 마이그레이션** 파일도 점점 많아집니다. 어느 순간, 배포 후에 애플리케이션이 정상적으로 동작하지 않거나, 특정 컬럼이 누락돼 오류가 발생한다면 “어디서 문제가 생겼을까?” 하는 고민에 빠지게 됩니다.

특히 **초보 개발자**는 커밋 히스토리를 일일이 뒤져가며 원인을 찾는 것이 너무 힘들고, 시간도 많이 잡아먹습니다.

이때 강력한 도구가 바로 **git bisect** 입니다. Git bisect는 “좋은(bad) 커밋”과 “좋은(good) 커밋”을 지정하면, 이분 탐색을 통해 문제가 발생한 정확한 커밋을 자동으로 찾아줍니다. 이번 포스팅에서는 **git bisect**와 **데이터베이스 마이그레이션**을 결합해 깨진 마이그레이션을 손쉽게 추적하는 과정을 단계별로 설명합니다.

---

# # 1️⃣ 데이터베이스 마이그레이션 오류 이해하기

| 원인 | 설명 | 흔히 발생하는 상황 |

|------|------|-------------------|

| **스키마 불일치** | 모델 변경 후 마이그레이션 파일을 누락하거나 순서가 뒤바뀜 | 새로운 필드 추가 후 `rails db:migrate`를 실행하지 않음 |

| **의존성 충돌** | 이전 마이그레이션에서 만든 테이블/컬럼을 이후 마이그레이션이 가정 | 외래키 제약조건이 먼저 생성돼 오류 발생 |

| **환경 차이** | 로컬과 CI/프로덕션 DB 버전이 달라 호환성 문제 | PostgreSQL 12 vs 13에서 지원되지 않는 문법 사용 |

이러한 오류는 **버그 추적**이 어려운 이유가 바로 “어디서 어떤 파일이 잘못됐는가”를 정확히 알기 힘들기 때문입니다.

---

# # 2️⃣ Git Bisect 기본 사용법

1. **시작** – 현재 브랜치에서 bisect를 시작합니다.

   
```
bash

   git bisect start

   
```

2. **Bad 커밋 지정** – 문제가 있는 최신 커밋(배포된 커밋)을 지정합니다.

   
```
bash

   git bisect bad   # HEAD가 보통 bad

   
```

3. **Good 커밋 지정** – 마이그레이션이 정상적으로 작동하던 과거 커밋을 지정합니다.

   
```
bash

   git bisect good <good-commit-hash>

   
```

4. **자동 탐색** – Git이 중간 커밋을 체크아웃하고, 사용자는 “테스트”만 수행하면 됩니다.

   
```
bash

   # 테스트 스크립트 예시

   ./run_migration_test.sh && git bisect good || git bisect bad

   
```

5. **결과 확인** – 최종적으로 문제를 일으킨 커밋 해시가 출력됩니다.

   
```
bash

   git bisect reset   # bisect 종료

   
```

이 과정을 **스크립트화**하면 매번 수동으로 테스트할 필요가 없어집니다.

---

# # 3️⃣ Bisect와 마이그레이션 결합하기

## # 3.1 테스트 스크립트 만들기

```
bash

# !/bin/bash

# 파일명: test_migration.sh

set -e

# 1️⃣ DB 초기화 (SQLite 예시)

rm -f db.sqlite3

python manage.py migrate --noinput   # Django 예시

# 2️⃣ 마이그레이션 실행 후 검증

if python manage.py migrate; then

  # 컬럼/테이블 존재 여부 확인 (예: users 테이블에 email 컬럼)

  if python -c 'import sqlite3; conn=sqlite3.connect('db.sqlite3'); \

                cur=conn.cursor(); cur.execute('PRAGMA table_info(users)'); \

                cols=[c[1] for c in cur.fetchall()]; \

                exit(0) if 'email' in cols else exit(1)'; then

    exit 0   # 테스트 PASS → good

  else

    exit 1   # 컬럼 누락 → bad

  fi

else

  exit 1   # 마이그레이션 자체 오류 → bad

fi

```

위 스크립트는 **데이터베이스 마이그레이션**을 새로 적용하고, 특정 컬럼이 존재하는지 확인합니다. `git bisect run ./test_migration.sh` 명령만으로 자동으로 good/bad을 판정할 수 있습니다.

## # 3.2 실제 실행 흐름

```
bash

git bisect start

git bisect bad               # 현재 배포된 커밋

git bisect good v1.2.0       # 정상 작동하던 태그

git bisect run ./test_migration.sh

```

Git bisect는 테스트가 통과(good)인지 실패(bad)인지에 따라 자동으로 다음 커밋을 선택합니다. 평균적으로 **log₂(N)** 번만 확인하면 되므로, 200개의 마이그레이션이라도 8번 정도만 실행하면 원인을 찾을 수 있습니다.

---

# # 4️⃣ 실전 예시 – “회원가입 페이지에서 이메일 컬럼이 사라졌다”

1. **문제 상황**

   - 배포 후 회원가입 폼에서 `email` 입력값이 DB에 저장되지 않음.

   - 로그에 “column email does not exist” 에러가 남음.

2. **Bisect 초기화**

   
```
bash

   git bisect start

   git bisect bad          # 현재 HEAD

   git bisect good v2.4.5  # v2.4.5까지는 정상

   
```

3. **테스트 스크립트 적용**

   위에서 만든 `test_migration.sh`를 프로젝트 루트에 두고 실행:

   
```
bash

   git bisect run ./test_migration.sh

   
```

4. **결과**

   - `git bisect`는 `abcd1234` 커밋을 “첫 번째 bad”으로 지정.

   - 해당 커밋을 열어보니 **마이그레이션 파일 2023_09_12_add_email_to_users.rb**에서 `add_column :users, :email, :string, null: false` 라인을 **주석 처리**한 흔적 발견.

5. **해결**

   - 주석을 복구하고 새로운 마이그레이션을 생성해 `email` 컬럼을 재추가.

   - `git bisect reset` 후 정상 배포 확인.

이처럼 **git bisect**와 간단한 검증 스크립트를 결합하면, 복잡한 마이그레이션 히스토리에서도 몇 번의 클릭만으로 문제 커밋을 pinpoint 할 수 있습니다.

---

# # 5️⃣ 마무리 – 지금 바로 적용해 보세요!

- **데이터베이스 마이그레이션** 오류는 눈에 띄지 않는 작은 실수에서 시작됩니다.

- **git bisect**는 이러한 실수를 빠르게 찾아내는 최고의 도구이며, 자동화 스크립트와 결합하면 초보자도 손쉽게 사용할 수 있습니다.

- 오늘 소개한 `test_migration.sh`와 같은 **버그 추적** 스크립트를 프로젝트에 추가하고, 문제가 발생했을 때 바로 bisect를 실행해 보세요.

> **행동 유도**

> 1️⃣ 프로젝트 루트에 테스트 스크립트를 하나 만들어 보세요.

> 2️⃣ `git bisect start …` 명령으로 첫 번째 bisect를 실행해 보세요.

> 3️⃣ 문제를 찾은 뒤, PR을 열어 팀과 공유하고 `git bisect reset`을 잊지 마세요!

지금 바로 **git bisect**를 활용해 깨진 마이그레이션을 잡아내고, 배포 안정성을 한 단계 끌어올리세요.

---

*※ 본 글은 Reddit의 “Finding broken migrations with Bisect” 스레드(https://reddit.com/r/programming/comments/1pjvtlv/finding_broken_migrations_with_bisect/)를 참고하여 작성되었습니다.*
