본문으로 건너뛰기

pg_stat_statements 해설

· 약 9분

pg_stat_statements는 컬럼이 스무 개가 넘지만, DBA가 매일 보는 건 사실 대여섯 개뿐이에요. 나머지는 그 대여섯 개를 해석할 때 보조로 쓰이며, 이 글에서는 핵심 컬럼을 읽는 법과 이 확장의 내부 동작 때문에 가끔 데이터가 비어 보이는 이유를 운영 관점에서 정리해요.

같은 주에 boringsql와 pganalyze가 이 주제를 각각 깊게 다뤘습니다. 두 글을 PostgreSQL 공식 문서로 교차 확인하면서 한국어 실무 가이드로 다시 엮었습니다.

pg_stat_statements가 수집하는 것

pg_stat_statements는 공유 메모리에 있는 고정 크기 해시 테이블입니다. 개별 실행을 하나하나 기록하는 게 아니라, 같은 모양의 쿼리를 하나의 항목으로 묶어 누적 카운터를 갱신합니다.

여기서 "같은 모양"의 기준은 정규화(normalization)입니다. 상수를 떼어내고 $1, $2 같은 자리표시자로 바꾼 뒤, 파싱된 쿼리 트리의 해시값을 queryid로 삼습니다. 그래서 아래 두 쿼리는 하나의 항목으로 집계됩니다.

SELECT * FROM users WHERE id = 42;
SELECT * FROM users WHERE id = 99;

여기서 DBA가 미리 알아둬야 할 정규화의 성질이 몇 가지 있습니다.

  • queryid는 메이저 버전 사이에서 안정적이지 않습니다. 같은 SQL이라도 메이저 업그레이드 후, 혹은 다른 CPU 아키텍처에서 다른 값으로 해시될 수 있습니다. 여러 서버의 통계를 묶을 때 queryid를 영구 조인 키로 쓰면 안 됩니다.
  • OID 기반이라 이름 기반이 아닙니다. 테이블을 drop하고 다시 만들면 새 OID가 붙고, 그 결과 새 queryid가 생깁니다. 이전 통계는 고아로 남습니다.
  • 구조에 민감합니다. 테이블 alias가 다르거나, 컬럼 목록이 바뀌거나, LIMIT이 붙거나, 조건 순서가 달라지면 논리적으로 같은 쿼리가 여러 항목으로 쪼개집니다. ORM이 이런 변형을 대량으로 쏟아내면 항목이 수백 개로 흩어지기도 합니다.

또 하나, 중요한 동작상의 제약이 있습니다. pg_stat_statements는 ExecutorEnd 단계에서 통계를 기록합니다. 즉 정상적으로 끝난 실행만 집계됩니다. 타임아웃으로 끊기거나 중간에 abort된 쿼리는 흔적을 남기지 않습니다. 장애 시점에 문제를 일으킨 쿼리가 정작 이 뷰에 안 보이는 경우가 여기서 나옵니다.

DBA가 봐야 할 핵심 컬럼

전체 컬럼은 공식 문서에 다 있습니다. 여기서는 운영 중에 실제로 손이 가는 것만 추립니다.

컬럼의미언제 보나
calls실행 횟수빈도. 한 번 느린지, 자주 느린지 구분
total_exec_time누적 실행 시간(ms)서버 부하에 가장 크게 기여하는 쿼리 찾기
mean_exec_time평균 실행 시간(ms)한 번 실행이 비싼 쿼리 찾기
min/max/stddev_exec_time최소, 최대, 표준편차(ms)편차가 큰 쿼리 식별
rows반환/영향 행 수호출당 결과 규모 추정
shared_blks_hitbuffer cache 적중 블록 수캐시 효율
shared_blks_read디스크에서 읽은 공유 블록 수실제 I/O 부담
wal_bytes생성한 WAL 양(bytes)쓰기 부하/복제 부담

느린 쿼리를 찾을 때 mean과 total 구분하기

가장 먼저 정해야 할 건 정렬 기준입니다. mean_exec_timetotal_exec_time은 전혀 다른 질문에 답합니다.

  • total_exec_time이 큰 쿼리는 서버 전체 부하에 가장 많이 기여하는 쿼리입니다. 한 번은 1ms로 빨라도 하루에 수천만 번 실행되면 누적 시간이 1위가 됩니다. 서버가 바쁜 원인을 찾을 때는 이 값을 봅니다.
  • mean_exec_time이 큰 쿼리는 한 번 실행이 비싼 쿼리입니다. 빈도는 낮아도 실행할 때마다 사용자를 기다리게 만듭니다. 특정 화면이 느리다는 제보를 추적할 때 유용합니다.
-- 누적 부하 상위 10개
SELECT
queryid,
calls,
round(total_exec_time::numeric, 1) AS total_ms,
round(mean_exec_time::numeric, 2) AS mean_ms,
rows,
query
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;

calls를 항상 함께 봐야 둘을 헷갈리지 않습니다. total_exec_time이 높은데 calls도 높으면 "자주 불려서 누적된" 것이고, calls가 낮은데 total이 높으면 "한 번이 무거운" 것입니다.

평균에서 사라지는 분포

pg_stat_statements는 평균(mean)과 표준편차(stddev)만 유지하고, 개별 실행 시간은 즉시 버립니다. 그래서 분포의 모양을 알 수 없습니다.

예를 들어 99%는 1ms에 끝나지만 1%는 2초가 걸리는 쿼리가 있다면, 평균은 약 21ms 근처로 찍힙니다. 이 21ms는 어느 실행도 대표하지 못하는 숫자입니다. 정작 문제가 되는 2초짜리 1%는 나머지 99%에 희석돼 평균 뒤로 묻힙니다. 게다가 pg_stat_statements는 p99(실행의 99%가 그 안에 들어오는 시간, 상위 1%를 잘라낸 경계) 같은 percentile 값을 주지 않으니, 평균만 봐서는 이런 느린 실행을 따로 짚을 길이 없습니다. stddev_exec_time이 평균에 비해 유난히 크거나 max_exec_time이 평균과 크게 벌어져 있다면, 그 쿼리는 분포가 넓다는 신호이니 별도로 들여다볼 가치가 있습니다.

I/O 컬럼의 hit와 read 읽기

shared_blks_hitshared_blks_read는 짝으로 읽습니다.

  • shared_blks_hit은 buffer cache에서 바로 찾은 블록 수입니다. 빠릅니다.
  • shared_blks_read는 buffer에 없어서 디스크(또는 OS page cache)에서 읽어 온 블록 수입니다. 느립니다.

shared_blks_read가 크다는 건 그 쿼리가 실제 I/O를 많이 일으킨다는 뜻입니다. 작업 집합이 buffer pool보다 크거나, 인덱스 없이 큰 테이블을 스캔하고 있을 가능성이 있습니다. 두 값을 합친 대비 적중률을 보면 캐시 효율을 가늠할 수 있습니다.

읽기/쓰기에 걸린 실제 시간까지 보려면 shared_blk_read_time, shared_blk_write_time 컬럼을 봅니다. 단, 이 값은 track_io_timing이 켜져 있어야 채워지고, 꺼져 있으면 전부 0입니다.

temp_blks_read, temp_blks_written은 임시 파일 I/O입니다. 정렬이나 해시 조인이 work_mem을 넘겨서 디스크로 흘러넘쳤다는 신호이므로, 이 값이 큰 쿼리는 work_mem 조정이나 쿼리 재작성 후보입니다.

쓰기 부하를 보여주는 WAL 컬럼

wal_bytes, wal_records, wal_fpi는 그 쿼리가 만든 WAL 양을 보여줍니다. 쓰기가 많은 쿼리, 즉 replication 지연이나 디스크 쓰기 부하의 원인을 찾을 때 봅니다. wal_fpi(full page image)가 유난히 크면 checkpoint 직후의 첫 쓰기에서 페이지 전체가 WAL에 기록되는 패턴일 수 있습니다.

버전에 따른 total_time 분리

PostgreSQL 13에서 타이밍 컬럼 이름이 바뀌었습니다. 12 이하에서는 total_time, mean_time 한 묶음이었지만, 13부터 계획(planning)과 실행(execution)이 분리되어 total_plan_time/total_exec_time, mean_plan_time/mean_exec_time으로 나뉘었습니다. 12 이하를 대상으로 한 옛 쿼리는 13 이상에서 컬럼명을 바꿔줘야 동작합니다.

단, 계획 시간 컬럼(total_plan_time 등)은 pg_stat_statements.track_planning이 켜져 있어야 채워집니다. 이 설정의 기본값은 off입니다. 계획 시간이 전부 0으로 보인다면 이 설정부터 확인합니다.

PostgreSQL 17부터는 stats_since(항목 통계 수집이 시작된 시각)와 minmax_stats_since(min/max 통계 수집 시작 시각) 컬럼이 추가됐습니다. 어떤 구간을 측정할 때 그 사이에 eviction이나 리셋이 끼었는지 판단하는 데 씁니다.

해시 테이블이 가득 찰 때의 eviction과 dealloc

pg_stat_statements가 추적하는 서로 다른 쿼리 수에는 상한이 있습니다. pg_stat_statements.max이고 기본값은 5000입니다. 이 값은 서버 시작 시에만 설정할 수 있습니다.

서로 다른 쿼리 수가 이 상한을 넘으면 eviction(축출)이 일어납니다. 공식 문서는 "가장 적게 실행된(least-executed) 항목 정보를 버려서 새 항목 자리를 만든다"고 설명합니다. 내부적으로는 각 항목에 겉으로 드러나지 않는 usage 카운터가 있고, deallocation 시점에 모든 usage 값을 일정 비율 줄인 뒤 정렬해서 하위 일부를 버립니다. 이 정렬은 항목 수에 비례하는 작업이며, exclusive lock을 잡은 채로 진행됩니다.

그래서 pg_stat_statements.max를 무작정 키우는 건 공짜가 아닙니다. max가 클수록 deallocation 시점의 정렬 비용이 커지고, 그동안 lock 경합도 길어집니다.

축출이 일어났는지는 별도 뷰인 pg_stat_statements_info로 확인합니다. 이 뷰는 단 한 행이고 컬럼 두 개를 가집니다.

컬럼의미
deallocmax를 초과해 항목이 축출된 누적 횟수
stats_reset전체 통계가 마지막으로 리셋된 시각
SELECT dealloc, stats_reset FROM pg_stat_statements_info;

dealloc이 계속 올라간다면, 테이블이 쉼 없이 가득 차고 비워지는 중입니다. 이 상태에서는 자주 실행되지 않는 쿼리의 통계가 수시로 사라지므로 데이터를 신뢰하기 어렵습니다. ORM이 구조가 조금씩 다른 쿼리를 대량으로 흘려보내 해시 테이블을 가득 채우는 경우가 대표적입니다. 이때 실행 빈도가 낮은 항목이 먼저 축출되면서, 나중에 그 쿼리를 되짚어볼 단서 자체가 남지 않습니다.

대응은 두 갈래입니다. max를 적당히 늘리거나(정렬 비용 증가를 감수하고), 애초에 쿼리 변형 수를 줄이는 것입니다. 예컨대 길이가 제각각인 IN 목록은 PostgreSQL 18 이전까지 길이마다 별도 항목을 만들었는데, = ANY($1) 배열 바인딩으로 바꾸면 버전과 무관하게 하나의 항목으로 묶입니다.

아래 도식은 새 쿼리가 들어왔을 때 항목이 잡히고 축출되기까지의 흐름입니다.

운영 관점의 리셋 전략과 함정

단조 증가하는 누적 통계

뷰의 카운터는 마지막 리셋 이후로 계속 쌓입니다. 그래서 "지금 어떤 쿼리가 부하를 일으키는가"를 보려면 두 시점의 스냅샷을 떠서 빼는 수밖에 없습니다. 한 번 조회한 절댓값만으로는 한 달 전 배치 작업과 방금 들어온 트래픽이 뒤섞여 보입니다.

모니터링 도구들이 일정 간격으로 뷰를 떠다가 차분을 계산하는 이유가 이것입니다. 직접 차분을 계산할 때는 그 사이에 eviction이나 리셋이 끼면 음수가 나올 수 있으니, stats_since(17 이상)나 pg_stat_statements_infodealloc/stats_reset을 함께 확인해야 합니다.

리셋 함수

pg_stat_statements_reset()으로 통계를 비웁니다. 인자 없이 호출하면 전체를 리셋하고, 특정 대상만 비울 수도 있습니다.

-- 전체 리셋
SELECT pg_stat_statements_reset();

-- 특정 user / db / queryid만 리셋 (0은 "전체" 의미)
SELECT pg_stat_statements_reset(0, 0, :queryid);

minmax_only 인자를 true로 주면 min/max_exec_time, min/max_plan_time만 비웁니다. 평균과 누적은 살려두고 최소/최대만 다시 측정하고 싶을 때 씁니다. 기본값은 superuser만 실행할 수 있고, 필요하면 GRANT로 권한을 넘깁니다.

리셋 전략에는 정답이 없습니다. 흔한 선택은 두 가지입니다.

  • 리셋하지 않고 누적 + 차분. 모니터링 도구에 맡기는 방식. 장기 추세를 잃지 않습니다.
  • 정기 리셋(예: 배포/점검 전후). 특정 구간만 깨끗하게 보고 싶을 때. 단, 리셋 순간 이전 데이터는 사라지니 추세 분석은 포기합니다.

자주 밟는 함정 정리

  • 타임아웃/abort된 쿼리는 집계되지 않습니다. 장애 원인 쿼리가 뷰에 없을 수 있습니다.
  • 평균만으로 판단하면 드물게 튀는 느린 실행을 놓칩니다. max_exec_time/stddev로 분포를 함께 의심합니다.
  • dealloc이 오르는 상태에서는 통계가 불완전합니다. 먼저 그것부터 해결합니다.
  • 계획 시간(*_plan_time)이 0이면 track_planning이 꺼진 것입니다.
  • I/O 시간(shared_blk_read_time 등)이 0이면 track_io_timing이 꺼진 것입니다.
  • queryid는 메이저 버전/아키텍처 간에 달라질 수 있어 영구 키로 부적합합니다.

정리

pg_stat_statements는 컬럼이 많아 보여도 DBA의 시선은 결국 몇 갈래로 좁혀져요. 부하의 원인은 total_exec_time, 느린 한 방은 mean_exec_time으로 찾고 둘 다 calls로 맥락을 잡으며, I/O가 의심되면 shared_blks_read와 temp 블록을, 쓰기가 의심되면 wal_bytes를 봐요. 데이터가 비어 보이거나 음수가 나오면 pg_stat_statements_infodeallocstats_reset을 먼저 확인하면 되고, 이 정도만 손에 익히면 대부분의 쿼리 튜닝은 이 뷰 하나에서 출발할 수 있어요.


참고한 출처:

PostgreSQL 파일 디스크립터

· 약 6분

튜닝 한 줄로 max_connections를 1만까지 올린 인스턴스가 어느 날 통째로 죽어요. 원인은 쿼리도 디스크도 아니고, DBA가 평소 신경 쓰지 않는 OS limit, file descriptor예요. 연결 풀러 없이 연결 수만 키운 구성은 file descriptor 고갈이라는 단 하나의 벽에 부딪혀 무너져요. 이 글에서는 그 메커니즘과 대응을 한 번에 정리해요.

PostgreSQL의 프로세스 모델과 file descriptor

PostgreSQL은 연결 하나마다 OS 프로세스 하나를 띄우는 process-per-connection 모델입니다. 클라이언트가 접속하면 postmaster가 backend 프로세스를 fork하고, 그 backend가 해당 세션의 모든 작업을 담당합니다. 스레드 풀로 연결을 다중화하는 일부 다른 데이터베이스와 결정적으로 다른 지점입니다.

여기서 핵심은 backend 프로세스 하나가 여러 개의 file descriptor를 동시에 들고 있다는 점입니다. file descriptor(이하 fd)는 프로세스가 열어둔 파일, 소켓, 파이프를 가리키는 OS 차원의 정수 핸들입니다. 하나의 backend는 다음을 모두 fd로 잡습니다.

  • 클라이언트와 연결된 소켓
  • 읽고 쓰는 테이블/인덱스 파일 (PostgreSQL 내부 VFD 계층이 관리)
  • WAL 세그먼트
  • 정렬/조인 과정에서 만들어지는 임시 파일

그래서 fd 소비량은 연결 수에 딱 비례하지 않고, 그 연결이 무슨 일을 하느냐에 따라 출렁입니다. 놀고 있는 idle backend는 fd를 10개에서 15개 정도만 쓰지만, 여러 테이블과 인덱스를 동시에 건드리는 write backend는 50개에서 200개 이상까지 올라갑니다. 연결 1만 개가 전부 활성 상태로 무거운 쓰기를 돌리는 순간, fd 소비량은 산술적 예상치를 한참 넘어섭니다.

고갈 메커니즘과 증상

fd에는 두 겹의 한계가 걸려 있고, 둘 중 무엇에 먼저 닿느냐에 따라 증상이 달라집니다.

첫 번째는 프로세스 단위 한계인 RLIMIT_NOFILE입니다. ulimit -n으로 조회/설정하며, 프로세스 하나가 열 수 있는 fd 개수를 제한합니다. PostgreSQL의 max_files_per_process는 이 OS limit 안에서 backend 하나가 잡을 fd 상한을 한 번 더 좁히는 PostgreSQL 자체 파라미터입니다.

두 번째는 시스템 전체 한계인 fs.file-max입니다. 커널이 머신 전체에서 열 수 있는 fd 총량을 제어하며, 이 값에 도달하면 어느 프로세스가 요청하든 모든 open() 호출이 실패합니다. PostgreSQL뿐 아니라 그 위에 떠 있는 모든 프로세스가 동시에 영향을 받습니다.

연결 풀러 없이 max_connections를 과하게 올린 구성에서는 두 번째 한계에 먼저 닿기 쉽습니다. 이론상 최악의 소비량은 다음 곱으로 표현됩니다.

worst-case fd ≈ max_connections × max_files_per_process

max_files_per_process 기본값이 1,000이므로, max_connections를 10,000으로 잡으면 산술적 상한이 천만 단위로 뜁니다. 실제로는 모든 backend가 동시에 상한까지 fd를 사용하지는 않으니 평소에는 멀쩡합니다. 문제는 배치 잡이 한꺼번에 쓰기를 일으킬 때입니다. LWLock:BufferContent, LWLock:WALInsert, LWLock:WALWrite 같은 lock 경합으로 락 보유 시간이 길어지면 동시에 오픈된 fd가 쌓이고, 어느 순간 시스템 한계를 갑자기 넘깁니다.

이때 PostgreSQL 로그는 한꺼번에 죽지 않고 단계적으로 무너집니다.

out of file descriptors: Too many open files in system; release and retry
...
server process (PID XXXXX) was terminated by signal 6
...
failed to send SSL negotiation response: Broken pipe

처음에는 평범한 로그 사이에 "Too many open files"(OS 레벨로는 EMFILE/ENFILE) 메시지가 하나둘 섞이다가, fd를 못 잡은 backend가 signal 6(abort)으로 죽고, postmaster가 crash recovery에 들어가면서 살아 있던 연결까지 SSL 끊김으로 떨어집니다. 애플리케이션 쪽에서는 "Unable to create new connection" 같은 커넥션 풀 예외로 나타납니다. 즉 fd 고갈은 느린 성능 저하가 아니라 인스턴스 전체가 한 번에 내려앉는 장애로 드러납니다.

공식 문서도 같은 맥락을 짚습니다. max_files_per_process에 대해 "If you find yourself seeing 'Too many open files' failures, try reducing this setting"이라고 안내하고, kernel resource 항목에서는 시스템 전역 한계를 fs.file-max로 조정하라고 명시합니다.

ulimit, max_files_per_process, 연결 풀러로 대응하기

대응은 세 층위로 나뉩니다. 급한 불을 끄는 임시 조치와 구조를 바꾸는 근본 조치를 구분하는 것이 중요합니다.

대응무엇을 푸나성격부작용/한계
fs.file-max 상향시스템 전역 fd 총량 확대임시 (시간 벌기)근본 원인인 backend 수는 그대로
ulimit -n 상향프로세스당 fd 상한 확대임시/보완메모리 소비 증가, 한계만 미룸
max_files_per_process 조정backend 1개의 fd 상한 제어보완너무 낮추면 VFD 캐시 회전 잦아져 성능 저하, 재시작 필요
PgBouncer 등 연결 풀러backend 절대 수 감소근본풀러 운영/모드 이해 필요

1단계: 임시로 OS limit 넓히기

PgBouncer 도입 전까지 시간을 벌어야 한다면 시스템 전역 한계부터 올립니다.

# 현재 상태 확인
cat /proc/sys/fs/file-max # 시스템 최대치
cat /proc/sys/fs/file-nr # 현재 사용량: <할당> <유휴> <최대>

# 시스템 전역 한계 상향 (재부팅 후에도 유지)
sysctl -w fs.file-max=20000000
echo "fs.file-max = 20000000" >> /etc/sysctl.conf
sysctl -p

프로세스당 한계는 postgres 사용자에 대해 /etc/security/limits.conf(또는 systemd 유닛의 LimitNOFILE)에서 soft/hard를 함께 올립니다. soft 한계가 실제로 적용되는 값이고 hard 한계까지 사용자가 올릴 수 있으며, hard 한계 자체는 root만 바꿀 수 있습니다. 다만 이는 어디까지나 시간을 버는 조치입니다. backend 수가 그대로라면 한계를 올린 만큼 더 큰 폭으로 다시 터집니다.

2단계: max_files_per_process로 backend 소비 제한

OS 전역 한계를 못 건드리는 환경이라면, backend 하나가 잡는 fd를 PostgreSQL 쪽에서 좁힐 수 있습니다. 공식 문서가 안내하는 방식입니다.

# postgresql.conf — 재시작 필요
max_files_per_process = 1000 # 기본값. "Too many open files" 보이면 낮춰 본다

단, 이 값은 OS의 프로세스당 fd 한계를 넘을 수 없습니다. 그리고 너무 낮추면 backend가 파일을 자주 닫았다 여는 VFD 캐시 회전이 잦아져 성능이 떨어집니다. 어디까지나 OS 한계 조정과 짝을 이루는 보완책으로 봅니다.

3단계: 연결 풀러로 근본 대응

진짜 해법은 애플리케이션과 PostgreSQL 사이에 PgBouncer 같은 연결 풀러를 두는 것입니다. 풀러는 수천 개의 애플리케이션 연결을 실제 200~500개 backend로 다중화합니다. transaction 모드에서는 트랜잭션이 끝날 때마다 backend가 풀로 반환되므로, 1만 개 클라이언트가 붙어도 PostgreSQL이 실제로 띄우는 backend 수는 풀 크기로 묶입니다.

풀러를 앞에 세운 뒤에는 max_connections를 500~1,000 수준으로 되돌립니다. 그래야 backend가 무한정 쌓이는 구조 자체가 사라집니다. 한계를 넓히는 게 아니라, 한계에 도달할 일을 없애는 방향입니다.

DBA 체크리스트

장애가 터지기 전에 점검할 항목과, 터졌을 때 들여다볼 지점을 나눠 정리합니다.

평상시 점검:

  • SHOW max_connections; 값이 실제 동시 연결 수요 대비 과하게 크지 않은가
  • 애플리케이션과 PostgreSQL 사이에 PgBouncer 등 연결 풀러가 있는가
  • 풀러를 쓴다면 transaction 모드로 backend가 트랜잭션마다 반환되는가
  • fs.file-max와 postgres 사용자 ulimit -n이 워크로드 피크를 감당할 값인가
  • cat /proc/sys/fs/file-nr 첫 번째 값(할당된 fd)이 fs.file-max의 50~60%를 넘지 않는가

모니터링/알람:

  • file-nr 사용량이 fs.file-max의 일정 비율을 넘으면 알람이 울리는가
  • pg_stat_activity의 활성 연결 수가 배치 기준선(예: 1,000)을 넘으면 감지되는가
  • 배치 윈도우에는 watch -n 5 'cat /proc/sys/fs/file-nr'로 실시간 추적하는가

장애 발생 시 진단:

  • 로그에 "Too many open files in system"이 보이는가 — fd 고갈 확정
  • cat /proc/$(pgrep -o postgres)/limits | grep "open files"로 프로세스 한계 확인
  • pg_stat_activity를 state/wait_event별로 집계해 lock 경합 backend가 몰려 있는지 확인
SELECT count(*), state, wait_event_type, wait_event
FROM pg_stat_activity
GROUP BY state, wait_event_type, wait_event
ORDER BY count DESC;

정리하면, fs.file-maxulimit을 올리는 건 응급 처치이지 치료가 아니에요. fd 고갈의 뿌리는 backend 프로세스가 너무 많다는 데 있고, 그 수를 구조적으로 묶는 유일한 방법이 연결 풀러예요. 연결 풀러가 이번 주 계획에 없다면, 지금 넣어야 해요.

참고

pgBackRest와 pg_tde 백업

· 약 5분

데이터를 디스크에 암호화해서 저장하는 클러스터를 백업 도구가 제대로 다룰 수 있을까요? 결론부터 말하면, pg_tde로 암호화한 PostgreSQL 클러스터를 pgBackRest로 백업하고 복구하는 과정은 거의 대부분 투명하게 작동하지만, 암호화된 데이터를 백업 도구가 해석할 수 없다는 본질적 한계 때문에 몇 가지 검증/압축 옵션은 꺼야 해요.

Data Egret의 Stefan Fercot(스테판 페르코)가 pgBackRest and pg_tde 글에서 이 조합을 직접 검증했습니다. 이 블로그에서 다뤄 온 백업 시리즈의 곁가지로, 백업 도구와 암호화 extension의 궁합을 운영 관점에서 정리해 봐요.

pg_tde가 암호화하는 것

pg_tde는 Percona가 개발 중인 투명 데이터 암호화(Transparent Data Encryption) extension입니다. 이름 그대로 애플리케이션은 암호화 여부를 신경 쓰지 않고, 디스크에 저장되는 데이터(data at rest)만 암호화합니다. 암호화 대상은 크게 두 가지입니다.

  • 테이블 데이터(heap): tde_heap 접근 방식(access method)으로 만든 테이블. 기존 테이블은 ALTER TABLE ... SET ACCESS METHOD tde_heap으로 전환합니다. heap 테이블뿐 아니라 거기 딸린 index, TOAST, sequence까지 암호화됩니다.
  • WAL: pg_tde.wal_encrypt GUC를 켜면 WAL 세그먼트도 암호화됩니다. 이 설정은 서버 전역이라 재시작이 필요하고, 켠 시점 이후의 WAL write부터 암호화가 적용됩니다.

다만 모든 게 암호화되지는 않습니다. 시스템 카탈로그와 통계 데이터 같은 메타데이터는 아직 암호화 대상이 아닙니다. 이름 그대로 "데이터" 암호화에 초점이 맞춰져 있습니다.

키 구조는 2계층입니다. 실제 데이터를 암호화하는 internal key는 $PGDATA/pg_tde 아래에 로컬로 저장되고, 이 internal key를 다시 암호화하는 principal key는 외부 KMS에 둡니다. principal key는 데이터베이스당 하나입니다. 검증에서는 KMS로 OpenBao를 Docker로 띄워 썼고, root 자격증명이 아니라 secret/ 경로에만 읽기/쓰기 권한을 준 최소 권한 토큰을 발급해 사용했습니다.

pgBackRest가 암호화된 클러스터를 다루는 흐름

pgBackRest 입장에서 보면, pg_tde가 이미 암호화해 놓은 데이터 파일과 WAL을 그대로 받아 저장소로 옮깁니다. 백업 도구는 그 안을 들여다보지 않습니다. 암호화는 PostgreSQL 쪽에서 끝나 있고, pgBackRest는 암호화된 바이트 덩어리를 운반하는 역할입니다.

중요한 지점은 복구 이후입니다. pgBackRest가 복구해 놓은 PGDATA는 여전히 암호화된 상태입니다. 이걸 PostgreSQL이 다시 읽으려면 internal key를 풀 principal key가 필요하고, principal key는 외부 KMS에 있습니다. 즉 백업 파일만 들고 있어서는 복구한 클러스터를 기동할 수 없고, KMS 접근이 함께 살아 있어야 합니다.

검증 결과와 주의점

Fercot는 pgbench로 부하를 주면서 full 백업과 incremental 백업을 뜨고, pgbench_tellers에서 1,000건을 삭제한 뒤 named restore point로 시점 복구(PITR)를 실행해 삭제된 1,000건이 되살아나는 것까지 확인했습니다. WAL 세그먼트와 데이터 파일은 백업 저장소 안에서도 암호화된 채 유지됐고, 복구 과정에서 별도의 복호화 래퍼 없이 named restore point에 깔끔하게 도달했습니다.

다만 암호화 특성 때문에 꺼야 하는 설정들이 있습니다. 정리하면 다음과 같습니다.

설정이유
archive-header-checkn암호화된 WAL 헤더를 pgBackRest가 해석하지 못합니다.
checksum-pagen암호화된 page의 checksum을 검증할 수 없습니다.
compress-typenone암호화된 데이터는 무작위에 가까워 압축 이득이 거의 없습니다.
repo1-blocknblock 단위 incremental의 효율이 암호화로 무력화됩니다.

표의 항목들은 모두 같은 원인에서 나옵니다. pgBackRest는 암호화된 내용을 들여다볼 수 없으므로, 데이터 내부를 읽어야 성립하는 검증과 최적화가 작동하지 않습니다. 그래서 page checksum 검증과 WAL 헤더 검증을 끄고, 압축도 끄는 편이 낫습니다. 압축을 켜 두면 줄어들지도 않을 데이터를 압축하느라 CPU만 씁니다.

한 가지 더, incremental 백업 크기가 예상보다 컸습니다. block 단위 incremental은 변경된 블록만 골라 담아 용량을 아끼는데, 암호화된 데이터에서는 이 절감 효과가 크게 줄어듭니다.

WAL 암호화 관련: 과거 Percona 문서는 암호화 환경에서 비동기 아카이빙(archive-async=y)을 권하지 않았습니다. 그러나 이번 검증에서는 비동기 아카이빙이 문제없이 작동했습니다. 운영에서 적용하기 전에는 사용하는 pg_tde 버전 기준으로 한 번 더 확인하는 편이 안전합니다.

키 관리 관점: 백업과 복구가 투명하게 돈다고 해서 백업만으로 복구가 끝나는 것은 아닙니다. 복구된 PGDATA는 암호화 상태 그대로이므로, principal key를 보관한 KMS에 접근하지 못하면 클러스터를 기동할 수 없습니다. 백업 파일과 KMS 접근 권한을 함께 보존하고, KMS 자체의 가용성과 백업도 별도로 챙겨야 합니다. 백업 저장소 한쪽만 살아남는 시나리오도 복구 절차에 반드시 포함해 두는 편이 좋습니다.

저장소 암호화 중복: pgBackRest 자체에도 저장소 암호화 옵션(repo1-cipher-type)이 있습니다. pg_tde가 이미 데이터를 암호화한 뒤 넘겨주므로 저장소 암호화는 선택 사항입니다. 다만 시스템 카탈로그처럼 pg_tde가 암호화하지 않는 영역이 백업에 포함되는 점을 고려하면, 저장소 암호화를 한 겹 더 두는 선택도 합리적입니다.

검증에는 Percona Server for PostgreSQL이 쓰였습니다. pg_tde가 특정 패치에 의존하기 때문에 표준 PostgreSQL이 아닌 Percona 배포판이 필요하고, pgBackRest가 버전을 제대로 인식하도록 pg-version-force로 버전을 강제해야 했습니다.

운영 관점과 백업 시리즈 연결

백업 도구를 고를 때는 도구 자체의 기능만 보기 쉽지만, 실제 운영에서는 암호화, 복제, 버전 같은 주변 환경과의 궁합이 더 자주 발목을 잡습니다. 이번 검증의 의미는 "pg_tde를 켜도 pgBackRest를 그대로 쓸 수 있다"는 점을 확인했다는 데 있습니다. 암호화 때문에 백업 도구를 새로 고민할 필요는 없고, 검증/압축 옵션 몇 개를 끄는 선에서 정리됩니다.

대신 복구 절차의 무게중심이 옮겨 갑니다. 평소처럼 백업 무결성만 점검하는 데서 그치지 말고, principal key를 가진 KMS까지 포함한 복구 리허설을 정기적으로 돌려야 합니다. 암호화를 도입하는 순간, 백업 전략은 "데이터 백업"에서 "데이터 백업 + 키 관리"로 확장됩니다.

pgBackRest를 운영에 들이는 과정 자체가 처음이라면, 이 블로그의 pgBackRest 도입기에서 기본 stanza 구성과 아카이빙 흐름을 먼저 잡고 오는 편이 좋아요. 암호화 궁합은 그 위에 얹는 한 겹이에요.

참고

Gemini CLI 종료와 판도

· 약 4분

Google이 2026년 6월 18일부터 무료, Pro, Ultra 등 비엔터프라이즈 사용자에게 Gemini CLI의 요청 처리를 중단한다고 공지했어요. 도구 자체를 삭제하는 게 아니라 이들 등급에서 백엔드가 더 이상 요청을 받지 않는 식이며, 5월 19일 공지가 나온 뒤 후속 안내가 GeekNews를 통해 국내에도 돌면서 다시 화제가 됐어요.

CLI 코딩 도구 글을 자주 쓰는 블로그 입장에서 이건 그냥 지나칠 소식이 아니에요. 무엇이 끝나는지부터 정확히 짚고, 그다음에 판도 이야기를 해보겠습니다.

정확히 무엇이 종료되나

부풀리지 않고 공지 그대로 정리하면 이렇습니다.

종료 시점은 2026년 6월 18일이며, Gemini CLI와 Gemini Code Assist IDE 확장의 요청 처리가 끊기는 등급은 Google AI Pro/Ultra 구독자, 개인용 무료 Gemini Code Assist 사용자, 무료/표준 등급의 GitHub 조직 사용자입니다. Gemini Code Assist Standard/Enterprise 라이선스 보유자와 유료 Gemini Agent Platform API 키 사용자는 그대로 쓸 수 있습니다. GitHub 확장은 6월 18일 이후 신규 설치가 막히고, 기존 설치도 이어지는 몇 주 안에 요청 처리가 끊깁니다.

정리하면 이번 변경의 범위는 비엔터프라이즈 등급의 백엔드 요청 처리 중단입니다. 도구가 통째로 사라지는 것은 아니고, 엔터프라이즈와 유료 API 경로는 그대로 남습니다.

Google이 밝힌 이유는 통합입니다. 사용자 워크플로가 초창기를 넘어섰고 이제 "여러 agent가 서로 통신하는" 멀티 agent 환경이 됐기 때문에, 하나의 플랫폼으로 묶는 편이 낫다는 설명입니다. 그 하나의 플랫폼이 Antigravity CLI입니다.

대체재와 이전 경로

대체재는 Antigravity CLI입니다. 5월 19일 공개됐고, Go로 작성돼 속도가 빠르고 비동기 멀티 agent 오케스트레이션을 지원한다고 합니다. Agent Skills, Hooks, Subagents, Extensions 같은 핵심 기능은 이어집니다.

마이그레이션 문서는 Google이 안내한 가이드 페이지에 올라와 있고, 영상 튜토리얼은 "몇 주 안에" 제공한다고 했습니다. 비엔터프라이즈 사용자에게 이전은 사실상 선택이 아니라 강제에 가깝습니다. 6월 18일 이후 기존 경로가 막히기 때문입니다.

한 가지 짚을 점이 있습니다. Gemini CLI 저장소 자체는 Apache 2.0 라이선스 그대로 GitHub에 남습니다. 라이선스가 바뀌거나 코드가 내려가는 건 아닙니다. 다만 비엔터프라이즈 백엔드가 요청을 받지 않으면, 일반 사용자에게는 코드만 남고 실제로는 돌릴 수 없는 박제에 가까워집니다. 반면 후속작인 Antigravity CLI는 클로즈드 소스입니다. 공개된 GitHub 페이지에는 changelog, readme, GIF 정도만 있고 실제 코드는 없습니다.

이 지점이 커뮤니티 반발의 핵심입니다. Gemini CLI는 오픈소스로 출발해 10만 개 넘는 star와 6,000건 이상의 외부 기여 PR을 모았는데, 그 기여가 결국 클로즈드 소스 후속작을 살찌우는 데 쓰였다는 인식입니다. 오픈소스에서 출발해 클로즈드로 넘어가는 흐름, 그리고 무료 등급의 빠듯한 사용량 한도가 함께 도마에 올랐습니다.

CLI 코딩 도구 판도 관점

여기서 한 발 물러나 판을 보겠습니다. CLI에서 도는 AI 코딩 도구는 지난 1~2년 사이에 빠르게 늘었습니다. Anthropic의 Claude Code, OpenAI 계열 도구, 그리고 Google의 Gemini CLI가 비슷한 시기에 비슷한 형태로 등장했습니다. 터미널에 상주하면서 코드베이스를 읽고 고치고 명령을 실행하는 형태입니다.

지금 벌어지는 건 그 도구들이 각자 다른 길을 고르는 장면입니다.

Google의 선택은 "접고 통합"입니다. 개별 CLI 제품을 유지하기보다 멀티 agent 플랫폼 하나로 묶고, 무료 등급은 정리하고 유료/엔터프라이즈 경로를 남깁니다. 멀티 agent라는 다음 단계에 자원을 몰겠다는 판단입니다. 한편 Gemini CLI를 굴리던 무료 사용자층은 한도와 강제 이전을 동시에 마주하게 됐습니다.

누구는 접고 누구는 키우는 이유를 한 줄로 단정하긴 어렵습니다. 다만 드러나는 차이는 있습니다. 도구를 단품으로 계속 끌고 갈지, 아니면 더 큰 플랫폼의 입구로 재배치할지의 갈림길입니다. Google은 후자를 골랐고, 그 과정에서 오픈소스로 모은 무료 사용자층과 기여자 커뮤니티가 정리 대상에 올랐습니다.

특정 도구가 더 낫다는 이야기를 하려는 게 아니며, 무료로 쓰던 CLI 도구가 어느 날 등급별로 갈리고 후속작으로 강제 이전될 수 있다는 점과 오픈소스 라이선스가 그대로여도 백엔드가 끊기면 일반 사용자에게는 의미가 달라진다는 점이 이번 사례에서 챙겨둘 두 가지예요. CLI 코딩 도구를 업무에 깊이 엮어뒀다면 백엔드 의존성과 등급 정책을 한 번쯤 점검해 둘 만해요.

참고

Project Glasswing

· 약 5분

Anthropic이 자사 비공개 모델 Claude Mythos를 약 150개 조직에 추가로 풀어, 전력, 수도, 의료, 통신 같은 핵심 인프라의 소프트웨어 취약점을 찾는 Project Glasswing을 15개국 이상으로 확대했어요. 6월 2일자 발표 기준이고, 4월에 미국 정부를 포함한 50여 개 파트너로 시작한 프로그램을 한 단계 키운 것이에요.

제가 이 블로그에서 Copy Fail, NGINX Rift, DirtyDecrypt 같은 CVE를 다룰 때마다 깔려 있던 전제가 하나 있었어요. 취약점은 사람이 찾는다는 것입니다. 그 전제가 지금 흔들리고 있습니다.

Project Glasswing과 Claude Mythos가 무엇인가

Claude Mythos는 Anthropic이 일반에 공개하지 않은 프리뷰 모델입니다. Anthropic은 이 모델이 코드에서 취약점을 찾고 익스플로잇을 짜는 능력에서 극소수 최상위 인간 보안 연구자를 제외한 거의 모두를 앞선다고 설명합니다. 몇 주 단위로 수천 개의 제로데이를 찾아낼 수 있다는 것이 핵심 주장입니다.

Project Glasswing은 이 모델을 통제된 형태로 파트너 조직에 제공하는 프로그램입니다. 파트너는 Mythos를 받아 자기 코드베이스를 스캔하고, 취약점을 식별하고, 패치를 작성하고, 릴리스 전 점검까지 돌립니다. 발표에 따르면 실제 활용 범위는 다음과 같습니다.

  • 취약점 패치 작성과 테스트
  • 릴리스 전 소프트웨어 검증
  • 침투 테스트
  • 위협 탐지
  • 메모리 안전 언어로의 코드 번역

흥미로운 대목은 Anthropic이 이 모델을 일반에 공개하지 않겠다고 못 박았다는 점입니다. 이런 사이버 능력이 악용되는 것을 막을 안전장치가 아직 충분히 갖춰지지 않았고, 자사를 포함한 어떤 AI 개발사도 그 수준에 이르지 못했다는 이유입니다. 취약점을 잘 찾는 능력은 방어에도 쓰이지만 공격에도 그대로 쓰입니다. 이중 용도 문제를 정면으로 인정한 셈입니다.

어디에 적용됐고, 무엇을 찾아냈나

확대된 명단에는 전력, 수도, 의료, 통신, 그리고 하드웨어 벤더와 오픈소스 메인테이너가 들어갑니다. 초기 50개 파트너 그룹에서는 상대적으로 빠져 있던 영역이라는 게 Anthropic의 설명입니다. 국가는 미국 외에 호주, 캐나다, 프랑스, 독일, 이탈리아, 스위스, 네덜란드, 스페인, 벨기에, 스웨덴, 인도, 일본, 뉴질랜드, 그리고 한국이 포함됐습니다. 접근 권한이 확인된 조직으로는 Okta, Samsung, SK Hynix, SK Telecom, NATO, EU 사이버보안 기관 ENISA 등이 거론됐습니다.

Anthropic은 확대 우선순위를 정한 기준을 이렇게 밝혔습니다.

파트너 대부분은 한 번의 대규모 공격으로 1억 명 이상이 피해를 입을 수 있다고 본다. 세계 안보와 각국 안보 양쪽에 중대한 영향을 미친다.

규모 수치는 출처에 나온 것만 정리하면 다음과 같습니다.

항목수치
발견된 고위험/심각 취약점10,000건 이상
스캔한 오픈소스 프로젝트1,000개 이상
전체 발견 이슈23,019건
그중 고위험/심각 등급6,202건
Anthropic + 외부 6개 보안업체가 검증한 건1,752건
검증된 건의 진짜 양성(true positive) 비율90% 초과

프로그램은 2026년 4월 초에 시작했습니다. 구체적 사례로 Cloudflare와 Mozilla가 자사 코드베이스에서 각각 수백 건의 취약점을 발견했다고 언급됐습니다. 또 수십억 대 기기가 쓰는 암호 라이브러리 wolfSSL에서 인증서 위조 공격으로 이어질 수 있는 결함을 Mythos가 짚어낸 사례도 공개됐습니다.

방어자에게 이것은 무엇을 의미하나

겉으로 드러난 그림은 방어자에게 유리합니다. 취약점을 찾는 비용이 급격히 떨어지면, 자기 코드를 먼저 점검하는 쪽이 더 많은 구멍을 더 빨리 메울 수 있습니다. Anthropic이 내세우는 목표 자체가 "방어자에게 영구적 우위"를 만드는 것입니다. 더 싼 AI 모델이 공격자 손에 들어가기 전에 방어 쪽이 앞서가야 한다는 논리입니다.

하지만 이 그림에는 균형추가 필요합니다.

첫째, 찾는 것과 고치는 것은 다른 문제입니다. Anthropic 스스로 인정한 병목이 바로 여기에 있습니다. 취약점을 찾기는 쉬워졌는데, 검증하고 공개하고 패치하는 일은 여전히 사람의 몫이고 느립니다. 23,019건을 찾아냈지만 검증된 건은 1,752건입니다. 나머지는 누군가 일일이 분류하고 확인해야 합니다. 진짜 양성 비율이 90%를 넘는다는 건 바꿔 말하면 10건 가까이를 외부 보안업체 여섯 곳까지 동원해 검증했다는 뜻이기도 합니다. 자동 탐지가 뱉어낸 결과는 곧바로 믿을 수 있는 결론이라기보다, 사람이 처리해야 할 대기열에 가깝습니다.

둘째, 부담이 특정 지점에 쏠립니다. 특히 오픈소스 메인테이너가 그렇습니다. 많은 프로젝트가 소수의 자원봉사자로 굴러갑니다. 여기에 AI가 쏟아내는 취약점 리포트가 밀려들면, 그 자체가 새로운 운영 부하가 됩니다. Anthropic도 이 긴장을 알고 있어서, 메인테이너가 리포트를 더 빨리 분류할 수 있도록 Mythos를 활용하는 방안과 오픈소스 취약점 보고 모범 사례 공개를 검토 중이라고 밝혔습니다. 도구가 만든 문제를 같은 도구로 풀겠다는 접근인데, 효과는 지켜봐야 합니다.

셋째, 이중 용도 위험은 사라지지 않고 미뤄졌을 뿐입니다. Anthropic은 Mythos급 모델을 일반 공개하지 않겠다고 했지만, 동시에 "앞으로 몇 주 안에" 모든 고객에게 Mythos급 모델을 제공할 것으로 본다고 말합니다. 경쟁사도 비슷한 방향입니다. 같은 기간 OpenAI는 사이버보안 특화 모델 GPT-5.5-Cyber를 다수 테스트 파트너에 배포했습니다. 방어자가 먼저 쓰는 동안 공격자도 비슷한 능력에 다가가고 있다는 뜻이고, "영구적 우위"라는 표현은 마케팅 문구에 가깝게 들립니다.

정리하면, 운영/보안 관점에서 실질적으로 바뀌는 건 탐지 단계의 처리량입니다. 그 뒤의 검증, 분류, 패치, 배포는 여전히 사람과 조직의 역량에 묶여 있고, 오히려 탐지가 빨라질수록 이쪽 병목이 더 도드라집니다. AI 취약점 탐지를 도입한다면 모델 성능보다 우리 조직이 늘어난 발견 건수를 소화할 분류/패치 파이프라인을 갖췄는지를 먼저 점검해야 합니다.

탐지에서 패치까지, 병목은 뒤쪽에 있다

탐지는 싸지고 빨라졌고, 그래서 무게중심이 도식의 아래쪽, 사람이 붙어야 하는 검증과 패치/배포로 옮겨갔어요. Project Glasswing이 던지는 진짜 질문은 "AI가 취약점을 찾을 수 있는가"보다 "찾아낸 것을 우리가 감당할 수 있는가"에 가까워요.


참고:

Aurora MySQL 8.4와 Kiro

· 약 6분

한 주에 겹친 세 건

Aurora MySQL 8.4가 정식 출시(GA)되어 커뮤니티 MySQL 8.4 LTS와 버전 번호가 직접 맞춰졌고, 같은 흐름에서 Aurora MySQL이 Kiro Powers와 통합되어 자연어로 데이터베이스 작업을 거는 길이 열렸어요. 2026년 6월 1일 AWS Weekly Roundup이 전한 두 갈래예요.

여기에 그 주의 헤드라인 발표로 Amazon Bedrock과 AWS의 Claude Platform에서 Claude Opus 4.8을 쓸 수 있게 됐다는 소식이 얹혔습니다. DBA 입장에서 흘려 넘기기 쉬운 발표 묶음이지만, 세 가지를 한 줄에 꿰면 클라우드 데이터베이스가 어디로 가는지가 보입니다.

Aurora MySQL 8.4 GA가 실무에서 바꾸는 것

가장 실무적인 변화는 버전 번호 정책입니다. Aurora MySQL 8.4는 Aurora가 커뮤니티 MySQL의 LTS(Long Term Support) 메이저 릴리스에 정렬되는 첫 버전입니다. MySQL 8.4가 커뮤니티 MySQL의 첫 LTS 메이저이고, Aurora MySQL 8.4가 그 정렬을 처음 적용한 Aurora 메이저입니다. 커뮤니티 MySQL 8.4.7과 호환됩니다.

이게 왜 중요합니까. 예전에는 Aurora MySQL 메이저 번호와 커뮤니티 MySQL 버전이 따로 놀았습니다. 자체 관리 MySQL이나 Amazon RDS for MySQL에서 Aurora로 마이그레이션할 때, 두 체계 사이를 머릿속으로 번역해야 했습니다. 8.4부터는 Aurora에서 돌리는 번호가 곧 호환되는 커뮤니티 MySQL 버전입니다. 번역 부담이 사라집니다.

LTS 정렬이 가져오는 두 번째 효과는 안정성입니다. 커뮤니티 MySQL LTS 메이저는 최초 릴리스 이후 버그 수정과 보안 패치만 받습니다. 그래서 Aurora MySQL 8.4 위에서 도는 애플리케이션은 minor 업그레이드를 거쳐도 동작이 일관되리라 기대해도 됩니다. Aurora는 그 위에 새 기능을 minor 버전으로 계속 얹습니다. 패치 관리도 단순해집니다. minor 안에서의 patch 버전은 AWS가 대신 관리하고, Aurora가 해당 minor의 최신 patch로 자동으로 올라갑니다.

릴리스 주기도 명시됐습니다. Aurora는 커뮤니티 MySQL LTS 릴리스 후 12개월 안에 메이저를, 각 커뮤니티 minor 후 3개월 안에 minor를, 그리고 각 메이저 후 12개월 안에 Aurora LTS minor를 목표로 합니다.

보안 기본값도 신규 클러스터 기준으로 단단해졌습니다.

항목8.4 신규 클러스터 기본값
인증 플러그인caching_sha2_password (기존 mysql_native_password 대체, 레거시는 호환용으로 유지)
전송 보안require_secure_transport 기본 활성 — 모든 연결에 TLS 요구
TLS 버전TLS 1.2 / 1.3만 지원 (1.0 / 1.1 제거)
비밀번호 정책DB 클러스터 파라미터로 복잡도/사용자명 검증 규칙 지정 가능

마이그레이션 경로는 RDS Blue/Green Deployments, in-place 업그레이드, 스냅샷 복원, AWS DMS, Percona XtraBackup 물리 마이그레이션까지 폭넓게 열려 있습니다. 8.4는 Aurora MySQL이 제공되는 모든 AWS 리전에서 곧바로 제공됩니다.

기존 클러스터를 8.4로 올릴 계획이라면, 엔진 기능보다 먼저 챙길 것이 이 보안 기본값입니다. TLS 강제와 caching_sha2_password는 오래된 드라이버나 connection 설정에서 연결이 끊기는 원인이 될 수 있습니다. 마이그레이션 전 검증 단계에서 클라이언트 호환성을 먼저 확인하는 편이 안전합니다.

Kiro Powers로 실제 할 수 있는 일

"자연어로 DB를 만진다"는 문구는 마케팅처럼 들리기 쉽습니다. 실체를 보면 생각보다 구체적입니다.

Kiro Powers는 미리 묶어둔 MCP 서버, steering 파일, hook을 모아둔 큐레이션 저장소입니다. Kiro 파트너가 검증한 묶음이며, 특정 용도를 빠르게 붙여 쓰도록 만들어졌습니다. Aurora MySQL 통합은 이 저장소에서 Aurora MySQL용 묶음을 끌어다 쓰는 방식입니다.

개발자가 할 수 있는 일은 두 평면으로 나뉩니다.

  • data plane — 쿼리, 스키마 관리 같은 데이터 작업
  • control plane — 클러스터 관리 같은 인프라 작업

둘 다 자연어로 지시합니다. "Serverless 스케일링을 어떻게 잡아야 하나", "RDS에서 Aurora로 어떻게 마이그레이션하나", "replication을 어떻게 설정하나" 같은 질문에 상황에 맞춘 가이드를 돌려줍니다.

여기서 오해하면 안 되는 지점이 있습니다. 에이전트가 자연어를 받아 곧장 운영 클러스터에 손을 대는 게 아닙니다. 에이전트는 API 호출, SQL, 설정값을 만들어 보여주고, 사람이 검토한 뒤 실행합니다. 마지막 방아쇠는 여전히 사람이 당깁니다. 설치는 Kiro IDE나 웹페이지에서 원클릭으로 끝납니다.

즉 Kiro Powers가 줄여주는 것은 "어떤 API를 어떤 순서로, 어떤 파라미터로 부를지"를 문서 뒤지며 조립하는 시간입니다. 실행 권한과 책임은 그대로 DBA에게 남습니다.

클라우드 DB의 AI 통합 흐름

이 발표를 단독으로 보면 기능 하나가 늘어난 것입니다. 같은 시기 다른 발표와 묶으면 흐름이 드러납니다.

바로 며칠 전 Google Cloud는 AlloyDB Remote MCP Server를 정식 출시했습니다. AI 에이전트가 표준 프로토콜로 PostgreSQL 호환 데이터베이스에 직접 붙어 SQL을 실행하고 인스턴스를 관리하도록 길을 연 발표입니다. 이 건은 AlloyDB가 AI 에이전트에 문을 열다에서 따로 다뤘습니다.

두 발표는 접근 방식이 조금 다릅니다. AlloyDB는 클라우드가 직접 관리형으로 호스팅하는 remote MCP 엔드포인트를 노출해, 에이전트가 그 엔드포인트로 붙습니다. Aurora MySQL은 개발 환경(Kiro IDE)에 MCP 서버 묶음을 설치해, IDE 안의 에이전트가 작업을 조립하도록 합니다.

항목AlloyDB Remote MCPAurora MySQL + Kiro Powers
호스팅클라우드 관리형 원격 엔드포인트Kiro IDE에 설치하는 MCP 묶음
진입점인증된 에이전트가 엔드포인트로 접속IDE 안의 에이전트가 도구 호출
공통점MCP 표준으로 DB에 자연어 인터페이스 부착MCP 표준으로 DB에 자연어 인터페이스 부착

공통 메시지는 분명합니다. 주요 클라우드 데이터베이스가 MCP를 공통 규약으로 삼아 AI 에이전트에 인터페이스를 여는 중입니다. 데이터 작업뿐 아니라 클러스터 관리 같은 control plane까지 자연어 대상으로 들어왔습니다. 1년 전이라면 콘솔이나 CLI로만 하던 일입니다.

세 발표를 DBA 시선으로 묶으면

세 발표를 DBA 시선으로 정리하면 이렇습니다.

첫째, Aurora MySQL 8.4 GA는 버전 관리가 단순해진다는 실용적 이득이 가장 큽니다. 커뮤니티 MySQL과 번호가 같아지니 마이그레이션 계획서에서 버전 매핑 표가 사라집니다. 다만 보안 기본값이 바뀐 만큼, 업그레이드는 클라이언트 호환성 검증을 끼고 진행해야 합니다.

둘째, Kiro Powers는 생산성 도구이지 자동 운영 도구가 아닙니다. 에이전트가 초안을 만들고 사람이 실행하는 구조라, 검토 없이 적용되는 위험은 설계상 막혀 있습니다. 그래도 운영 계정 자격증명이 에이전트의 작업 흐름과 맞닿는 만큼, 어떤 권한으로 어떤 클러스터에 접근할 수 있는지는 미리 좁혀두는 편이 좋습니다.

셋째, Bedrock의 Claude Opus 4.8은 이 흐름에서 엔진에 해당하는 변화입니다. AWS는 이 모델을 agentic coding과 knowledge work, 긴 자율 작업을 겨냥해 만든 모델로 소개했습니다. 더 긴 자율 세션을 이어가고, 오류에서 스스로 복구하며, 엔지니어처럼 코드베이스를 읽고 편집에 앞서 계획을 세운다는 설명입니다. Bedrock에서는 Guardrails, Knowledge Bases, 데이터 거주(data residency) 같은 AWS 관리 기능과 함께 씁니다. 데이터베이스 작업을 다루는 에이전트의 추론 강도가 올라간다는 뜻이고, 그만큼 사람이 검토 경계를 어디에 둘지가 더 중요해집니다.

결국 이번 묶음이 그리는 그림은 AI가 DB를 대신 운영하는 쪽이 아니에요. 조립과 탐색은 에이전트가 빠르게 맡고, 실행과 책임은 사람에게 남는 구도에 가까워요. DBA가 챙길 일은 줄지 않았고, 검토할 초안의 품질이 좋아졌을 뿐이에요.

참고

Oracle 월간 CSPU 전환

· 약 8분

Oracle이 20년 넘게 유지해 온 분기 Critical Patch Update(CPU) 체제 위에 매달 발행하는 Critical Security Patch Update(CSPU)를 얹었습니다. 그 첫 릴리스가 2026년 5월 28일에 나왔습니다.

분기 CPU는 그대로 1, 4, 7, 10월에 누적본으로 나옵니다. CSPU는 그 사이 달에 셋째 화요일마다 끼어드는 소규모/고우선 전용 패치입니다. 첫 CSPU는 CVE 35건을 담았고, 그중 하나는 CVSS 10.0이었습니다. Oracle이 분기 리듬을 깨고 빠른 차선을 새로 낸 이유를 Oracle Security Blog의 공지와 DBA 관점에서 정리합니다.

20년간 이어진 분기 CPU

Oracle의 분기 CPU는 DBA에게 익숙한 행사입니다. 매년 1, 4, 7, 10월 셋째 화요일에, Oracle의 전 제품군에 걸친 보안 수정이 한 묶음으로 떨어집니다. 한 번에 수백 건이 쏟아지는 게 특징입니다. 바로 직전인 2026년 4월 CPU만 해도 450건의 취약점을 한꺼번에 고쳤습니다.

이 모델의 핵심은 누적(cumulative)이라는 점입니다. 가장 최신 CPU 하나에 그 이전의 모든 수정이 포함되므로, DBA는 사실상 최신 CPU 한 개만 적용하면 됩니다. 관리가 단순하다는 장점은 분명합니다.

문제는 주기입니다. 1월에 발표된 취약점을 표준 절차로 막으려면 4월 CPU까지 최대 석 달을 기다려야 합니다. 그 석 달 동안 취약점은 공격자에게 열린 창으로 남습니다.

사이를 메우는 월간 CSPU

CSPU는 그 창을 좁히는 장치입니다. 분기 CPU를 대체하지 않고 사이를 메웁니다.

  • 발행 주기: 분기 CPU가 없는 달의 셋째 화요일 — 2, 3, 5, 6, 8, 9, 11, 12월
  • 성격: 전 제품군을 훑는 게 아니라, 즉시 대응이 필요하다고 Oracle이 판단한 소수 항목만 추린 묶음
  • 사전 예고: 각 CSPU 발행 직전 목요일(T-5)에 미리 공지

분기 CPU 4회와 CSPU 8회를 합치면, DBA는 1년에 12번의 예측 가능한 패치 이벤트를 갖게 됩니다(Oracle). 사실상 월 1회 리듬입니다.

분기 CPU vs 월간 CSPU

둘은 목적이 다릅니다. 나란히 놓으면 역할이 분명해집니다.

항목분기 CPU월간 CSPU
발행 시점1, 4, 7, 10월 셋째 화요일2, 3, 5, 6, 8, 9, 11, 12월 셋째 화요일
연간 횟수4회8회
범위전 제품군 전수고우선 항목만 선별
규모수백 건 (4월 450건)소규모 (5월 35건)
누적 여부누적 (최신본 하나면 됨)비누적 (개별 적용)
사전 예고발행 전 목요일발행 전 목요일

여기서 DBA가 놓치면 안 되는 한 가지가 있습니다. CSPU는 비누적이지만, 다음 분기 CPU가 그동안의 CSPU 수정을 모두 빨아들인다는 점입니다. 즉 CSPU를 적용하지 않고 넘어갔더라도 다음 분기 CPU를 적용하면 그 사이 CSPU 수정이 따라옵니다 — 다만 그때까지 노출 창이 길어질 뿐입니다.

5월 28일, 첫 CSPU의 내용

첫 CSPU는 새 CVE 35건을 담았습니다(Oracle Security Blog). 분기 CPU의 수백 건과 비교하면 의도적으로 작은 묶음입니다. 제품군별 분포는 다음과 같습니다.

제품군패치 수
Oracle E-Business Suite12
Oracle REST Data Services (ORDS)11
Oracle Communications Unified Assurance8
Oracle Database Server3
Oracle Hospitality OPERA 51

심각도가 가볍지 않습니다. 가장 눈에 띄는 건 ORDS의 CVE-2026-46840으로, CVSS 10.0 만점입니다. 기밀성, 무결성, 가용성이 모두 완전히 무너지는 등급입니다. E-Business Suite에도 CVSS 9.8~9.9급이 여러 건 있었고, Hospitality OPERA 5의 CVE-2026-34311은 9.8이었습니다.

집계 기준도 짚어 둘 필요가 있습니다. 새 CVE는 35건이지만, Communications 제품군에 들어간 서드파티 컴포넌트 CVE까지 합치면 이번 CSPU가 처리한 취약점은 모두 77건입니다(SecurityWeek). 그중 상당수는 인증 없이 원격으로 악용할 수 있었습니다. ORDS 7건, Communications 4건, E-Business Suite/Database Server 각 3건이 인증 없는 원격 공격에 그대로 열려 있었습니다.

묶음이 작다고 가벼운 것은 아닙니다. 오히려 분기까지 기다릴 수 없다고 Oracle이 판단한 항목만 골라 담았기 때문에, 평균 심각도는 분기 CPU보다 높다고 봐야 합니다.

20년 리듬을 깬 배경

이 블로그가 주목하는 지점이 여기입니다. Oracle이 20년 넘게 지켜 온 분기 리듬을 굳이 깬 배경에는, 취약점이 발견되는 속도 자체가 달라졌다는 인식이 깔려 있습니다.

Oracle Database 업그레이드를 총괄하는 Mike Dietrich(마이크 디트리히)는 이 변화를 AI 기반 위협에 대한 대응으로 명시했습니다. 그는 AI 모델이 이전과 비교가 안 되는 속도로 취약점을 찾아내고 있으며, Oracle 자체도 Anthropic과 OpenAI의 모델을 취약점 탐지에 활용하고 있다고 밝혔습니다. 발견 속도가 빨라지면 노출 창을 그만큼 줄여야 한다는 게 그의 논리입니다.

이건 지난달 Copy Fail 글에서 다룬 흐름과 정확히 같은 줄기입니다. AI 코드 감사기가 10년 묵은 커널 버그를 한 시간 만에 찾아낸 사건은, 방어자에게 한 가지를 분명히 일러 줬습니다. 오늘 멀쩡해 보이는 코드가 내일도 멀쩡하리라고 가정할 수 없다는 것입니다. 취약점이 더 빨리, 더 많이 드러나는 시대에는 패치 사이클도 그만큼 짧아져야 합니다.

분기에서 월간으로의 전환은 그 압력에 벤더가 내놓은 응답입니다. 발견과 패치 사이의 간격을 구조적으로 좁히려는 시도입니다.

[과거] 분기 모델
취약점 발견 ───────── 최대 3개월 ─────────▶ CPU 적용
(열린 창)

[현재] 월간 + 분기 모델
취약점 발견 ─── 최대 1개월 ───▶ CSPU 적용
(좁힌 창)

DBA가 지금 해야 할 일

패치 주기가 4배로 잦아졌다는 건, 운영 부담도 그만큼 늘었다는 뜻입니다. 12번을 모두 같은 속도로 따라가면 검증과 변경 관리가 무너집니다. 그래서 차선을 나눠 대응해야 합니다.

1) 패치 차선을 risk로 나눈다

모든 CSPU를 같은 속도로 처리할 필요는 없습니다. 인터넷에 노출된 ORDS/E-Business Suite처럼 공격 표면이 넓은 자산은 긴급 차선, 내부망 전용 DB는 표준 차선으로 분류합니다. 5월 CSPU의 ORDS CVSS 10.0 같은 항목은 자산 분류와 무관하게 즉시 차선입니다.

2) T-5 목요일 예고에 계획을 건다

Oracle이 발행 5일 전 목요일에 미리 알려 주므로, 화요일 발행을 기다리지 말고 목요일 예고로 영향 자산을 먼저 추립니다. 발행 당일에 시작하면 이미 늦습니다.

3) 회귀 테스트를 가볍고 결정론적으로 만든다

월 1회 리듬에서는 매번 광범위한 수동 검증을 붙일 여유가 없습니다. 핵심 쿼리, 배치, 연동 지점만 자동으로 돌려 확인하는 최소 세트를 미리 갖춰 둬야 패치 주기를 따라갈 수 있습니다.

4) 우회책에 기대지 않는다

Dietrich의 표현을 빌리면, virtual patching처럼 임시방편에 의존하는 건 보안이 아니라 심리적 위안에 가깝습니다. 결국 정식 패치를 빠르게 적용할 수 있는 체계를 만드는 게 유일한 답입니다.

이 변화가 남기는 신호

이번 변화의 의미는 단순히 "Oracle 패치가 잦아졌다"가 아닙니다. 보안 패치의 기본 단위가 분기에서 월로 바뀌는 흐름이 메이저 DB 벤더에서 시작됐다는 신호입니다.

Microsoft는 오래전부터 매달 둘째 화요일 Patch Tuesday를 돌려 왔습니다. 리눅스 배포판들은 CVE가 뜨면 며칠 안에 안정 커널을 내놓습니다. 분기라는 긴 호흡을 고수하던 Oracle마저 월간 차선을 열었다는 건, AI가 취약점 발견 속도를 끌어올린 환경에서 분기 주기로는 더 이상 버틸 수 없다는 업계의 공통 인식에 합류했다는 뜻입니다.

DBA에게 이 흐름의 결론은 명확합니다. 패치를 분기에 한 번 몰아서 하는 행사가 아니라 상시로 도는 프로세스로 다시 설계해야 합니다. CSPU는 그 전환을 강제하는 첫 신호예요.

정리

  • Oracle이 분기 CPU에 더해 매달 셋째 화요일 CSPU를 발행하기 시작했습니다. 첫 릴리스는 2026년 5월 28일입니다.
  • CSPU는 CPU를 대체하지 않고 사이 달을 메우는 소규모/고우선 패치입니다. 분기 CPU는 누적, CSPU는 비누적입니다.
  • 첫 CSPU는 CVE 35건, ORDS의 CVSS 10.0(CVE-2026-46840)을 포함한 고심각도 항목 중심이었습니다.
  • 전환의 배경은 AI가 끌어올린 취약점 발견 속도 — 발견과 패치 사이 창을 구조적으로 좁히려는 응답입니다.
  • DBA는 패치를 분기 행사가 아니라 상시 프로세스로 재설계하고, risk 기준으로 차선을 나눠야 합니다.

참고

Neon 백엔드 플랫폼 확장

· 약 7분

짧게 먼저

2026-05-28, Neon(네온)이 "우리는 앱과 agent를 위한 boring backend를 만든다"는 글을 내고 같은 주 changelog로 세 가지 신규 서비스를 예고했어요. PostgreSQL 한 제품으로 출발한 회사가 자기 무기인 branch를 데이터베이스 밖으로 끌고 나가, 스토리지와 compute와 AI 라우팅까지 같은 모델로 묶기 시작했어요.

세 서비스는 오브젝트 스토리지(Object Storage), 서버리스 compute(Compute), AI Gateway입니다. 셋 다 아직 "coming soon"이지만 방향은 분명합니다. Neon은 더 이상 자기를 "서버리스 PostgreSQL"로만 규정하지 않습니다. PostgreSQL 30년 산업사 글에서 정리한 "클라우드 베어의 시대" 흐름이, 이번에는 PostgreSQL 회사 한 곳이 백엔드 플랫폼으로 몸집을 키우는 형태로 다시 나타났습니다.

예고된 세 가지 서비스

발표 내용을 사실 단위로 끊어 봅니다. 1차 출처는 Neon 공식 블로그(Bryan Clark, VP Product)와 changelog입니다.

서비스상태한 줄 정의핵심 성질
Database출시됨서버리스 PostgreSQLbranch/서버리스의 출발점
Auth출시됨내장 인증백엔드 기본 블록
Data API출시됨REST/HTTP 접근코드 없이 데이터 노출
Object Storagecoming soonDB와 함께 branch되는 S3 호환 스토리지DB/파일 상태를 branch마다 동기화
Computecoming soonDB 옆에 붙는 서버리스 compute인프라 관리 없이 함께 확장
AI Gatewaycoming soon모델 라우팅, 로깅, 비용 통제Databricks 인프라 위에 구동

세 신규 서비스를 묶는 한 문장은 Neon이 직접 말합니다. 모든 서비스가 "instant, branchable, serverless"라는 것입니다. branch가 DB만의 기능이 아니라 플랫폼 전체의 기본 동작이 된다는 선언입니다.

AI Gateway 쪽에는 숫자 하나가 붙습니다. Neon은 이 Gateway가 "Databricks에서 월 125조 토큰을 처리하는 같은 인프라 위에 올라간다"고 적었습니다. 2025년 5월 Databricks(데이터브릭스)가 Neon을 인수한 뒤, 모회사의 운영 규모를 그대로 끌어쓰는 자리입니다.

1초 만에 끝나는 branch의 원리

이 발표를 이해하려면 Neon의 branch가 어떻게 동작하는지부터 짚어야 합니다. 일반적인 PostgreSQL 호스팅에서 "테스트용 사본"을 만들려면 pg_dump로 받아 다른 인스턴스에 복원하거나, 스냅샷에서 새 볼륨을 띄웁니다. 데이터가 클수록 시간과 비용이 선형으로 늘어납니다.

Neon의 branch는 다릅니다. storage 계층에서 copy-on-write로 동작합니다. branch를 만드는 순간 데이터를 복사하지 않고, 부모 branch의 WAL 히스토리 특정 시점을 가리키는 메타데이터 포인터만 만듭니다. 페이지는 수정될 때 비로소 branch 쪽에 따로 기록됩니다. 그래서 branch 생성은 데이터 크기와 무관하게 O(1)이고, 1초 안에 끝납니다.

Neon은 이 branch가 하루에 수천만 개씩 생성된다고 밝혔습니다. 사람이 만드는 양이 아닙니다. CI에서 PR마다, agent가 작업마다 격리된 환경을 띄웠다 지우는 패턴이 깔려 있다는 뜻입니다. branch를 "만들고 쓰고 버리는" 일회성 자원으로 보는 시각이 이미 자리 잡았습니다.

branch가 DB 밖으로 나간다는 것

이번 발표가 겨냥한 지점이 여기입니다. branch가 데이터베이스 안에만 있으면 반쪽짜리입니다. 현실의 애플리케이션은 DB만으로 돌지 않습니다 — 업로드된 파일은 오브젝트 스토리지에 있고, 백그라운드 작업은 compute에서 돌며, AI 기능은 외부 모델을 호출합니다. DB만 branch되고 나머지가 production을 공유하면, 격리는 깨집니다.

예를 들어 보겠습니다. 결제 영수증 PDF를 S3에 올리는 기능을 고치는 중이라고 가정하겠습니다. DB는 branch로 격리했는데 스토리지는 production 버킷을 그대로 쓴다면, 테스트로 만든 가짜 영수증이 실제 버킷에 섞입니다. compute도 마찬가지입니다. branch DB를 바라봐야 할 워커가 production 큐를 집어 들면 격리가 무의미해집니다.

Neon의 답은 단순합니다. branch를 만들 때 DB뿐 아니라 스토리지/compute가 함께 갈라지게 합니다. 오브젝트 스토리지는 "DB와 함께 branch되어 모든 branch에서 데이터와 스토리지가 동기 상태를 유지"하고, compute는 "DB 옆에 배치되는 서버리스" 형태로 같이 따라옵니다.

같은 copy-on-write 사고를 백엔드 기본 블록 전체로 넓힌 것입니다. DB 한 줄만 격리하던 환경이, 이제 파일과 연산까지 통째로 격리되는 환경으로 넓어집니다.

직접 굴리는 조합과 갈리는 지점

운영자 시각에서 차이를 표로 정리합니다. 비교 대상은 "직접 굴리는 PostgreSQL + 별도 오브젝트 스토리지 + 별도 워커"의 전통 조합입니다.

항목전통 PG 호스팅 조합Neon 백엔드 플랫폼
DB 사본 생성pg_dump/스냅샷, 크기에 비례branch, 1초/O(1)
스토리지 격리버킷 수동 분리/복사DB와 함께 자동 branch
compute 격리별도 인스턴스 프로비저닝DB 옆 서버리스 자동
AI 모델 호출직접 연동/자체 비용 추적Gateway가 라우팅, 로깅, 비용 통제
환경 단위DB, 스토리지, compute 각각branch 하나로 묶음
통합 책임운영자가 봉합플랫폼이 봉합

전통 조합은 각 계층을 운영자가 직접 잇습니다. 그만큼 통제권은 크지만, 환경 하나를 새로 깔 때마다 손이 많이 갑니다. Neon은 그 봉합을 플랫폼이 가져가는 대신 계층 선택의 자유를 줄입니다. 어느 쪽이 맞는지는 워크로드가 정하고, 여기에는 분명한 lock-in 비용이 따릅니다.

편의를 얻는 만큼 묶이는 비용을 계산한다

플랫폼이 편의를 가져가면 그만큼 묶이는 비용이 생깁니다. 운영자 관점에서 짚을 지점을 추립니다.

  • lock-in의 폭이 넓어집니다. DB만 Neon에 둘 때와, 스토리지, compute, AI 라우팅까지 둘 때의 이탈 비용은 다릅니다. branch가 묶어 주는 편의가 클수록, 빠져나올 때 풀어야 할 매듭도 많아집니다. PostgreSQL 30년 글에서 인용한 Christophe Pettus(크리스토프 페투스)의 한 줄, "이미 쓰는 데이터 플랫폼이 선택을 대신했다"가 여기에 그대로 적용됩니다.
  • AI Gateway는 표준 PostgreSQL 영역 밖입니다. 모델 라우팅/비용 통제는 PostgreSQL 호환성과 무관한 독자 기능입니다. 이 자리는 pg_dump나 logical replication으로 옮겨지지 않습니다. 의존하기 전에 대체 경로를 먼저 확인해야 합니다.
  • 세 서비스 모두 아직 예고 단계라는 점도 무게를 둡니다. 운영 결정은 정식 출시, SLA, 요금이 공개된 다음에 내려도 늦지 않습니다. 발표 시점에 확정된 것은 방향이지 가용성이 아닙니다.
  • AI Gateway가 모회사 인프라 위에 올라간다는 점은 규모의 강점이자 결합의 신호입니다. Neon Serverless PostgreSQL과 Databricks Lakebase(레이크베이스)가 같은 엔진을 공유한다는 구조도 함께 봅니다.

산업사 흐름에서 본 위치

PostgreSQL 30년 글은 2025년을 "클라우드 베어의 시대"로 불렀습니다. Databricks가 Neon을, Snowflake(스노우플레이크)가 Crunchy Data(크런치 데이터)를 가져간 분기입니다. 그 글의 진단은 "AI agent를 위한 PostgreSQL"이었습니다. Neon의 branch 모델이 agent가 매 작업마다 격리된 DB를 띄우기에 맞는다는 이유였습니다.

이번 발표는 그 진단의 다음 장입니다. Neon은 "agent를 위한 PostgreSQL"에서 "agent를 위한 백엔드 전체"로 범위를 넓혔습니다. 발표 글의 표현을 빌리면 "agent-native cloud는 마법보다 boring한 기본기 — 신원, 권한, 로그, 롤백, 비용 통제 — 가 먼저 필요하다". DB 회사가 백엔드 플랫폼을 지향할 때 내거는 명분이 바로 이 자리입니다.

이 흐름은 Neon만의 것이 아닙니다. Supabase(수파베이스)는 처음부터 PostgreSQL + 인증 + 스토리지 + 함수를 한 묶음으로 팔아 온 회사입니다. Neon이 늦게 같은 무대로 올라왔지만 무기는 다릅니다. Neon은 자기 고유의 branch 모델을 백엔드 전 계층에 바르는 방식으로 차별화를 시도합니다. PostgreSQL을 코어로 둔 회사들이 "DB 벤더"에서 "백엔드 플랫폼"으로 수렴하는 큰 그림은 같습니다.

정리

발표 전의 Neon은 자기를 서버리스 PostgreSQL로 규정했고 branch는 DB 안에만 있었습니다. 이번 발표 이후 그 회사는 백엔드 플랫폼을 지향하고, branch 범위는 스토리지와 compute까지 넓어지며, AI는 pgvector 같은 DB 내부 기능이 아니라 Gateway로 분리/외부화됩니다. 운영자 관점에서 보면 DB 한 계층에 대한 의존이 백엔드 여러 계층에 대한 의존으로 커집니다.

정리하면 Neon은 branch를 데이터베이스 밖으로 끌고 나갔습니다. 스토리지와 compute가 DB와 함께 갈라지면 환경 하나를 통째로 격리하는 일이 명령 한 줄로 끝나는데, 이건 운영자에게 편의이자 결합입니다. 봉합 비용을 플랫폼에 넘기는 대신 계층 선택의 자유를 일부 내줍니다.

다만 세 서비스가 아직 예고 단계라는 점은 잊지 말아야 해요. 방향은 분명하지만 가용성, 요금, SLA는 아직이에요.

참고

Claude Code 동적 워크플로

· 약 8분

또 한 단계 올라갔다

Skills로 명령어를 통합하고, Routines로 예약 실행을 붙이고, Auto 모드로 권한 판단까지 AI에게 넘기더니, 이번엔 Claude가 오케스트레이션 스크립트를 직접 짜서 서브에이전트 수백 개를 한 세션에서 병렬로 돌리는 Dynamic Workflows가 2026년 5월 28일 Opus 4.8과 함께 공개됐어요.

지금까지의 서브에이전트는 Claude가 대화 턴마다 하나씩 띄우고 결과를 자기 컨텍스트로 받아오는 방식이었습니다. 몇 개까지는 괜찮지만, 500개 파일을 동시에 손봐야 하는 작업에서는 컨텍스트가 먼저 터집니다. Dynamic Workflows는 그 한계를 넘으려고 나온 기능입니다. (Anthropic 발표, TechCrunch)

주의: 이 글의 내용은 전부 리서치 프리뷰 기준입니다. 동작 방식, 한도, 요금 모두 정식 출시 전에 바뀔 수 있습니다. Claude Code v2.1.154 이상이 필요합니다.

한 줄 정의

공식 문서의 정의는 명확합니다.

"A dynamic workflow is a JavaScript script that orchestrates subagents at scale."Claude Code Docs

워크플로우는 Claude가 작성하는 자바스크립트 오케스트레이션 스크립트입니다. 사용자가 작업을 설명하면 Claude가 그 작업에 맞는 스크립트를 쓰고, 런타임이 그 스크립트를 백그라운드에서 실행합니다. 스크립트가 도는 동안 대화 세션은 그대로 응답 가능한 상태로 남습니다.

중요한 차이는 누가 계획을 들고 있느냐에 있습니다.

서브에이전트/스킬과 무엇이 다른가

셋 다 멀티스텝 작업을 처리할 수 있습니다. 차이는 계획의 주체와 중간 결과의 저장 위치입니다.

서브에이전트스킬워크플로우
정체Claude가 띄우는 워커Claude가 따르는 지침런타임이 실행하는 스크립트
다음 실행 결정Claude가 턴마다Claude가 프롬프트 따라스크립트가
중간 결과 위치Claude 컨텍스트Claude 컨텍스트스크립트 변수
재사용 단위워커 정의지침오케스트레이션 자체
규모턴당 몇 개서브에이전트와 동일런당 수십~수백 개
중단 시턴 재시작턴 재시작같은 세션 내 재개

서브에이전트와 스킬에서는 Claude가 오케스트레이터입니다. 무엇을 띄울지 턴마다 판단하고, 모든 결과가 Claude 컨텍스트로 돌아옵니다. 워크플로우는 그 루프와 분기, 중간 결과를 스크립트 안으로 옮깁니다. 그 결과 Claude 컨텍스트에는 최종 답만 남습니다. 그래서 컨텍스트가 터지지 않습니다.

어떻게 도는가

작업을 워크플로우로 넘기면 세 단계를 거칩니다.

대화 세션은 이 흐름 내내 자유롭습니다. /workflows를 실행하면 진행 중인 런의 진행 화면이 뜨고, 단계별 에이전트 수와 토큰 사용량, 경과 시간을 볼 수 있습니다.

패턴 1: Fan-Out

워크플로우가 시작되면 Claude가 프롬프트를 기준으로 계획을 세우고, 작업을 서브태스크로 쪼갠 뒤 여러 에이전트에 병렬로 펼칩니다. 이걸 fan-out이라 부릅니다. 한 런에서 수십에서 수백 개의 에이전트가 동시에 돕니다.

예를 들어 라우트 디렉토리 전체에서 인증 누락을 감사하라고 하면, 엔드포인트마다 에이전트 하나씩 붙여 동시에 점검합니다.

Run a workflow to audit every API endpoint
under src/routes/ for missing auth checks

프롬프트에 트리거 키워드를 넣으면 Claude Code가 그 단어를 강조 표시하고, 턴 단위로 처리하는 대신 워크플로우 스크립트를 작성합니다. 발표 직후에는 workflow가 트리거였지만, 2026년 6월 2일 v2.1.160에서 트리거 키워드가 ultracode로 바뀌었습니다. 이제 workflow라는 단어만으로는 런이 시작되지 않습니다. 다만 평소 쓰는 말로 워크플로우를 요청하는 건 그대로 동작합니다. (Claude Code Changelog)

패턴 2: 어드버서리얼 검증

여기가 단순히 에이전트를 더 많이 돌리는 것과 갈리는 지점입니다. 워크플로우는 반복 가능한 품질 패턴을 적용합니다.

에이전트가 발견한 내용을 그냥 보고하지 않습니다. 다른 에이전트가 그 발견을 반박하는 임무를 맡습니다. 한 에이전트가 "이 함수에 race condition이 있다"고 주장하면, 다른 에이전트는 그 주장을 깨는 일을 맡습니다. 반박을 거치고도 살아남은 주장만 사용자에게 전달됩니다.

번들로 제공되는 /deep-research 워크플로우가 이 패턴을 그대로 씁니다. 여러 각도로 웹 검색을 펼치고, 찾은 출처를 서로 교차검증하고, 각 주장에 투표한 뒤, 교차검증을 통과하지 못한 주장은 걸러낸 인용 리포트를 돌려줍니다.

패턴 3: 수렴 반복

고정된 단계의 파이프라인이 아닙니다. 워크플로우는 답이 더 이상 바뀌지 않을 때까지 반복합니다. 에이전트 수와 반복 횟수는 작업이 실제로 요구하는 바에 따라 실시간으로 정해집니다.

이 수렴 방식 덕분에 단일 패스로는 도달할 수 없는 결과까지 갑니다. 한 번 훑고 끝내는 게 아니라, 발견과 반박을 답이 안정될 때까지 돌리는 구조입니다.

실제 사례: Bun을 Zig에서 Rust로

가장 인상적인 사례는 Jarred Sumner가 Bun 런타임을 Zig에서 Rust로 포팅한 작업입니다. 약 75만 줄 코드를 11일 만에 옮겼습니다. 파일마다 에이전트를 붙여 수백 개를 병렬로 돌렸고, 파일당 리뷰어를 두 명씩 뒀습니다. (Anthropic 발표)

Anthropic은 이 기능의 목표를 "코드베이스 규모의 마이그레이션을 킥오프부터 머지까지, 기존 테스트 스위트를 합격 기준으로 삼아 수행"하는 것으로 잡았습니다. (TechCrunch) 기존 테스트가 통과 여부를 판정하니, 사람이 일일이 검수하지 않아도 합격선이 정의됩니다.

발표의 표현을 빌리면 분기 단위로 계획하던 일이 며칠 만에 끝납니다. 다만 이건 잘 풀린 사례입니다. 테스트 커버리지가 부실한 코드베이스라면 합격 기준 자체가 흔들립니다.

한도와 제약

런타임에는 다음과 같은 제약이 있습니다.

제약이유
런 도중 사용자 입력 불가단계 사이 승인이 필요하면 단계별로 워크플로우를 쪼갤 것
워크플로우 자체의 파일/셸 직접 접근 불가읽기, 쓰기, 명령 실행은 에이전트가, 스크립트는 조율만
동시 에이전트 최대 16개 (코어 적으면 더 적게)로컬 자원 사용 제한
런당 총 에이전트 1,000개폭주 루프 방지

수백 개 병렬이라는 표현과 동시 16개가 충돌하는 것처럼 보이지만, 동시 실행은 16개로 묶이고 누적 총량이 런당 최대 1,000개라는 뜻입니다. (Claude Code Docs, MarkTechPost)

권한 측면도 짚어둘 만합니다. 세션 권한 모드와 무관하게, 워크플로우가 띄우는 서브에이전트는 항상 acceptEdits 모드로 돌고 파일 편집은 자동 승인됩니다. 긴 런에서 셸 명령이나 MCP 도구로 중간에 멈추고 싶지 않다면, 시작 전에 필요한 명령을 allowlist에 넣어두는 편이 낫습니다.

어떻게 켜고 끄는가

워크플로우를 작성하게 하는 방법은 두 가지입니다.

방법동작
프롬프트에 트리거 키워드(ultracode) 포함해당 작업 하나만 워크플로우로 처리
/effort ultracode 설정세션의 모든 주요 작업을 워크플로우로 계획

발표 시점의 트리거 키워드는 workflow였으나 v2.1.160(2026년 6월 2일)에서 ultracode로 바뀌었습니다. 예전 글이나 영상에서 workflow라고 적으라는 안내를 봤다면 키워드만 바꿔 읽으면 됩니다.

ultracodexhigh effort(추론 강도)와 자동 워크플로우 오케스트레이션을 묶은 설정입니다. 켜두면 Claude가 작업마다 워크플로우가 필요한지 알아서 판단합니다. 한 요청이 여러 워크플로우로 갈라질 수도 있습니다. 코드 이해용 하나, 변경용 하나, 검증용 하나 식으로. 그만큼 토큰과 시간을 더 씁니다.

마음에 드는 런이 나오면 /workflows에서 그 런을 골라 s 키로 명령어로 저장할 수 있습니다. 프로젝트의 .claude/workflows/에 두면 저장소를 받은 모두가 쓰고, 홈의 ~/.claude/workflows/에 두면 저만 써요.

끄는 방법도 명확합니다.

  • /config에서 Dynamic workflows 토글 끄기
  • ~/.claude/settings.json"disableWorkflows": true
  • 환경변수 CLAUDE_CODE_DISABLE_WORKFLOWS=1
  • 조직 전체는 managed settings의 "disableWorkflows": true

요금과 가용성

  • 리서치 프리뷰. Claude Code v2.1.154 이상 필요
  • 유료 플랜 전체에서 사용 가능 (Pro는 /config에서 켜야 함). 발표 기준 Max, Team, Enterprise는 기본 활성화
  • Anthropic API, Amazon Bedrock, Google Cloud Vertex AI, Microsoft Foundry 지원
  • 토큰 소비가 일반 세션보다 크게 많습니다. 에이전트를 수십~수백 개 띄우니 당연합니다

비용 관리 팁도 문서에 있습니다. 큰 런 전에 /model을 확인하고, 강한 모델이 필요 없는 단계는 작은 모델로 라우팅하도록 작업 설명에 명시하면 됩니다.

함께 나온 Opus 4.8은 자기 작업의 불확실성을 더 적극적으로 드러내고, 근거 없는 주장을 덜 한다는 평가입니다. 어드버서리얼 검증 패턴과 맞물려 보면, 모델이 스스로 의심을 표하는 성향이 강해진 게 수백 개 에이전트를 신뢰하는 데 보탬이 됩니다. Fast 모드는 2.5배 속도로 동작하면서 이전 모델보다 3배 저렴해졌습니다. (Anthropic Opus 4.8 발표)

운영자 시각에서 한마디

Dynamic Workflows의 본질은 에이전트를 더 많이 돌리는 게 아니라 계획을 코드로 옮기는 데 있습니다. 오케스트레이션이 읽고 다시 돌릴 수 있는 스크립트로 굳으면, 매 브랜치마다 같은 리뷰를 같은 방식으로 돌릴 수 있습니다. 일회성 마법이 아니라 반복 가능한 프로세스가 된다는 뜻입니다.

다만 지금은 리서치 프리뷰입니다. 한도도 동작도 바뀔 수 있고, 토큰 비용은 만만치 않습니다. 처음 쓴다면 작은 작업으로 범위를 좁혀 토큰 사용 패턴부터 감을 잡으라는 게 공식 권고입니다.

그래도 방향은 분명해요. 75만 줄 마이그레이션을 11일에 끝냈다는 사례가 과장이 아니라면, 분기 단위 작업의 정의가 다시 쓰이는 중이에요. Skills, Routines, Auto 모드에 이어 이번엔 오케스트레이션 자체가 자동화됐습니다. 따라가는 것만으로도 벅차지만, 한 번쯤 직접 /deep-research부터 돌려보는 게 감을 잡는 가장 빠른 길입니다.

참고 자료

Claude Opus 4.8 팀 작업

· 약 7분

출시

2026년 5월 28일, Anthropic이 Claude Opus 4.8을 출시했고, 모델 ID는 claude-opus-4-8이에요. 직전 모델인 Opus 4.7이 나온 지 41일 만이며, 표준 가격은 입력 $5, 출력 $25(백만 토큰당)로 4.7과 같아요.

직전 글에서 4.7의 방향을 "더 똑똑하기보다 더 맡길 수 있는 모델"이라고 정리했습니다. 4.8은 그 연장선을 한 칸 더 밀어붙입니다. 이번에는 작업 한 건을 통째로 맡기지 않고, 작업을 잘게 쪼개 수백 개의 subagent에게 동시에 맡깁니다. 한 사람에게 맡기던 일을 한 팀에게 맡기는 단계입니다.

한눈에 보는 변화

Opus 4.7Opus 4.8
출시일2026-04-162026-05-28
표준 가격 (입/출)$5 / $25동일
고속 모드2.5배 속도, $10 / $50
병렬 subagent제한적수백 개 (동적 워크플로우)
코드 결함 누락기준4.7의 약 1/4
불확실성 표시제한적적극적으로 먼저 알림
effort(추론 강도) 조절low~max + xhigh슬라이더 + ultracode

가격을 보면 표준 호출 비용은 그대로입니다. 대신 새로 생긴 두 가지 — 동적 워크플로우와 고속 모드 — 가 작업의 단위 자체를 바꿉니다.

핵심 1: 동적 워크플로우

가장 큰 변화는 수백 개의 subagent를 활용하는 **동적 워크플로우(dynamic workflows)**입니다. Claude Code 안에서 Claude가 직접 작업 계획을 세우고, 그 계획을 orchestration 스크립트로 옮긴 다음, 수백 개의 subagent를 동시에 돌립니다. Anthropic은 이걸 코드를 완성하는 단계를 넘어선 기능으로 설명합니다.

규모 제한은 명확하게 정해져 있습니다.

항목
동시 실행 subagent최대 16개
한 번의 실행당 총 subagent1,000개
필요 버전Claude Code v2.1.154 이상
제공 플랜Max / Team / Enterprise (Max/Team은 기본 켜짐)
상태리서치 프리뷰

흐름을 도식으로 보면 이렇습니다.

여기서 중요한 건 분할과 취합을 사람이 짜는 게 아니라는 점입니다. 사람은 "이 작업을 해줘"라고 던지고, 어떻게 쪼갤지와 어떻게 합칠지는 모델이 정합니다. 동시 16개라는 상한이 있어서 1,000개를 한꺼번에 띄우는 게 아니라, 16개씩 흘려보내며 총 1,000개까지 처리하는 구조입니다.

실제로 뭐가 달라지나

MarkTechPost가 전한 사례가 이 기능의 성격을 잘 보여줍니다. 약 75만 줄 규모의 Rust 코드를 다시 쓰는 작업에서, Opus 4.8이 기존 테스트 스위트의 99.8%를 통과시키며 첫 커밋부터 병합까지 11일 만에 끝냈습니다.

중요한 대목은 기존 테스트 스위트를 합격선으로 삼는다는 점입니다. 수십만 줄 규모의 마이그레이션을 사람이 일일이 검수하는 대신, 통과해야 할 테스트를 기준으로 모델이 스스로 작업의 완료 여부를 판단합니다. 4.7에서 강조됐던 셀프 검증이 워크플로우 전체로 확장된 모양새입니다.

다만 리서치 프리뷰이고, 일반적인 세션보다 토큰을 눈에 띄게 많이 쓴다는 경고가 붙어 있습니다. 가격과 제공 범위가 바뀔 수 있다는 단서도 함께 붙었습니다.

핵심 2: 고속 모드

두 번째는 2.5배 속도를 내면서 이전 세대보다 가격을 3분의 1로 낮춘 **고속 모드(fast mode)**입니다. 같은 Opus 4.8을 출력 토큰 기준 2.5배 빠르게 돌립니다. 모델 품질은 표준과 동일하고, 속도만 끌어올립니다.

가격은 입력 $10, 출력 $50(백만 토큰당)로 표준의 두 배입니다. 다만 The New Stack에 따르면 이 고속 모드 가격이 이전 모델들의 고속 모드($30/$150)보다 3배 저렴해졌습니다.

구분입력출력속도
표준$5$25기준
고속 모드 (4.8)$10$502.5배
고속 모드 (이전 세대)$30$150

쓰는 법도 단순합니다. Claude Code에서 /fast 명령으로 켜고 끄며, 켜진 상태는 작은 번개 아이콘으로 표시됩니다. 다만 청구 방식이 다릅니다. 고속 모드는 플랜 할당량이 아니라 사용량 크레딧(usage credits)에서 차감되므로, 크레딧을 활성화해 둬야 쓸 수 있습니다.

속도가 두 배 이상 빨라진다는 건 단순히 답이 빨리 나온다는 의미를 넘어섭니다. 동적 워크플로우처럼 subagent를 수백 개 돌리는 작업에서는 개별 호출의 속도가 전체 완료 시간을 좌우합니다. 두 기능이 같은 날 나온 게 우연은 아닙니다.

핵심 3: 더 정직해진 모델

벤치마크 점수 못지않게 강조된 변화가 정직성입니다. Opus 4.8은 자기 작업에서 코드 결함을 놓치는 빈도가 4.7의 약 4분의 1로 줄었다. 작업의 불확실한 부분을 먼저 드러내고, 근거 없는 단언을 덜 한다는 평가도 함께 나왔습니다.

TechCrunch가 전한 Bridgewater Associates의 코멘트가 인상적입니다. 분석의 입력과 출력에서 문제를 능동적으로 짚어내는데, 다른 모델들이 으레 놓치던 지점이라는 것입니다.

이 변화는 동적 워크플로우와 맞물립니다. subagent 수백 개가 동시에 돌아가는 작업에서 모델이 결함을 자주 놓치거나 근거 없이 다 됐다고 보고하면, 사람이 검수할 지점이 폭발적으로 늘어납니다. 결함 누락이 줄고 불확실성을 먼저 알리는 성질은 대규모 위임을 실제로 굴러가게 만드는 전제입니다.

핵심 4: effort 슬라이더와 ultracode

4.7에서 xhigh effort 레벨이 추가됐던 것을 기억할 것입니다. 4.8은 이 effort 조절을 더 손에 잡히게 바꿨습니다.

  • claude.ai와 Cowork에서 슬라이더로 effort 수준을 조절합니다. 품질과 토큰 소비를 직접 저울질하는 방식입니다.
  • 기본값은 high effort입니다. 4.7과 같은 토큰을 쓰면서 성능은 더 낫다는 게 Anthropic의 설명입니다.
  • Claude Code에는 ultracode 설정이 생겼습니다. xhigh effort에 자동 워크플로우 orchestration을 결합한 모드입니다.

ultracode 외에도 프롬프트에 workflow라는 단어를 넣거나 번들 /deep-research 명령을 쓰면 동적 워크플로우가 작동합니다. 즉 동적 워크플로우는 별도 화면이 아니라 기존 작업 흐름 안에서 자연스럽게 켜지도록 설계됐습니다.

벤치마크

수치 자체는 4.7만큼 극적이진 않지만, 측정 대상이 달라졌습니다. 단일 코딩 점수보다 에이전트와 실무 작업 쪽에 무게가 실렸습니다.

벤치마크결과
Online-Mind2Web (브라우저 에이전트)84%
Super-Agent모든 케이스를 끝까지 완료한 유일한 모델
Legal Agent Benchmark (전체 통과 기준)전체 통과 10% 넘긴 첫 모델

전체 통과 기준에서 10%를 넘긴 첫 모델이라는 표현이 현재 에이전트 벤치마크의 난이도를 잘 보여줍니다. 부분 점수가 아니라 한 작업을 처음부터 끝까지 완수했는지를 따지면, 아직 대부분의 모델이 한 자릿수에 머문다는 뜻입니다.

정리

4.7이 사람이 덜 개입해도 되는 방향이었다면, 4.8은 그 위에 한 사람이 못 하던 규모를 한 번에 처리하는 방향을 얹었습니다. 수십만 줄 마이그레이션을 11일에 끝낸 사례가 과장이 아니라면, 위임의 단위가 작업 한 건에서 프로젝트 한 덩어리로 넘어간다고 볼 수 있습니다.

물론 동적 워크플로우는 아직 리서치 프리뷰이고, 토큰을 많이 쓴다는 단서가 붙어 있습니다. 작은 작업이라면 표준 호출이 여전히 합리적입니다. 다만 사람 손으로 며칠 걸리겠다 싶은 큰 작업 앞에서 선택지가 하나 더 생겼다는 건 분명합니다.

출시 직후 외부 클라우드로도 빠르게 퍼졌어요. Databricks Model Serving이 5월 28일 Claude Opus 4.8을 호스팅 모델로 추가했고, AWS도 6월 초 Amazon Bedrock과 AWS의 Claude Platform 양쪽에서 모델 제공을 시작했어요. Bedrock에서는 Guardrails, Knowledge Bases, 데이터 레지던시 같은 관리형 기능과 묶어 쓸 수 있어요.

참고 자료