한 줄로
Fabric Explorer(블록 탐색기) 하나만 쓰는 전용 DB 다.
애플리케이션 DB 가 아니다. 이 시스템의 본체 DB 는 따로 있고, 이건 탐색기가 화면을 그리려고
쌓아두는 사본이다.
왜 블록체인에 DB 가 또 필요한가
Fabric Explorer 는 블록·트랜잭션을 웹 화면으로 보여주는 도구다. 그런데 원장(블록 사슬)을
직접 읽어서 화면을 그리기엔 느리다.
- “최근 트랜잭션 20건” → 사슬 끝에서부터 뒤져야 한다
- “시간대별 트랜잭션 수” → 전부 훑어야 한다
- “이 조직이 만든 블록” → 전부 훑어야 한다
그래서 Explorer 는 블록을 읽어서 관계형 DB 에 다시 적재한다. 화면은 그 DB 에서 조회한다.
Fabric 원장 → Explorer 가 읽음 → PostgreSQL 에 적재 → 화면 조회
즉 이 DB 는 원본이 아니라 조회용 사본이다. 날아가도 원장은 멀쩡하고, 다시 적재하면 된다.
couchdb 편의 상태 DB 와 성격이 비슷하다.
블록체인 주변에는 “빠른 조회를 위한 사본” 이 이렇게 여러 개 붙는다.
alpine 을 골랐다
이미지가 postgres:13-alpine 이다. 뒤에 붙은 -alpine 이 선택이다.
| 태그 | 베이스 | 대략 크기 |
|---|---|---|
postgres:13 |
Debian | ~130MB |
postgres:13-alpine |
Alpine Linux | ~80MB |
Alpine 은 아주 작은 리눅스 배포판이다. 같은 PostgreSQL 인데 바탕 OS 를 가볍게 해서
이미지 크기를 줄인 것이다.
busybox 편에서와 같은 이유다.
폐쇄망에서는 이미지 용량이 곧 레지스트리 저장 공간이고, 옮길 때 그대로 전송량이 된다.
네트워크마다 하나씩 뜬다
Explorer 와 이 DB 는 Fabric 네트워크의 같은 네임스페이스 안에 뜬다.
fabric-{네트워크ID}
├─ CA · 피어 · 오더러 ← 블록체인 본체
├─ explorer-db ← 이 글의 주인공
└─ fabric-explorer ← 탐색기
즉 Fabric 네트워크를 만들 때마다 PostgreSQL 이 하나씩 늘어난다.
디스크는 볼륨으로 1Gi 를 잡는다.
여기서 Fabric 편에서 다룬 문제와
이어진다. 상태 판정이 네임스페이스 전체를 보기 때문에, 이 DB 파드가 죽으면
Fabric 네트워크 전체가 ERROR 로 표시된다. 블록체인 본체는 멀쩡한데도 그렇다.
스키마를 psql 11번 호출로 만든다
설치 방식이 특이하다. 마이그레이션 도구를 쓰지 않는다.
kubectl exec -n ${NS} deploy/explorer-db -- env PGPASSWORD=... psql ... -c "
CREATE TABLE ...
"
이런 kubectl exec 호출이 11번 이어진다. 테이블을 하나씩 만드는 것이다.
폐쇄망이라 이해되는 면이 있다. Explorer 공식 배포본에는 스키마 SQL 이 들어 있지만, 그걸
컨테이너 안으로 가져다 실행하려면 파일을 옮기거나 이미지를 다시 말아야 한다. 그냥
kubectl exec 로 SQL 을 던지는 게 간단하다.
대신 약점이 뚜렷하다.
- 중간에 실패하면 절반만 만들어진 상태로 남는다. 되돌리는 코드가 없다
- 순서가 코드에 암묵적으로 박혀 있다 — 어떤 테이블이 어떤 것보다 먼저인지 스크립트 순서가 전부다
- 다시 돌리면 어떻게 되는지가 명확하지 않다
DB 스키마를 절차적으로 만드는 방식의 전형적인 한계다. 항목이 11개라 지금은 관리되지만,
늘어날수록 힘들어진다.
자격증명이 평문으로 박혀 있다
이 스크립트에서 가장 걸리는 부분이다.
DB 사용자·비밀번호·DB 이름이 매니페스트와 psql 명령줄에 그대로 들어 있다.
11번의 kubectl exec 마다 비밀번호가 명령줄에 실린다.
문제가 몇 겹이다.
| 문제 | 설명 |
|---|---|
| 소스에 남는다 | git 에 그대로 커밋돼 있다 |
| 프로세스 목록에 뜬다 | 명령줄 인자는 ps 로 보인다 |
| 모든 네트워크가 같다 | 회사·네트워크가 달라도 값이 동일하다 |
| 교체 경로가 없다 | 바꾸려면 스크립트를 고쳐야 한다 |
폐쇄망이고 클러스터가 회사별로 격리돼 있어 실제 위험은 낮다. 하지만 쿠버네티스에는
Secret 이라는 표준 수단이 있는데 안 쓴 것이라, 고치기 어려운 종류의 문제도 아니다.
이 글에는 실제 값을 적지 않는다. 위치만 남긴다.
겪은 이슈 — 두 번째 회사부터 포트가 틀렸다
이 DB 자체가 아니라 함께 뜨는 Explorer 의 포트에서 사고가 났다.
fix(fabric): Explorer NodePort 오계산 및 TLS CA fallback 처리 (2026-04-20)
RemoteFabricService: EXPLORER_NODE_PORT를 portRangeStart+9 고정값으로 WAS에서 직접 전달
(기존 API_SERVER_PORT+9 계산은 두 번째 이상 Fabric 생성 시 잘못된 포트 산출)
첫 회사는 멀쩡했고, 두 번째부터 틀렸다. 이런 종류가 발견이 늦다.
원인은 기준점을 잘못 잡은 것이다. 포트를 API_SERVER_PORT + 9 로 계산하고 있었는데,
회사마다 포트 대역을 나눠주는 구조에서
그 두 값은 첫 회사에서만 우연히 일치한다.
회사A : 대역 10000~10009, API 서버 10000 → +9 = 10009 ✅
회사B : 대역 10010~10019, API 서버 10010 → +9 = 10019 ✅
여기까지는 맞다. 그런데 API 서버 포트는 kind 가 실제로 잡은 값을 도커에서 긁어오는
반면, 포트 대역은 DB 에 저장된 값이다. 두 출처가 어긋나는 순간 계산이 깨진다.
고친 방식은 계산 자체를 없앤 것이다. WAS 가 portRangeStart + 9 를 직접 넘긴다.
포트 대역의 주인이 WAS 이니, 그 값을 아는 쪽이 계산해서 내려보내는 게 맞다.
같은 값을 두 곳에서 각자 계산하면 언젠가 어긋난다. 한쪽을 원본으로 정하고 나머지는
받아쓰는 게 낫다.
한 가지 더. 같은 커밋에서 cacert.pem 이 없을 때 시크릿에서 대신 가져오는 처리도
들어갔다. 인증서 파일이 항상 같은 자리에 있다고 가정했다가 깨진 것으로 보인다.
Explorer 는 비필수인데 DB 는 따라온다
한 가지 구조적으로 어색한 지점이 있다.
Fabric 배포 스크립트는 Explorer 설치를 “비필수” 로 선언한다.
... || { echo "⚠️ ... non-critical, continuing..."; }
탐색기가 없어도 블록체인은 돈다는 판단이고, 맞는 말이다.
그런데 비필수 기능 하나 때문에 PostgreSQL 파드와 1Gi 볼륨이 네트워크마다 따라붙는다.
그리고 앞서 말했듯, 그 비필수 파드가 죽으면 네트워크 전체가 ERROR 로 보인다.
비필수라면서 실패에 가장 민감한 자리에 놓여 있는 셈이다.
정리
- Fabric Explorer 전용 DB — 원장을 다시 적재한 조회용 사본이다. 날아가도 복구 가능
-
-alpine을 고른 이유는 크기(~130MB → ~80MB). 폐쇄망에서 용량은 곧 비용 - Fabric 네트워크마다 하나씩 뜬다. 볼륨 1Gi 포함
- 스키마를
kubectl exec+psql11번으로 만든다. 마이그레이션 도구가 아니라
중간 실패 시 절반만 남는다 - ⚠️ 자격증명이 평문으로 매니페스트와 명령줄에 있다. 모든 네트워크가 같은 값이고
Secret을 쓰지 않았다 - ⚠️ Explorer 는 “비필수” 인데, 이 DB 가 죽으면 네트워크 전체가
ERROR로 표시된다 - ⚠️ 두 번째 회사부터 Explorer 포트가 틀렸다. 같은 값을 WAS 와 스크립트가 각자
계산하다 어긋났다. 한쪽을 원본으로 정하고 받아쓰도록 고쳤다
같이 읽을 글:
couchdb — 피어마다 붙는 상태 DB ·
Fabric 네트워크는 어떻게 생기나 ·
registry:2 — 자기 자신을 담고 있는 레지스트리