---
title: "GitLab 마이그레이션: PostgreSQL 업그레이드와 서버 이전을 위한 종합 가이드"
description: "GitLab을 OpenStack으로 이전하며 PostgreSQL을 15에서 16으로 업그레이드하는 과정에서 GitLab 백업, PostgreSQL 백업 및 복원, GitLab 복구 및 업그레이드 절차를 다룬다. CI/CD를 차단하고, "
date: "2025-06-05"
last_modified: "2026-05-15T08:36:00.000Z"
type: "Post"
tags:
  - "gitlab"
  - "postgresql"
  - "migration"
  - "docker"
  - "openstack"
  - "CI/CD"
  - "troubleshooting"
categories:
  - "📗 Docs"
canonical_url: "https://blog.pieroot.xyz/gitlab-postgres-migration"
markdown_url: "https://blog.pieroot.xyz/gitlab-postgres-migration.md"
---

# GitLab 마이그레이션: PostgreSQL 업그레이드와 서버 이전을 위한 종합 가이드

GitLab을 OpenStack으로 이전하며 PostgreSQL을 15에서 16으로 업그레이드하는 과정에서 GitLab 백업, PostgreSQL 백업 및 복원, GitLab 복구 및 업그레이드 절차를 다룬다. CI/CD를 차단하고, 

## 준비

GitLab을 원래 물리 서버에서 OpenStack 안으로 이전하면서 마이그레이션을 진행해야 했다.

공식문서를 따라하지 않고 그냥 내 맘대로 했다가 여러 가지 시행착오를 겪어서 나중을 위해 정리한다…

우선 GitLab 서버의 버전을 보다 쉽게 관리하기 위해 우리는 docker compose를 사용해서 관리하고 있다.

이번에 GitLab에서 변경사항이 몇 가지 있다.

1. **17 → 18**로 업그레이드

1. 18로 업그레이드하면서 **PostgreSQL 15 → 16**으로 업그레이드

1. GitLab을 기존 **물리머신에서 OpenStack 인스턴스**로 이전

위 3가지를 수행해야 한다.

> **이 글에서 다루는 내용**
> 
> - GitLab 데이터(레포, 아티팩트 등) 백업
> 
> - PostgreSQL 15 → 16 덤프 & 복원을 통한 업그레이드
> 
> - 새 서버에서 GitLab 복구 및 버전 업그레이드
> 
> - 삽질 과정에서 얻은 트러블슈팅 팁

> **GitLab 18.0부터 PostgreSQL 16이 최소 요구 버전이다.** GitLab 17.11에서는 자동 업그레이드를 시도하지만, 우리처럼 외부 PostgreSQL을 사용하는 경우 수동으로 업그레이드해야 한다.

[Back up and restore overview \| GitLab Docs](https://docs.gitlab.com/administration/backup_restore/)

위 공식 문서를 보고 따라한다면 좋겠지만 원래 자료 조사라는 게 참 귀찮고 원하는 정보를 얻는 게 힘든 법이니 ~~스근하이~~ 정리를 하려 한다.

## 시작

---

보통 Docker를 사용해서 서비스를 유지 관리할 때 Docker에서 사용하는 볼륨을 잘 보관해서 다른 곳으로 옮기면 알아서 동작하겠거니 하는 기대를 할 수 있다.

나도 당연히 그렇게 생각했고 그렇게 옮겨봤는데 **당연하게도 실패했다.**

여기서 발생하는 원인이 첫째로는 PostgreSQL이 내부 데이터만 옮긴다고 정상 동작하지 않는다는 점과, GitLab의 볼륨이 옮겨지면 **무결성이 깨진다**는 게 문제다.

> PostgreSQL은 메이저 버전 간에 **내부 데이터 저장 형식이 호환되지 않는다.** 따라서 15에서 16으로 올릴 때 단순히 data 디렉토리를 복사하는 것만으로는 절대 안 된다. 반드시 `pg_dump`로 논리적 백업을 하고, 새 버전에서 `psql`이나 `pg_restore`로 복원해야 한다.

그래서 우리가 해야 할 것은 크게 3가지가 될 것이다.

1. **GitLab 백업** (레포, 아티팩트, 시크릿 등)

1. **PostgreSQL 백업 및 업그레이드** (15 → 16)

1. **GitLab 복구 및 버전 업그레이드** (17 → 18)

### 🔒 GitLab 백업

여기서 주의할 게 있다.

우선 GitLab에 새로운 CI/CD가 동작하지 않도록 설정해야 한다. 마이그레이션 중에 새로운 파이프라인이 돌면 데이터 정합성이 깨질 수 있기 때문이다.

```shell
nginx['custom_gitlab_server_config'] = "location = /api/v4/jobs/request {\n    deny all;\n    return 503;\n  }\n"
```

위 설정값을 `gitlab.rb`에 넣거나 docker compose의 경우 환경변수를 갱신한 후 GitLab을 재설정한다.

```shell
sudo gitlab-ctl reconfigure

# or

docker compose restart gitlab # 재시작이 권장되진 않지만 뭐 이렇게도 동작은 하는걸~ 
```

> **마이그레이션 전 반드시 CI/CD를 차단하자.** 백업 중에 새로운 Job이 돌아가면 백업 파일과 실제 데이터 간 불일치가 발생할 수 있다. Runner도 일시적으로 중지하는 것을 권장한다.

우리 환경은 GitLab 외부에 PostgreSQL이 빠져있어서 PostgreSQL은 별도로 백업을 해야 한다.

```shell
docker compose exec <container name> gitlab-backup create
```

docker compose로 올려두었기에 위 명령어로 백업파일을 만들면 된다.

하지만 PostgreSQL은 외부에 분리되어 있으므로 배제해야 하기에

```shell
docker compose exec <container name> gitlab-backup create SKIP=db
```

위와 같이 실행하면 된다.

```shell
2025-06-23 07:13:34 UTC -- Dumping database ... [SKIPPED]
2025-06-23 07:21:50 UTC -- Dumping repositories ... done
2025-06-23 07:21:50 UTC -- Dumping uploads ... done
2025-06-23 07:21:50 UTC -- Dumping builds ... done
2025-06-23 07:21:54 UTC -- Dumping artifacts ... done
2025-06-23 07:21:54 UTC -- Dumping pages ... done
2025-06-23 07:22:17 UTC -- Dumping lfs objects ... done
2025-06-23 07:22:17 UTC -- Dumping terraform states ... done 
2025-06-23 07:22:17 UTC -- Dumping container registry images ... done
2025-06-23 07:22:17 UTC -- Dumping packages ... done
2025-06-23 07:22:17 UTC -- Dumping ci secure files ... done
2025-06-23 07:22:17 UTC -- Dumping external diffs ... done
2025-06-23 07:37:14 UTC -- Creating backup archive: 1750662814_2025_06_23_18.1.0_gitlab_backup.tar ... done
2025-06-23 07:37:14 UTC -- Uploading backup archive to remote storage  ... [SKIPPED]
2025-06-23 07:37:14 UTC -- Deleting old backups ... [SKIPPED]
2025-06-23 07:37:14 UTC -- Deleting tar staging files ...
2025-06-23 07:37:14 UTC -- Cleaning up /var/opt/gitlab/backups/backup_information.yml
2025-06-23 07:37:14 UTC -- Cleaning up /var/opt/gitlab/backups/repositories
2025-06-23 07:37:15 UTC -- Cleaning up /var/opt/gitlab/backups/uploads.tar.gz
2025-06-23 07:37:15 UTC -- Cleaning up /var/opt/gitlab/backups/builds.tar.gz
2025-06-23 07:37:15 UTC -- Cleaning up /var/opt/gitlab/backups/artifacts.tar.gz
2025-06-23 07:37:15 UTC -- Cleaning up /var/opt/gitlab/backups/pages.tar.gz
2025-06-23 07:37:15 UTC -- Cleaning up /var/opt/gitlab/backups/lfs.tar.gz
2025-06-23 07:37:15 UTC -- Cleaning up /var/opt/gitlab/backups/terraform_state.tar.gz
2025-06-23 07:37:15 UTC -- Cleaning up /var/opt/gitlab/backups/registry.tar.gz
2025-06-23 07:37:15 UTC -- Cleaning up /var/opt/gitlab/backups/packages.tar.gz
2025-06-23 07:37:15 UTC -- Cleaning up /var/opt/gitlab/backups/ci_secure_files.tar.gz
2025-06-23 07:37:15 UTC -- Cleaning up /var/opt/gitlab/backups/external_diffs.tar.gz
2025-06-23 07:37:15 UTC -- Deleting tar staging files ... done
2025-06-23 07:37:15 UTC -- Deleting backups/tmp ... done
2025-06-23 07:37:15 UTC -- Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data 
and are not included in this backup. You will need these files to restore a backup.
Please back them up manually.                          
2025-06-23 07:37:15 UTC -- Backup 1750662814_2025_06_23_18.1.0 is done.
2025-06-23 07:37:15 UTC -- Deleting backup and restore PID file at [/opt/gitlab/embedded/service/gitlab-rails/tmp/backup_restore.pid] ... done
```
*백업 과정 출력*

그러면 컨테이너 안의 기준으로 `/var/opt/gitlab/backups` 안에 backup 파일이 시간과 버전별로 백업이 생성된다.

![image](https://blog.pieroot.xyz/api/image-proxy?id=c46a69cc-bad9-42a2-abc0-ea98dfae97bc&kind=s3&pageId=30d067c0-15d0-8038-b335-dced932e88d2&source=block&blockId=30d067c0-15d0-80e2-bf15-d55bdd89e486)

생성된 파일을 호스트 머신으로 추출해야 한다.

```shell
mkdir ./gitlab-backups
docker compose cp <container name>:/var/opt/gitlab/backups/* ./gitlab-backups/
```

GitLab의 백업들은 모두 되었다.

![image](https://blog.pieroot.xyz/api/image-proxy?id=3aa0274b-2978-448c-b38a-6177106fa0b7&kind=s3&pageId=30d067c0-15d0-8038-b335-dced932e88d2&source=block&blockId=30d067c0-15d0-8042-b525-f343c8a701db)

우리는 S3도 사용 중인데 PostgreSQL과 달리 S3는 애초부터 외부에 격리가 되어있기도 하고, GitLab에서 백업 시 건드리지 않기에 넘어간다.

그리고 새로 GitLab을 이전할 때 **시크릿 파일들을 반드시 백업**해야 한다.

시크릿 파일에는 내부 패스워드들과 SSH 호스트키들이 포함된다.

```shell
docker compose cp <container name>:/etc/gitlab/gitlab-secrets.json ./gitlab-backups/
docker compose cp -r <container name>:/etc/gitlab/ssl ./gitlab-backups/ # 우린 ssl 을 외부(nginx, haproxy)에서 연결하고 있어서 백업 안해도 무관하다.
docker compose cp <container name>:/etc/gitlab/trusted-certs ./gitlab-backups/ # ssh url 이 바뀔 예정이라 백업 안해도 무관하다.
```

시크릿 파일 말고 SSL 파일은 사실 동일한 URL을 사용해서 동작할 때 동일한 URL이 다른 키파일로 인증하면 중간자 공격으로 의심해서 그걸 방지하고자 넘기는 거지만 URL을 바꿀 거라면 그냥 무시해도 된다.

> **`gitlab-secrets.json`****은 절대 빠뜨리지 말 것!** 이 파일이 없으면 복구 시 2FA(이중 인증), CI/CD 변수 암호화 키, 데이터베이스 암호화 키 등을 모두 잃게 된다. 사실상 복구가 불가능해진다.

백업한 파일들의 목록은 아래와 같을 것이다.

> > ./gitlab-backups/
> > 	\| 
> > 	\|-- /gitlab-secrets.json
> > 	\|-- /\<TIMESTAMP\>\_\<VERSION\>\_gitlab\_backup.tar
> > 	\|-- /ssl/
> > 	\|-- /trusted-certs

### 🗄️ PostgreSQL 백업

GitLab의 백업이 끝났다면 GitLab을 종료하고 PostgreSQL을 백업할 순서이다.

```shell
docker compose down gitlab
```

GitLab에서 기본적으로 사용하는 PostgreSQL의 DB 이름은 `gitlabhq_production`이다.

#### pg\_dump vs pg\_dumpall

여기서 선택지가 두 가지 있다.

보통 사용자에 대한 정보가 DB 객체(role, permission)로 관리되기 때문에 `pg_dump`만 하면 사용자 정보가 빠질 수 있다. 서버 전체를 이전하는 우리 상황에서는 **`pg_dumpall`****을 사용하는 것이 안전**하다.

```shell
# GitLab DB만 백업
docker compose exec \
  <postgres name> pg_dump -U <postgres root user> \
  gitlabhq_production > gitlabhq_production.sql
  
# or

# 전체 백업 (역할, 권한 포함) - 권장
docker compose exec <postgres name> pg_dumpall -U <postgres root user> > dumpall.sql
```

이렇게 하면 Docker 내부에 있는 DB를 호스트 머신으로 바로 추출할 수 있다.

> **PostgreSQL의 ****`pg_dump`****는 구버전에서 덤프한 SQL을 신버전에서 복원하는 것을 공식적으로 지원한다.** 즉, PostgreSQL 15에서 `pg_dump`로 뽑은 SQL 파일을 PostgreSQL 16에서 `psql`로 밀어 넣으면 된다. 반대(신→구)는 보장되지 않으니 주의.

#### 덤프 파일 검증

덤프가 정상적으로 생성되었는지 간단히 확인한다.

```shell
# 파일 크기 확인 (0이면 문제가 있다)
ls -lh dumpall.sql

# 마지막 라인 확인 (정상이면 PostgreSQL dump complete 같은 메시지가 있다)
tail -5 dumpall.sql

# 테이블 수 확인
grep -c "CREATE TABLE" dumpall.sql
```

~~파일 크기가 0바이트인데 신나게 다음 단계로 넘어가는 실수는 하지 말자~~

---

### 🔄 PostgreSQL 16 신규 생성 후 복원

이제 새 서버에서 PostgreSQL 16 컨테이너를 올리고, 백업 파일을 복원할 차례다.

#### 새 PostgreSQL 16 컨테이너 준비

docker compose에서 PostgreSQL 이미지 버전을 16으로 변경한다.

```yaml
services:
  db:
    image: postgres:16
    environment:
      POSTGRES_USER: <postgres root user>
      POSTGRES_PASSWORD: <password>
      POSTGRES_DB: gitlabhq_production
    volumes:
      - ./postgres-data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
```

```shell
# 기존 데이터 디렉토리가 있다면 비워두거나 새로 생성
mkdir -p ./postgres-data-new

# PostgreSQL 16 컨테이너 시작
docker compose up -d db
```

#### 덤프 복원

PostgreSQL이 생성되었다면 이전에 백업파일로 받은 SQL 스크립트를 가져와서 복구를 시도한다.

```shell
# pg_dumpall 로 백업한 경우
docker compose exec -T db psql -U <postgres root user> < dumpall.sql

# or

# pg_dump 로 백업한 경우
docker compose exec -T db psql -U <postgres root user> -d gitlabhq_production < gitlabhq_production.sql
```

> **`pg_dump`****로 백업한 경우 주의사항**
> 
> `pg_dump`는 역할(role)을 포함하지 않기 때문에, GitLab에서 사용하는 DB 사용자를 미리 생성해줘야 한다.
> 
> ```javascript
> docker compose exec db psql -U <postgres root user> -c "CREATE ROLE gitlab WITH LOGIN PASSWORD '<password>';"
> ```
> 
> `pg_dumpall`을 사용했다면 역할 정보가 함께 포함되어 있으므로 이 과정은 필요 없다.

#### 복원 결과 확인

복원이 끝나면 데이터가 정상적으로 들어갔는지 확인한다.

```shell
# DB 목록 확인
docker compose exec db psql -U <postgres root user> -c "\l"

# gitlabhq_production 테이블 수 확인
docker compose exec db psql -U <postgres root user> -d gitlabhq_production -c "SELECT count(*) FROM information_schema.tables WHERE table_schema = 'public';"

# 주요 테이블 데이터 확인
docker compose exec db psql -U <postgres root user> -d gitlabhq_production -c "SELECT count(*) FROM users;"
docker compose exec db psql -U <postgres root user> -d gitlabhq_production -c "SELECT count(*) FROM projects;"
```

테이블 수가 기존과 동일하고, `users`와 `projects` 등 주요 테이블에 데이터가 있으면 성공이다.

---

### 🚀 GitLab 복구

PostgreSQL이 준비되었으니 이제 GitLab을 복구한다.

#### 새 서버에 GitLab 컨테이너 준비

새 서버에서 **기존과 동일한 버전(17.x)**의 GitLab 컨테이너를 먼저 올려야 한다.

> **반드시 백업 시점과 동일한 GitLab 버전으로 복구해야 한다!** 백업 파일명에 버전이 포함되어 있다 (`1750662814_2025_06_23_18.1.0_gitlab_backup.tar`에서 `18.1.0` 부분). 다른 버전으로 복구하면 마이그레이션 스크립트가 꼬여서 데이터가 날아갈 수 있다.

```yaml
services:
  gitlab:
    image: gitlab/gitlab-ce:17.x.x-ce.0  # 백업 시점의 버전과 동일하게!
    volumes:
      - ./gitlab-config:/etc/gitlab
      - ./gitlab-logs:/var/log/gitlab
      - ./gitlab-data:/var/opt/gitlab
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'https://gitlab.example.com'
        postgresql['enable'] = false
        gitlab_rails['db_adapter'] = 'postgresql'
        gitlab_rails['db_host'] = 'db'
        gitlab_rails['db_port'] = 5432
        gitlab_rails['db_username'] = '<postgres user>'
        gitlab_rails['db_password'] = '<password>'
        gitlab_rails['db_database'] = 'gitlabhq_production'
```

#### 시크릿 파일 복원

가장 먼저 시크릿 파일을 복원한다.

```shell
# 시크릿 파일 복사
docker compose cp ./gitlab-backups/gitlab-secrets.json gitlab:/etc/gitlab/gitlab-secrets.json

# GitLab 재설정
docker compose exec gitlab gitlab-ctl reconfigure
```

#### 백업 파일 복원

백업 파일을 GitLab 컨테이너 안으로 복사하고 복원한다.

```shell
# 백업 파일을 컨테이너로 복사
docker compose cp ./gitlab-backups/1750662814_2025_06_23_18.1.0_gitlab_backup.tar \
  gitlab:/var/opt/gitlab/backups/

# 파일 권한 설정 (이거 안 하면 복원 시 권한 오류 발생)
docker compose exec gitlab chown git:git /var/opt/gitlab/backups/1750662814_2025_06_23_18.1.0_gitlab_backup.tar
```

```shell
# GitLab 프로세스 중지 (DB 연결 관련 프로세스)
docker compose exec gitlab gitlab-ctl stop puma
docker compose exec gitlab gitlab-ctl stop sidekiq

# 프로세스 상태 확인
docker compose exec gitlab gitlab-ctl status
```

```shell
# 복원 실행 (SKIP=db 로 DB 복원 제외 - 이미 PostgreSQL에서 직접 복원했으므로)
docker compose exec gitlab gitlab-backup restore BACKUP=1750662814_2025_06_23_18.1.0 SKIP=db
```

> **복원 시 ****`SKIP=db`****를 넣는 이유**
> 
> 우리는 PostgreSQL을 별도로 `pg_dumpall` → `psql`로 이미 복원했다. GitLab의 backup restore가 DB를 다시 덮어쓰면 PostgreSQL 16에 맞게 복원한 데이터가 꼬일 수 있으므로 DB 복원은 스킵한다.

복원이 완료되면 GitLab을 재시작한다.

```shell
# GitLab 재시작
docker compose exec gitlab gitlab-ctl restart

# 또는 컨테이너 자체를 재시작
docker compose restart gitlab
```

---

### ⬆️ GitLab 18로 업그레이드

복구가 완료되었으면 이제 GitLab 17에서 18로 업그레이드한다.

> **GitLab 업그레이드는 반드시 순차적으로 진행해야 한다!** GitLab은 메이저 버전을 건너뛸 수 없다. 17 → 18로 올리려면 17의 마지막 마이너 버전(예: 17.11.x)을 거쳐야 한다. GitLab 공식 [Upgrade Path 도구](https://gitlab-com.gitlab.io/support/toolbox/upgrade-path/)를 사용해서 정확한 경로를 확인하자.

#### 업그레이드 절차

```shell
# 1. docker compose에서 GitLab 이미지 버전을 변경
# docker-compose.yml에서
# image: gitlab/gitlab-ce:17.x.x-ce.0
# → image: gitlab/gitlab-ce:18.x.x-ce.0

# 2. GitLab 컨테이너 재생성
docker compose up -d gitlab

# 3. 마이그레이션 로그 확인 (시간이 꽤 걸린다)
docker compose logs -f gitlab
```

업그레이드 중에 내부적으로 DB 마이그레이션이 돌아가면서 스키마가 업데이트된다. 로그에 `Migrated to ...` 메시지가 쭉 나오다가 최종적으로 GitLab이 정상 기동되면 성공이다.

#### 업그레이드 확인

```shell
# GitLab 버전 확인
docker compose exec gitlab gitlab-rake gitlab:env:info

# 또는 웹 브라우저에서
# https://gitlab.example.com/help 접속
```

---

### 🔧 트러블슈팅

마이그레이션 과정에서 만날 수 있는 문제들을 정리했다.

#### 복원 시 "permission denied" 에러

```shell
# 백업 파일 권한 문제
docker compose exec gitlab chown git:git /var/opt/gitlab/backups/*.tar

# /var/opt/gitlab/backups 디렉토리 권한도 확인
docker compose exec gitlab ls -la /var/opt/gitlab/backups/
```

~~파일 권한 문제로 1시간 삽질하는 건 리눅스 사용자의 통과의례다~~

#### PostgreSQL 복원 시 "role does not exist" 에러

`pg_dump`로 백업한 경우 역할 정보가 빠져있어서 발생한다.

```shell
# 필요한 역할 수동 생성
docker compose exec db psql -U <postgres root user> -c "CREATE ROLE gitlab WITH LOGIN PASSWORD '<password>';"
docker compose exec db psql -U <postgres root user> -c "ALTER ROLE gitlab CREATEDB;"
```

#### 복원 후 500 에러 발생

`gitlab-secrets.json`이 제대로 복원되지 않았을 가능성이 크다.

```shell
# 시크릿 파일 확인
docker compose exec gitlab cat /etc/gitlab/gitlab-secrets.json | head -20

# 재설정
docker compose exec gitlab gitlab-ctl reconfigure
docker compose exec gitlab gitlab-ctl restart
```

#### 업그레이드 후 마이그레이션 멈춤

```shell
# 백그라운드 마이그레이션 상태 확인
docker compose exec gitlab gitlab-rake db:migrate:status

# 마이그레이션이 멈춰있다면
docker compose exec gitlab gitlab-rake db:migrate
```

> **마이그레이션이 오래 걸리는 건 정상이다.** 특히 메이저 버전 업그레이드 시 스키마 변경이 많아서 데이터 양에 따라 수십 분에서 수 시간까지 걸릴 수 있다. 로그가 계속 찍히고 있다면 참을성 있게 기다리자.

---

### ✅ 핵심 정리

✅ **GitLab 백업**: `gitlab-backup create SKIP=db`로 레포/아티팩트 백업, `gitlab-secrets.json`은 별도 백업

✅ **PostgreSQL 백업**: `pg_dumpall`로 역할 포함 전체 백업 권장, 덤프 파일 검증 필수

✅ **PostgreSQL 업그레이드**: pg\_dump의 SQL은 구버전→신버전 복원을 공식 지원, 15에서 뽑은 SQL을 16에 바로 복원 가능

✅ **GitLab 복구**: 반드시 백업 시점과 **동일한 버전**으로 먼저 복구, 그 다음 순차적으로 업그레이드

✅ **GitLab 업그레이드**: 메이저 버전은 건너뛸 수 없다. Upgrade Path 도구로 경로 확인 필수

✅ **시크릿 파일**: `gitlab-secrets.json`을 잃으면 복구 불가. 절대 빠뜨리지 말 것

### ⚠️ 주의사항

⚠️ **CI/CD 차단 먼저**: 백업 전에 반드시 Runner와 Job을 중지하여 데이터 정합성을 유지하자

⚠️ **버전 일치**: 백업 파일의 GitLab 버전과 복구 서버의 GitLab 버전이 동일해야 한다

⚠️ **pg\_dump vs pg\_dumpall**: 역할/권한까지 이전하려면 `pg_dumpall`을 사용하자

⚠️ **복원 순서**: PostgreSQL 복원 → 시크릿 복원 → GitLab 데이터 복원 → 업그레이드 순서를 지키자

⚠️ **디스크 공간**: 백업 파일 + 덤프 파일 + 복원 데이터까지 충분한 디스크 공간을 확보하자

### 📚 참고 자료

- [GitLab Backup & Restore 공식 문서](https://docs.gitlab.com/administration/backup_restore/)

- [GitLab Docker 업그레이드 가이드](https://docs.gitlab.com/update/docker/)

- [GitLab Upgrade Path 도구](https://gitlab-com.gitlab.io/support/toolbox/upgrade-path/)

- [GitLab 새 서버로 마이그레이션 가이드](https://docs.gitlab.com/administration/backup_restore/migrate_to_new_server/)

- [PostgreSQL 공식 문서 - pg\_dump](https://www.postgresql.org/docs/current/app-pgdump.html)

- [PostgreSQL 업그레이드 가이드](https://www.postgresql.org/docs/current/upgrading.html)
