---
title: "MySQL Router와 InnoDB Cluster의 역할: 상용·커뮤니티 적용 가능성 구분"
description: "MySQL Router, Group Replication, Shell의 책임을 구분하고 Community 구성 가능성, 연결 장애 복구, 읽기 분산과 Aurora 차이를 정리한다."
tags: [ MySQL, 고가용성, 복제, 운영, DBA ]
image: "mysql-report-bg.png"
published: "2026-11-01"
updated: "2026-11-01"
author: "MySQL 기술 노트"
source_url: ""
---

# MySQL Router와 InnoDB Cluster의 역할: 상용·커뮤니티 적용 가능성 구분

데이터베이스 세 대를 복제하고 접속 주소 하나를 제공했다고 해서 고가용성 설계가 끝나지는 않는다. 누가 새로운 primary를 결정하는지, 애플리케이션이 어떻게 그 서버를 찾는지, 끊긴 트랜잭션을 누가 복구하는지가 서로 다른 문제이기 때문이다. 특히 MySQL Router를 자동 승격 도구로 이해하거나 InnoDB Cluster를 유료 제품에서만 가능한 기능으로 판단하면 구성과 비용 산정이 모두 잘못될 수 있다.

이 글은 **Group Replication은 데이터 복제와 그룹 내 역할 변경, MySQL Shell의 AdminAPI는 구성·관리, MySQL Router는 접속 경로 제공을 담당한다**는 구분에서 출발한다. MySQL Community에서도 이 조합을 구성할 수 있지만, 소프트웨어 사용 가능성과 운영 책임의 외주화는 별개의 선택이다.

설명은 MySQL 8.0·8.4 계열과 single-primary 구성을 중심으로 한다. 읽기·쓰기 자동 분리 부분은 Router 8.4 공식 문서를 기준으로 별도 구분한다. 아래 SQL은 Group Replication과 Router를 구성하지 않은 폐기용 MySQL 8.0 서버에서 실행했다. 진단 객체와 결과 해석을 검증한 것이며, 이 글에서 실제 Router bootstrap, 3멤버 승격, 애플리케이션 재접속이나 Aurora 장애 조치를 시험한 것은 아니다.

## 1. 하나의 제품명이 아니라 역할이 다른 구성 요소의 조합

### Group Replication: 데이터와 멤버십의 계층

각 MySQL 서버는 자기 InnoDB 데이터와 로그를 유지한다. Group Replication은 그룹 통신, 트랜잭션 순서와 충돌 판정, 멤버 상태를 다루며 single-primary 모드에서 primary 변경을 지원한다. 공용 디스크 하나를 여러 서버가 번갈아 사용하는 구조가 아니다.

고가용성 InnoDB Cluster는 최소 세 대의 서버 인스턴스를 기준으로 설계한다. 과반수를 확보해야 진행할 수 있다는 조건 때문에 서버 대수뿐 아니라 전원, 네트워크, 가용 영역의 장애 경계를 함께 보아야 한다. 세 프로세스가 같은 호스트에 있으면 호스트 장애를 견디는 설계가 아니다. 또한 멤버가 ONLINE이라는 사실만으로 모든 읽기가 최신 커밋을 즉시 보게 되는 것은 아니다. 읽기 일관성은 적용 진행과 consistency 설정, 해당 세션의 Read View까지 포함해 판단한다.

### MySQL Shell과 AdminAPI: 구성과 운영의 계층

MySQL Shell은 일반 SQL 클라이언트 기능에 더해 AdminAPI를 제공한다. AdminAPI는 인스턴스 구성 점검, 클러스터 생성과 멤버 추가, 상태 조회, 재가입 및 복구 작업을 다룬다. 클러스터 구성 정보는 `mysql_innodb_cluster_metadata` 스키마에 저장된다.

Shell을 실행하는 관리 터미널이 종료되었다고 기존 Group Replication이 멈추지는 않는다. Shell이 모든 커밋에 개입하거나 상시 실행되는 외부 승격 데몬인 것은 아니다. 반대로 관리 도구가 필요 없다는 뜻도 아니다. 전체 장애 후 복구나 멤버 교체는 올바른 데이터 이력과 상태를 판단하는 관리 절차가 필요하다.

### MySQL Router: 애플리케이션 접속의 계층

Router는 애플리케이션과 서버 사이에서 연결을 받는다. InnoDB Cluster용으로 bootstrap한 Router는 메타데이터와 실시간 그룹 상태를 참조해 접속 가능한 서버와 역할을 파악하고 캐시에 유지한다. primary가 바뀌면 쓰기 접속의 목적지를 갱신한다.

Router 자체가 트랜잭션을 복제하거나 과반수를 만들지는 않는다. Router만 여러 대 설치해도 데이터베이스가 자동으로 고가용성 클러스터가 되는 것은 아니다. 정적인 목적지 목록을 사용하는 Router 구성과, AdminAPI로 관리되는 클러스터의 메타데이터를 이용하는 구성도 구별해야 한다.

```mermaid
flowchart TB
    A[애플리케이션 연결 풀] --> R[MySQL Router]
    R -->|쓰기 경로| P[PRIMARY]
    R -->|읽기 경로| S1[SECONDARY 1]
    R -->|읽기 경로| S2[SECONDARY 2]
    P <-->|Group Replication| S1
    P <-->|Group Replication| S2
    S1 <-->|그룹 통신| S2
    H[MySQL Shell AdminAPI] -.->|구성 및 관리| P
    H -.->|구성 및 관리| S1
    H -.->|구성 및 관리| S2
    M[클러스터 메타데이터와 멤버 상태] -.->|조회 및 캐시 갱신| R
    P -.-> M
```

그림의 복제선은 역할 관계를 나타낸다. 실제 모든 트랜잭션이 그림의 화살표 순서로 일대일 전달된다는 의미는 아니다. 아래의 연결 설명은 기본 연결 라우팅을 기준으로 하며, 자동 읽기·쓰기 분리는 별도 기능으로 다룬다.

## 2. Community에서 가능한 것과 상용 지원의 경계

MySQL 공식 Community Edition 소개에는 **Group Replication, InnoDB Cluster, MySQL Router**가 포함되어 있다. 따라서 “InnoDB Cluster를 쓰려면 Enterprise Edition부터 구매해야 한다”는 전제는 맞지 않는다. 필요한 Community 서버, Shell, Router 패키지를 각각 준비하고 호환 버전을 조합할 수 있다.

판단은 다음 세 항목으로 나누는 편이 정확하다.

- **기능의 이용 가능성:** Community 구성으로 복제 그룹, AdminAPI 관리, Router 접속 경로를 만들 수 있는가. 이 핵심 조합은 가능하다.
- **상용 계약의 범위:** 공식 기술 지원, 지원 기간, 특정 운영 도구나 부가 기능이 필요한가. 실제 계약과 해당 제품의 제공 범위를 확인해야 하며, 모든 Enterprise 부가 기능이 Community에 포함된다고 해석해서는 안 된다.
- **소프트웨어 배포와 라이선스:** Community는 GPL로 제공된다. 사내 서버 운영과 제품에 포함한 재배포는 검토 조건이 다를 수 있다. 기술적으로 사용 가능하다는 판단을 모든 배포 방식에 대한 라이선스 결론으로 바꾸지 않는다.

Community라고 운영 비용이 사라지지는 않는다. 멤버별 저장 공간, 백업, 장애 리허설, 패치 호환성, 모니터링과 당직 대응이 필요하다. 반대로 상용 지원을 계약해도 애플리케이션의 중복 실행 방지나 복구 승인 절차가 자동으로 만들어지지는 않는다.

이름이 비슷한 제품도 구분한다. InnoDB Cluster는 Group Replication 기반이며 NDB Cluster와 다른 기술이다. InnoDB ReplicaSet의 비동기 복제 운영 모델이나 ClusterSet의 클러스터 간 재해복구 모델을 단일 InnoDB Cluster의 장애 조치와 같은 것으로 다루지 않는다.

## 3. Router bootstrap이 해 주는 것과 하지 않는 것

bootstrap은 **이미 존재하는 클러스터에 Router를 연결하도록 초기 구성하는 절차**다. 클러스터를 생성하는 절차가 아니다. 메타데이터 접근 계정과 인증 정보 저장, 라우팅 설정, 상태 파일 등을 준비하며 결과로 생성된 설정을 이용해 Router를 실행한다.

운영에서는 다음 순서가 중요하다.

1. 서버 버전, Group Replication 요구 조건과 인스턴스 설정을 먼저 점검한다.
2. AdminAPI로 클러스터를 구성하고 멤버 상태와 쓰기 역할을 확인한다.
3. 각 Router 인스턴스의 식별 정보, 메타데이터 접근 계정, 파일 권한과 TLS 정책을 정한다.
4. bootstrap 후 실제 생성된 설정과 포트를 확인한다.
5. 애플리케이션 계정으로 Router를 경유해 접속하고 목적지와 권한을 확인한다.

bootstrap에 사용하는 관리 계정, Router가 메타데이터를 조회하는 계정, 애플리케이션 계정은 책임이 다르다. 편의를 위해 모두 관리자 계정으로 통일하지 않는다. 설정 디렉터리의 keyring과 키 파일도 단순 캐시가 아니라 보호해야 할 인증 자산이다. 클라이언트에서 Router까지와 Router에서 서버까지의 TLS 보호·신원 검증을 각각 확인한다.

기본 포트는 설명을 돕는 관례일 뿐 고정 계약은 아니다. 전통적인 Classic protocol 쓰기 경로는 6446, 읽기 경로는 6447을 흔히 사용한다. `--conf-base-port` 등과 실제 설정에 따라 달라지므로 포트 번호만 보고 역할을 확정하지 않는다.

공식 bootstrap 예제의 읽기 경로에는 `round-robin-with-fallback`이 사용된다. 이 정책에서는 secondary를 사용할 수 없을 때 primary로 연결될 수 있다. 따라서 읽기 포트라는 이름을 “primary에 절대로 연결하지 않는 보안 경계”로 해석하면 안 된다. 쓰기를 금지할 업무 계정에는 실제 DB 권한 제한도 필요하다.

## 4. 기본 연결 라우팅과 자동 읽기·쓰기 분리는 다르다

### 기본 연결 라우팅

기본 라우팅에서는 새 연결이 만들어질 때 목적지를 선택하고 그 연결의 패킷을 전달한다. 애플리케이션이 읽기용 연결 풀과 쓰기용 연결 풀을 분리한다면, 어떤 작업을 어느 풀로 보낼지 애플리케이션이 결정한다. 읽기 연결 하나를 오래 유지하면서 SELECT를 여러 번 보내도 매번 다른 secondary로 재분배되는 구조라고 가정해서는 안 된다.

클러스터 멤버 추가로 읽기 자원이 늘어도 기존의 장수 연결이 즉시 균등해지지는 않는다. 연결 풀 수명과 재생성 정책, 각 연결의 실제 부하를 함께 관찰해야 한다. 연결 수가 같아도 긴 분석 쿼리가 한 서버에 집중되면 부하는 다를 수 있다.

### Router 8.4의 자동 분리 기능

“Router는 어떠한 경우에도 SQL을 분류하지 않는다”는 설명은 Router 8.4 전체에 적용할 수 없다. 별도의 Read/Write Splitting 기능에서는 쿼리와 트랜잭션 유형에 따라 목적지를 선택한다. 공식 문서의 구성 조건은 `access_mode=auto`, `connection_sharing=1`, `protocol=classic`, 그리고 `PRIMARY_AND_SECONDARY` 역할의 메타데이터 목적지다. bootstrap이 만드는 자동 분리 경로의 기본 포트는 6450이며, `--disable-rw-split`으로 이 구성을 비활성화할 수 있다.

이 기능을 기존 6446·6447 기본 경로와 같은 것으로 설명하거나, 과거 Router 버전에도 그대로 적용해서는 안 된다. `wait_for_my_writes`는 같은 세션의 마지막 쓰기 적용을 기다리는 기능이며, timeout 후 read-write 목적지로 돌아가는 정책이 있다. 이는 모든 세션과 모든 읽기에 대한 전역적인 즉시 일관성 보장이 아니다. 세션 상태, 트랜잭션 경계와 연결 재설정 동작까지 실제 드라이버로 검증한 뒤 도입해야 한다.

## 5. primary 승격과 애플리케이션 복구 사이의 빈틈

기본 연결 라우팅에서 primary가 중단되면 그 서버에 연결되어 있던 세션은 오류를 받는다. 이후 그룹이 새 primary를 결정하고 Router가 새 상태를 반영해도, 기존 세션의 진행 중 트랜잭션이 새 서버에서 이어서 실행되는 것은 아니다.

서비스 복구에는 최소한 다음 단계가 있다.

1. Group Replication이 장애를 감지하고 그룹 상태와 primary 역할을 정리한다.
2. Router가 변경된 상태를 확인하고 새로운 연결의 목적지를 갱신한다.
3. 연결 풀이 실패한 연결을 폐기하고 새 연결을 얻는다.
4. 애플리케이션이 이전 요청의 결과를 판단하고 필요한 업무 단위를 재시도한다.

특히 COMMIT을 보낸 직후 연결이 끊기면 애플리케이션이 커밋 성공 여부를 모를 수 있다. 이 상황에서 무조건 같은 결제를 다시 실행하는 것은 안전한 복구가 아니다. 업무 요청 식별자, 중복 방지 제약, 처리 결과 조회를 통해 불확실성을 해소해야 한다. 재접속 성공과 트랜잭션 재실행의 안전성은 별도의 합격 조건이다.

Router를 중앙 한 대에만 두면 데이터베이스가 정상이어도 Router 장애로 전체 접속이 끊길 수 있다. 애플리케이션 호스트별 배치나 여러 Router를 향한 별도의 접근 계층을 선택하고 해당 계층의 장애도 시험한다. 같은 호스트에 두는 방식은 공통 Router 장애를 줄이지만, 배포 대상과 설정 관리가 많아진다.

과반수 상실이나 전체 장애는 단순한 접속 주소 변경으로 해결되지 않는다. Router가 살아 있다는 이유로 강제 복구를 시작하지 말고, 생존 멤버·이력·격리 여부를 확인한 뒤 정해진 복구 절차를 적용한다. 메타데이터를 지우고 다시 만들면 해결될 것이라는 접근도 위험하다. 공식 문서는 메타데이터 삭제가 Router의 기존 연결 종료와 신규 연결 거부를 일으킬 수 있음을 경고한다.

## 6. SQL로 확인할 수 있는 범위부터 분리한다

아래 예제는 읽기 전용 진단이다. 모니터링 계정에는 필요한 조회 권한이 있어야 하며, 권한 부족 오류를 기능 미설치로 해석하지 않는다. 실제 운영에서는 각 멤버 직접 접속과 Router 경유 접속을 구별해 기록한다.

### 서버 버전과 현재 쓰기 제한

```sql
SELECT VERSION() AS server_version,
       @@version_comment AS distribution,
       @@global.read_only AS read_only,
       @@global.super_read_only AS super_read_only;
```

실행 결과(MySQL 8.0.x):

```text
mysql> SELECT VERSION() AS server_version,
    ->        @@version_comment AS distribution,
    ->        @@global.read_only AS read_only,
    ->        @@global.super_read_only AS super_read_only;

+----------------+------------------------------+-----------+-----------------+
| server_version | distribution                 | read_only | super_read_only |
+----------------+------------------------------+-----------+-----------------+
| 8.0.46         | MySQL Community Server - GPL |         0 |               0 |
+----------------+------------------------------+-----------+-----------------+
1 row in set (0.00 sec)
```

`distribution`은 현재 서버 배포판을 보여 줄 뿐 Shell과 Router의 설치 여부나 지원 계약을 알려 주지 않는다. 두 read-only 값이 0이어도 해당 서버가 클러스터의 정당한 primary임을 증명하지 못한다. standalone 서버도 같은 값을 반환할 수 있다. 반대로 `read_only=1`만으로 모든 권한의 쓰기가 막힌다고 간주하지 않는다. 애플리케이션 계정의 실제 쓰기 거부를 따로 확인해야 한다.

### Group Replication 플러그인과 멤버 상태

```sql
SELECT PLUGIN_NAME, PLUGIN_STATUS
FROM information_schema.PLUGINS
WHERE PLUGIN_NAME = 'group_replication';

SELECT MEMBER_ID, MEMBER_STATE, MEMBER_ROLE
FROM performance_schema.replication_group_members
ORDER BY MEMBER_ID;
```

실행 결과(MySQL 8.0.x):

```text
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
    -> FROM information_schema.PLUGINS
    -> WHERE PLUGIN_NAME = 'group_replication';

Empty set (0.00 sec)

mysql> SELECT MEMBER_ID, MEMBER_STATE, MEMBER_ROLE
    -> FROM performance_schema.replication_group_members
    -> ORDER BY MEMBER_ID;

Empty set (0.00 sec)
```

이번 시험 서버에서는 두 조회가 모두 빈 결과다. 첫 결과는 해당 플러그인이 설치·활성화된 행이 없다는 뜻이고, 두 번째 결과는 관측할 그룹 멤버가 없다는 뜻이다. **멤버 장애가 0건이라서 정상이라는 의미가 아니다.** 클러스터를 구성한 서버에서는 예상 멤버 수, ONLINE 상태, 역할을 함께 대조하고 한 서버가 보는 상태만으로 전체 네트워크가 정상이라고 단정하지 않는다.

### 관리 메타데이터와 접속 대상

```sql
SELECT SCHEMA_NAME
FROM information_schema.SCHEMATA
WHERE SCHEMA_NAME = 'mysql_innodb_cluster_metadata';

SELECT @@port AS backend_port,
       @@global.read_only AS backend_read_only,
       @@global.super_read_only AS backend_super_read_only;
```

실행 결과(MySQL 8.0.x):

```text
mysql> SELECT SCHEMA_NAME
    -> FROM information_schema.SCHEMATA
    -> WHERE SCHEMA_NAME = 'mysql_innodb_cluster_metadata';

Empty set (0.00 sec)

mysql> SELECT @@port AS backend_port,
    ->        @@global.read_only AS backend_read_only,
    ->        @@global.super_read_only AS backend_super_read_only;

+--------------+-------------------+-------------------------+
| backend_port | backend_read_only | backend_super_read_only |
+--------------+-------------------+-------------------------+
|         3306 |                 0 |                       0 |
+--------------+-------------------+-------------------------+
1 row in set (0.00 sec)
```

메타데이터 조회가 빈 것은 이번 standalone 시험 환경의 예상 결과다. 운영 환경에서는 조회 권한 때문에 보이지 않는 경우도 구별한다. 스키마가 존재해도 내용이 최신이고 Router 인증이 성공하며 클러스터가 정상이라는 결론으로 이어지지는 않는다. 이 스키마의 내부 테이블을 임의로 수정하기보다 AdminAPI의 상태·관리 기능을 사용한다.

`@@port`는 Router의 리스닝 포트가 아니라 연결된 MySQL 서버의 포트다. 다만 여러 서버가 모두 3306을 쓸 수 있으므로 포트만으로 목적지를 식별할 수는 없다. 실제 접속 경로 검증에서는 서버 UUID도 함께 조회하고 내부 자산 정보로 관리한다. 여기의 결과는 서버 직접 접속이며 Router 경유 성공 사례로 제시한 것이 아니다.

## 7. Aurora MySQL에서는 관리 경계가 다르다

Aurora의 DB cluster와 InnoDB Cluster는 이름이 비슷하지만 같은 구성 방식이 아니다. Aurora는 관리형 스토리지·복제·장애 조치 체계를 사용하며, 이 글의 Community 서버용 AdminAPI와 Group Replication 구성 절차를 Aurora 클러스터 생성 절차로 대체할 수 없다.

Aurora에서는 cluster endpoint가 현재 writer 접속에, reader endpoint가 읽기 인스턴스 대상의 연결 분산에 사용된다. 여기서도 endpoint가 바뀐다고 기존 세션이 자동으로 새 인스턴스로 이동하거나 진행 중 트랜잭션이 복원되지는 않는다. AWS 문서 역시 장애 조치 후 endpoint를 이용한 재접속을 설명한다. 드라이버·연결 풀의 DNS 캐시와 재접속 정책을 함께 검증해야 한다.

또한 reader endpoint는 쿼리마다 서버를 고르는 것이 아니라 연결을 분산한다. 장애 조치 중에는 새 primary로 잠시 연결될 수도 있으므로 이름만으로 쓰기 권한 통제를 대신하지 않는다. Aurora 앞에 별도 프록시를 두는 선택과 Aurora 자체의 writer 선출은 다른 계층이며, InnoDB Cluster 메타데이터 기반 Router bootstrap을 그대로 적용하는 설계로 혼동하지 않는다.

## 8. 도입·장애 리허설의 합격 기준

- [ ] Community 구성 가능성과 상용 지원·부가 기능·배포 라이선스 요구를 각각 문서화했는가.
- [ ] 서버·Shell·Router의 실제 버전과 상호 지원 범위를 확인했는가. Router 8.4를 더 새로운 서버 계열에 무조건 대응 가능한 범용 프록시로 가정하지 않았는가.
- [ ] 최소 세 멤버와 장애 도메인을 설계하고, 과반수 상실·전체 장애의 복구 승인 기준을 마련했는가.
- [ ] AdminAPI 관리, 복제·승격, 연결 라우팅의 담당 계층을 구분했는가.
- [ ] Router bootstrap 결과의 포트·대상 역할·읽기 fallback과 계정·keyring 보호를 확인했는가.
- [ ] 기본 연결 라우팅과 자동 읽기·쓰기 분리 중 사용하는 기능을 명시했는가.
- [ ] 쓰기 직후 읽기의 가시성을 애플리케이션 트랜잭션과 세션 범위에서 시험했는가.
- [ ] primary 장애 후 새 연결 성공뿐 아니라 기존 연결 오류, 풀 교체, 업무 요청 중복 방지까지 확인했는가.
- [ ] Router 한 대의 중단도 장애 시험에 포함하고, 클라이언트·Router·서버 구간의 TLS를 따로 검증했는가.
- [ ] 백업 복원과 잘못된 업무 변경의 복구 절차를 별도로 유지하는가. 고가용성 복제를 백업으로 대체하지 않았는가.

운영 승인 시험에서는 primary 중단 전후의 멤버 역할, Router 로그, 새 연결의 목적지, 애플리케이션 오류와 업무 처리 결과를 같은 시간축으로 보관한다. SQL 진단이 성공했다는 증거만으로 승격 시간이나 서비스 RTO를 기록하지 않는다.

## 9. 정리

InnoDB Cluster는 Community에서도 구성할 수 있는 통합 고가용성 체계다. 그러나 Group Replication의 역할 변경, Shell의 관리 작업, Router의 연결 경로, 애플리케이션의 재시도는 서로 대체 관계가 아니다. 상용 지원 여부는 이 구조 위에서 운영 책임과 계약을 선택하는 문제다.

다음 단계의 고가용성 설계에서는 Router를 통과한 접속 성공뿐 아니라 과반수 상실, 네트워크 분리, 커밋 결과 불확실성을 함께 다루어야 한다. 데이터베이스의 정상 상태와 서비스의 정상 상태를 각각 증명할 수 있어야 운영 가능한 클러스터가 된다.

## 참고 문서

- [MySQL Community Edition의 포함 기능](https://www.mysql.com/products/community/)
- [MySQL Shell 8.0: InnoDB Cluster](https://dev.mysql.com/doc/mysql-shell/8.0/en/mysql-innodb-cluster.html)
- [MySQL Router 8.4: 지원 버전 개요](https://dev.mysql.com/doc/mysql-router/8.4/en/mysql-router-general.html)
- [MySQL Router 8.4: 메타데이터와 상태](https://dev.mysql.com/doc/mysql-router/8.4/en/mysql-router-general-metadata.html)
- [MySQL Router 8.4: bootstrap](https://dev.mysql.com/doc/mysql-router/8.4/en/mysql-router-deploying-bootstrapping.html)
- [MySQL Router 8.4: 애플리케이션 고려 사항](https://dev.mysql.com/doc/mysql-router/8.4/en/mysql-router-general-using-developing.html)
- [MySQL Router 8.4: 읽기·쓰기 분리 구성](https://dev.mysql.com/doc/mysql-router/8.4/en/router-read-write-splitting-configuration.html)
- [Amazon Aurora: endpoint 연결과 고가용성](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Overview.Endpoints.html)
