본문으로 건너뛰기

머리말 — 오픈소스 바이오공정 데이터 시스템

📍 현재 위치: 이 시리즈의 세 번째 책으로 들어서는 정문입니다. 여기서부터는 생물공정 데이터에 관한 글을 읽는 것을 멈추고, 바이오리액터(bioreactor)의 센서에서 규제 허가 제출까지 데이터를 실어 나르는 플랫폼을 직접 만들기 시작합니다.

이 시리즈의 첫 번째 책 Biologic Drug Manufacturing은 단일클론항체(monoclonal antibody, mAb, 만들어지는 단백질 의약품)가 실제로 어떻게 만들어지는지를 살펴보았습니다. 그것을 생산하도록 조작된 살아 있는 CHO 세포(중국 햄스터 난소 세포), 영양분을 단계적으로 넣어 주며 세포를 키우는 탱크인 유가식(fed-batch) 바이오리액터, 배양액에서 항체를 포착해 내는 친화 크로마토그래피 컬럼인 단백질 A(Protein A) 컬럼이 그 무대였습니다. 두 번째 책 Data Management in Biopharmaceutical Manufacturing는 한 걸음 물러서서, 그 공정에서 나오는 데이터를 어떻게 거버넌스해야 하는지를 물었습니다. 누가 그것을 소유하는지, 어떻게 신뢰성을 유지하는지, "좋은" 상태란 어떤 모습인지를 다뤘습니다. 두 책 모두 읽는 책이었습니다.

이 책은 실행하는 책입니다.

여러분은 Git 저장소 하나를 클론하고 make up을 입력한 뒤, 실제로 동작하는 오픈소스 생물공정 데이터 플랫폼이 여러분의 노트북에서 살아나는 것을 지켜보게 됩니다. 책을 끝낼 무렵이면 여러분에게는 실시간 센서 데이터를 저장하는 히스토리안(historian, 타임스탬프가 찍힌 센서 판독값을 위해 만들어진 데이터베이스), 그 숫자들에 의미를 부여하는 배치 모델(batch model), 직접 변조를 시도해 보고(그리고 그 시도를 스스로 잡아내는) 감사 추적(audit trail, 누가 무엇을 언제 바꿨는지를 변조하면 드러나도록 남기는 기록), 그리고 라만 스펙트럼(Raman spectrum, 배양액에 무엇이 녹아 있는지를 빠르게 광학적으로 측정한 값)으로부터 항체 역가(titer, 배양이 축적한 항체의 양, 리터당 그램)를 예측하는 소프트 센서(soft-sensor, 측정하기 어려운 양을 더 값싼 신호로부터 추론하는 모델)가 갖춰져 있을 것입니다. 이 책의 모든 코드 블록은 실제로 실행되고 테스트된 그 저장소의 파일에서 나온 것입니다. 얼버무린 것은 하나도 없습니다.

쉽게 말하면

첫 번째 책은 요리하는 법을 가르쳤습니다. 두 번째 책은 주방 위생과 위생 검사관의 사고방식을 가르쳤습니다. 이 책은 주방 그 자체를 건네줍니다. 화구, 온도계, 작업 일지, 레시피 카드까지 — 모두 오픈소스이고, 모두 서로 연결되어 있습니다 — 그리고 그것을 직접 만드는 방법을 보여 줍니다. 그런 다음, 어떤 장비는 여전히 상용 벤더에게서 사야 한다는 사실을 솔직하게 말해 줍니다. 무료 장비만으로는 그 자체로 검사를 통과할 수 없기 때문입니다.

이 장에서 다루는 내용

  • 이 책이 누구를 위한 책인지, 그리고 앞선 두 책으로부터 어떻게 바통을 이어받는지.
  • 책 전체를 하나로 묶는 두 가지 생각: 오픈소스 우선(open-source first), 그리고 순수 오픈소스(OSS)가 더 이상 나아갈 길이 없을 때를 위한 정직한 하이브리드(honest hybrid).
  • 우리가 절대 어기지 않는 단 하나의 규칙: 모든 주장은 여기서 실행 가능하거나 출처가 인용되어 있다.
  • 이 책을 관통하는 사례 — 유가식 CHO + 단백질 A 항체 생산 라인 — 그리고 동반 저장소를 클론하고 시작하는 정확한 방법.
  • 모든 장에서 보게 될 관례: 코드를 어떻게 보여 주는지, 출처를 어떻게 인용하는지, 그리고 오픈소스만으로는 충분하지 않은 지점을 어떻게 표시하는지.

이 책은 누구를 위한 것인가

데이터가 벤더의 블랙박스 속으로 사라지는 것을 지켜본 공정 엔지니어, "그냥 바이오리액터를 클라우드에 연결하라"는 요청을 받은 자동화 또는 데이터 엔지니어, 각 열이 무엇을 뜻하는지 말해 주는 맥락이 벗겨진 CSV 파일(comma-separated values, 쉼표로 구분된 평문 데이터 파일)만 받는 데 지친 데이터 과학자, 또는 실제 제약 데이터 스택이 어떻게 맞물려 돌아가는지 보고 싶은 학생이라면 — 이 책은 여러분을 위한 것입니다. 미생물학자나 규제 업무(regulatory-affairs) 전문가일 필요는 없습니다. 앞선 두 책이 그 기초를 제공하며, 진행하면서 중요한 부분은 다시 짚어 줍니다. 다만 터미널을 한 번이라도 본 적이 있다면 편하게 따라올 수 있습니다. Docker 전문가일 필요는 없으며 — 2장이 여러분의 수준을 끌어올려 줍니다 — 명령어를 입력하고 오류 메시지를 당황하지 않고 읽을 의지만 있으면 됩니다.

우리는 약 16GB RAM을 갖춘 노트북에 Docker와 Docker Compose가 설치되어 있고 [1], uv(make venv가 사용하는 빠른 Python 환경 및 패키지 설치 도구)와 함께 Python 3.12, Git [2], 그리고 GNU Make(make up 같은 짧은 이름을 그 뒤의 실제 명령에 대응시키는 작업 실행기)가 갖춰져 있다고 가정합니다. 이 책의 모든 명령은 여러분이 입력하는 make 타깃이기 때문입니다. 전제 조건은 그게 전부입니다. 핵심 스택 — 가장 먼저 띄우는 부분 — 은 대략 3GB RAM에 들어가며, 이후의 더 무거운 구성 요소는 선택적으로 추가되므로 여러분의 컴퓨터는 지금 보고 있는 장에 필요한 만큼만 부담합니다.

이 책을 떠받치는 두 가지 생각

오픈소스 우선

이 책의 핵심 주장은, 현대적이고 규제를 인식하는 생물공정 데이터 플랫폼의 대부분을 오픈소스 소프트웨어로 만들 수 있으며, 그렇게 하는 것이 오히려 명료하게 해 준다는 것입니다. 모든 계층을 들여다볼 수 있을 때, 비로소 여러분은 자신의 데이터가 무엇을 하고 있는지 이해하게 됩니다. 우리는 전체 스택 — PostgreSQL + TimescaleDB 히스토리안(타임스탬프가 찍힌 센서 데이터베이스), Eclipse Mosquitto 메시지 브로커(message broker, 센서 메시지를 발행자에서 구독자로 실어 나르는 중계기), Grafana 대시보드 계층(여러분이 들여다보는 차트), SQL로 구현한 ISA-88/95 배치 모델(어떤 판독값이 어떤 배치와 단계에 속하는지를 말해 주는 스키마), 지식 그래프(knowledge graph, 사실을 탐색 가능한 관계의 망으로 저장하는 데이터베이스, 19장에서 구축), ALCOA+ 감사 체인(audit chain, 신뢰할 수 있는 기록이 갖춰야 할 데이터 무결성 속성들 — 뒤에서 자세히 설명), 그리고 라만-역가 소프트 센서 — 을 거의 전부 관대한 라이선스를 가진 도구들(소프트웨어를 거의 제약 없이 사용, 수정, 재배포하게 해 주는 라이선스)로 조립합니다.

하지만 "오픈소스 우선"은 출발점이 되는 자세이지 종교가 아닙니다. 상용 시스템이 정직한 답인 곳에서는, 우리는 그렇다고 말하고 그것과 통합합니다.

정직한 하이브리드

여기 우리가 여러분이 모르는 채로 넘어가게 두지 않을 선이 있습니다. 어떤 오픈소스 도구도 다운로드 그대로 21 CFR Part 11을 준수하지 않으며, 내려받기만으로 준수하게 되는 일은 앞으로도 결코 없습니다 [3]. Part 11 — 미국 식품의약국(U.S. Food and Drug Administration, FDA)의 전자 기록 및 전자 서명에 관한 규정으로, 미국 연방 규정집(U.S. Code of Federal Regulations, CFR) 제21편(Title 21)에 성문화되어 있습니다 — 은 전자 기록을 신뢰할 수 있고 종이 기록과 동등한 것으로 취급하기 위한 기준을 정합니다 [3]. 그 동반 지침은 이 점을 더욱 날카롭게 짚습니다. 준수는 위험 기반(risk-based)이며, 검증된(validated) 시스템과 그것을 둘러싼 절차에 부여되는 것으로, 특정 통제에 대해서는 집행 재량(enforcement discretion)을 적용해 다뤄집니다 — 선반 위에 놓인 소프트웨어 한 조각에 부여되는 것이 아닙니다 [4]. 유럽의 대응물인 EudraLex Annex 11도 다른 표현으로 같은 말을 합니다. 규제 대상 공정에 사용되는 전산화 시스템(computerised system)은 감사 추적과 데이터 무결성(data integrity) 통제를 갖추어 검증(validation = 시스템이 의도한 일을 하고 계속 그렇게 한다는 것을 문서화된, 위험 기반 증거로 보이는 것)되어야 하며, 그 속성은 어느 한 구성 요소가 아니라 시스템 전체에 속한다는 것입니다 [5].

그래서 우리가 책 전반에 걸쳐 되풀이하는 정직한 추정은 이렇습니다. 순수 오픈소스는 여러분을 대략 80% 지점까지 데려다줍니다. 그것은 데이터를 포착하고, 저장하고, 맥락을 부여하고, 시각화하며, 심지어 의미론적으로(semantically) 추론하게도 해 줍니다. 나머지 20% — 검증, 적격성이 입증된(qualified) 전자 서명, 벤더 책임성(vendor accountability), 고가용성(high-availability) 보장이라는 GxP("Good x Practice", GMP/GLP/GCP 품질 규정의 집합)의 마지막 1마일(last mile) — 은 여러분이 직접 진지한 하드닝(hardening) 작업을 하거나 상용 제품에 손을 뻗어야 하는 지점입니다. (여기서 cGMP, 즉 현행 우수 제조 관리 기준(current Good Manufacturing Practice)을 처음 사용하니 정의해 둡니다. FDA가 집행하는 품질 시스템으로, GxP 데이터 무결성 규정이 그 안에서 작동합니다.)

이것은 오픈소스의 패배가 아닙니다. 그것이야말로 현대의 지침이 실제로 기대하는 바입니다. 컴퓨터 시스템 검증을 위한 업계의 주요 참고 문헌인 ISPE의 GAMP 5 제2판은 오픈소스 소프트웨어에 관한 부록과 위험 기반 보증(risk-based assurance) 접근법을 명시적으로 추가했으며, OSS가 GxP 환경에서 사용될 수 있음을 — 다만 검증된 수명 주기(validated lifecycle) 안에서만 — 확인했습니다 [6]. FDA의 컴퓨터 소프트웨어 보증(Computer Software Assurance) 사고방식도 같은 방향을 가리킵니다. 보증은 소프트웨어 위에 덧입혀지는, 위험에 비례하고 의도된 용도(intended-use)에 맞춘 활동이며, 바로 그렇기 때문에 어떤 도구도 준수된 상태로 도착하지 않습니다 [7]. 우리는 실행 가능한 80%를 만들고, 하이브리드 20%를 분명하게 가리키며, 마지막 장에서는 각 경계에서 정확히 무엇을 포기하게 되는지 점수를 매깁니다.

왼쪽의 바이오리액터 센서에서 오른쪽의 규제 허가 제출까지 이어지는 수평 계층 스택으로, 각 계층은 그 오픈소스 도구로 라벨링되어 있고, 순수 OSS인 부분과 규제 영역 가까이에서 상용 시스템 또는 무거운 검증이 넘겨받는 지점을 음영으로 보여 줍니다.

센서에서 허가까지: 데이터는 포착, 히스토리안, 배치 맥락, 의미론, 신뢰 계층을 거쳐 왼쪽에서 오른쪽으로 흐릅니다. 녹색 음영 띠(왼쪽)는 여러분이 여기서 직접 만들고 실행하는 순수 오픈소스이고, 제출 가까이의 장미색 음영 처리된 마지막 1마일은 정직한 하이브리드입니다 — 검증, 적격성이 입증된 전자 서명, 그리고 오픈소스 단독으로는 제공하지 못하는 벤더 책임성입니다. 저자가 AI의 도움을 받아 직접 제작한 그림입니다.

단 하나의 규칙: 실행 가능하거나 인용되거나

이 책의 모든 사실적 주장은 둘 중 한 방식으로 뒷받침됩니다. 실행 가능하거나 — 동반 저장소에 여러분이 직접 실행해 확인할 수 있는 파일이 있거나 — 아니면 1차 출처에 인용되어 있습니다. 규정, 표준, 공식 문서 페이지, 또는 동료 심사를 거친 논문(peer-reviewed paper)이 그 출처입니다.

동반 저장소는 여러분이 클론하는 저장소의 examples/ 폴더에 있으며 한 번만 클론하면 됩니다(클론 = git clone으로 로컬 작업 사본을 내려받는 것). 그 README.md는 약속을 분명하게 밝힙니다:

# Open-Source Bioprocess Data Systems — companion repo

Everything the book claims is **either runnable here or cited.** This repo is the
"runnable" half — and CI runs the same `make` targets the book prints, so
"implementable on a laptop" is *proven*, not asserted.

그 마지막 문장이 우리가 하는 가장 강력한 약속입니다. 여러분이 책을 읽으며 입력하는 바로 그 make 타깃들이, 지속적 통합(continuous integration)에 의해 깨끗한 머신에서 실행됩니다. 이 책의 어떤 명령이 동작하지 않았다면, 빌드가 출판 전에 실패했을 것입니다.

관통하는 사례와 시작하는 방법

책 전반에 걸쳐 우리는 하나의 공정을 따라갑니다. 단일클론항체를 생산하는 유가식 CHO 세포 배양으로, 단백질 A 컬럼에서 포착되는 공정 — 오늘날에도 승인된 항체 대부분을 만들어 내는 일꾼입니다. 숫자가 장난감이 아니라 현실적이도록, 8L 벤치 규모 바이오리액터를 1L 단백질 A 컬럼에서 포착하는 형태로 모델링했습니다. 14일 동안 골든 배치(golden batch, 이후 모든 장이 기준으로 삼는, 깨끗하고 목표에 들어맞는 참조 실행)는 mL당 약 2천만 개의 생존 세포까지 오르고, 생존율(viability, 아직 살아 있는 세포의 비율)이 68% 가까이로 떨어지기 전에 약 5.9g/L의 항체를 축적합니다 — 그 숫자 하나하나가 여러분이 생성하는 데이터셋 안에 있습니다. 중요한 곳에서는 현대의 집약화된(intensified) 변형 — 신선한 배지가 흘러 들어오고 회수물이 섞인 사용된 배지가 배치 단위가 아니라 연속적으로 빠져나가는 관류(perfusion) 배양 — 을 짚어 주는데, 시뮬레이터(simulator)는 이를 30일 연속 실행으로 제공하며, 원칙적으로 다중 컬럼 연속 포착 트레인(multi-column continuous capture train)에 공급하는 형태입니다. 그래서 관류 바이오리액터는 단지 읽는 것이 아니라 실행해 볼 수 있는 반면, 다중 컬럼 포착 트레인은 모델이 확장될 방향으로 스케치되어 있습니다.

시작은 다섯 개의 명령입니다. examples/README.md에서:

make venv # Python env + the simulator (uv)
make data # generate every dataset deterministically + MANIFEST.sha256
make up # bring up the core stack (postgres+timescale, mosquitto, grafana)
make seed # load the ISA-88/95 reference CHO line
make load # load the datasets into the historian + lab tables

make data에 있는 결정론적으로(deterministically)라는 단어가 핵심입니다. 시뮬레이터는 하나의 고정된 시드(SIM_SEED=2026)에서 실행되므로, 14일짜리 배치는 여러분의 노트북에서나 우리 쪽에서나 바이트 단위로 동일합니다. 생성이 끝나면 MANIFEST.sha256이 모든 파일의 해시를 기록합니다 — 18개의 결정론적 산출물 전부(시계열, 오프라인 분석값, 크로마토그램, 라만 스펙트럼, 관류 실행, 그리고 ASM과 AnIML 교환 내보내기 — 분석 및 랩 데이터를 위한 벤더 중립 표준 형식):

e3a78c7291c873b8ede54611d775152c356da138c22be1fc2f35ded04b359701 batches.csv
9b2eec56e5af4d12d7b78895578199fc88a49cf352ba2b45f99f447d275aa441 fedbatch_timeseries.parquet
6f4b5c4261fe3d7c4052326bd4d8fd3530c1cc06f8f0fd305dbb706cf9a0547c fedbatch_timeseries_10min.csv

여러분의 숫자가 책의 숫자와 어긋나는 일이 생기면, 단 하나의 차트가 여러분을 오도하기 전에 매니페스트가 곧바로 알려 줍니다. 이것이 작은 규모의 FAIR 데이터 사고방식입니다 — 찾을 수 있고(Findable), 접근 가능하고(Accessible), 상호 운용 가능하고(Interoperable), 재사용 가능한(Reusable) — 재현성(reproducibility)을 희망이 아니라 설계 목표로서 처음부터 새겨 넣은 것입니다 [8].

make up이 실제로 시작하는 것

make up 명령은 얇은 래퍼(wrapper)입니다. examples/Makefile에서 그것은 core 프로파일만 띄우고 데이터베이스가 응답하기를 기다립니다:

up: ## bring up the core stack (postgres+timescale, mosquitto, grafana)
$(COMPOSE) --profile core up -d
@echo "waiting for postgres..." && sleep 3
@until docker exec bioprocess-data-stack-postgres-1 pg_isready -U bioproc >/dev/null 2>&1; do sleep 2; done
@echo "core stack up."

그 뒤에는 모든 서비스를 정확히 한 번씩 정의하는 하나의 선언적 파일 examples/platform/compose/compose.yaml이 자리합니다. Docker Compose는 하나의 YAML로 멀티 컨테이너 애플리케이션을 기술하고 단일 명령으로 시작하게 해 주며 [9], 우리는 그 프로파일(profiles) 기능에 기댑니다. 그래야 여러분이 지금 보고 있는 계층에 대해서만 비용을 치릅니다:

services:
# --- core --------------------------------------------------------------
postgres:
# timescale/timescaledb IS PostgreSQL + TimescaleDB, so the historian
# hypertable and the ISA-88/95 batch model live in one joinable database.
image: timescale/timescaledb:2.17.2-pg17
profiles: ["core"]
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-bioproc} -d ${POSTGRES_DB:-bioproc}"]
interval: 5s
timeout: 5s
retries: 20

mosquitto:
image: eclipse-mosquitto:2.0.22
profiles: ["core"]

grafana:
image: grafana/grafana-oss:11.4.0
profiles: ["core"]

그 스니펫에서 천천히 짚어 볼 만한 점이 두 가지 있습니다. 첫째, 모든 이미지가 정확한 버전에 고정되어(pinned) 있습니다 — timescale/timescaledb:2.17.2-pg17, eclipse-mosquitto:2.0.22, grafana/grafana-oss:11.4.0 — 결코 :latest가 아닙니다. 떠다니는(floating) 태그는 규제 시스템 안의 시한폭탄이며, 이 저장소의 설계는 한 걸음 더 나아갑니다. 각 이미지의 기반 다이제스트(digest)를 커밋된 versions.lock에 고정해, 실행 중인 스택과 라이선스 인벤토리, 검증 등록부가 결코 조용히 어긋나지 않게 합니다. 둘째, postgres의 주석은 의도된 선택을 드러냅니다. TimescaleDB는 시계열 확장(time-series extension)을 갖춘 PostgreSQL 그 자체이므로, 여러분의 고빈도 센서 이력과 ISA-88/95 배치 맥락이 조인 가능한 동일한 데이터베이스에 함께 자리합니다. 이 하나의 결정이 나중에 통합의 고통 한 부류를 통째로 덜어 줍니다.

명령이 끝나면 여러분에게는 히스토리안, 메시지 브로커, 대시보드 서버가 돌아가고 있습니다 — 이후 모든 장이 전제하는, 늘 켜져 있는 토대입니다.

핵심 스택 서비스의 해부: make up이 실제로 띄우는 것

위 스니펫은 지면을 위해 줄여 놓은 것입니다. examples/platform/compose/compose.yaml 안의 실제 postgres 서비스 블록은 몇 줄 더 길고, 그 모든 줄이 제 몫을 합니다. 이 블록 하나가 make up이 띄우는 바로 그것이고, 여덟 개의 짧은 키 안에 스택을 재현 가능하고(reproducible), 자체 초기화되며(self-initializing), 안전하게 기다릴 수 있게 만드는 것의 대부분이 담겨 있으므로, 필드별로 해부해 볼 가치가 있습니다. 아래 카드가 그 해부입니다.

postgres 서비스 블록을 필드별로 해부한 식별 카드: image(고정된 태그), profiles core, environment 기본값, ports, 두 개의 volumes, restart 정책, 그리고 make up이 기다리는 강조된 healthcheck. postgres 핵심 서비스를 필드별로: 고정된 이미지, 프로파일 게이트, 자체 초기화 init-mount, 그리고 make up이 스택이 떴다고 선언하기 전에 블록하는 healthcheck. 저자가 AI의 도움을 받아 직접 제작한 그림입니다.

키를 순서대로 읽어 봅시다:

  • image: timescale/timescaledb:2.17.2-pg17 — 결코 :latest가 아니라 정확한 태그에 고정되어 있고, 의도적으로 순정 PostgreSQL이 아니라 TimescaleDB 이미지입니다. timescale/timescaledb는 시계열 확장이 함께 컴파일된 PostgreSQL 그 자체이므로, 여러분의 고빈도 센서 이력(ts.sensor_reading)과 ISA-88/95 배치 맥락(s88.batch)이 단일 질의로 조인할 수 있는 — 각 센서 행을 공유 키로 그 배치에 맞춰 짝지을 수 있는 — 하나의 데이터베이스에 함께 자리합니다.
  • profiles: ["core"] — 필요한 만큼만 비용을 치르는 게이트입니다. make updocker compose --profile core up -d를 실행하므로 core로 태그된 서비스(이 데이터베이스, Mosquitto 브로커, Grafana)만 시작되고, OPC UA 컬렉터(산업용 OPC UA 제어 시스템 서버에서 읽어 오는 서비스), 상용 목(유료 시스템을 흉내 내는, 라벨링된 대역), 트리플스토어(triplestore, 지식 그래프를 떠받치는 그래프 데이터베이스)는 이후 장이 요청할 때까지 잠들어 있습니다.
  • environmentPOSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB가 모두 ${POSTGRES_USER:-bioproc} 문법을 통해 bioproc로 기본 설정되므로, 스택은 설정 없이 실행되지만 모든 값을 셸에서 재정의할 수 있습니다.
  • ports: ["5432:5432"] — 컨테이너의 PostgreSQL 포트를 여러분의 노트북에 매핑합니다. 이것이 make seedmake load 타깃이 psql로 데이터베이스에 도달하는 방법입니다.
  • volumes — 두 개가 있고, 서로 다른 두 가지 일을 합니다. pgdata:/var/lib/postgresql/data는 명명된 볼륨이라 make down과 재부팅 이후에도 데이터가 살아남습니다. 두 번째 ../db:/docker-entrypoint-initdb.d:ro가 영리한 부분입니다. PostgreSQL의 공식 엔트리포인트는 데이터베이스가 처음 초기화될 때 그 디렉터리의 모든 *.sql 파일을 파일명 순서로 실행하므로, platform/db/를 거기에 마운트하면 컨테이너가 여러분의 추가 명령 없이 스스로 스키마를 구축합니다(00-init.sql부터 60-views.sql까지: 확장과 스키마, ISA-88/95 모델, 히스토리안 하이퍼테이블, 랩 및 이벤트 테이블, 거버넌스, ALCOA+ 감사 체인, 맥락화 뷰).
  • healthcheck — 카드의 녹색 블록이며, make up이 신뢰할 만한 이유입니다. 그것은 5초마다 최대 20회까지 pg_isready -U bioproc -d bioproc를 실행하고, make upcore stack up.을 출력하기 전에 호스트에서 until docker exec … pg_isready 루프로 이를 반영합니다. 그 핸드셰이크가 make seedmake load가 아직 초기화 중인 데이터베이스와 경합하지 않도록 보장합니다.

블록 하나만으로도 여러분은 스택의 전체 철학을 읽어낼 수 있습니다. 고정되고, 프로파일로 게이트되고, 스스로 시드하며, 헬스 게이트가 걸려 있습니다.

출처 핀의 해부: pinneddeterministic을 어떻게 검증 가능하게 만드는가

"고정됨(pinned)"과 "결정론적(deterministic)"은 주장하기는 쉽고 증명하기는 어려운 단어입니다. 이 저장소는 두 개의 평문 레코드로 둘 다를 검증 가능하게 만들며, 이 둘은 서로 다른 두 질문 — 올바른 소프트웨어가 실행되었는가? 그리고 그것이 올바른 데이터를 만들어 냈는가? — 에 답하므로 나란히 해부해 볼 가치가 있습니다.

두 개의 출처 레코드를 해부한 식별 카드: 태그와 sha256 다이제스트로 나뉘고 VERIFY-BEFORE-USE 자리표시자가 붙은 versions.lock 한 줄, 그리고 파일 해시와 파일명으로 된 MANIFEST.sha256 한 줄, 각각이 검증 가능하게 만드는 주장에 대응시키는 패널과 함께. 두 레코드가 책의 약속을 감사 가능하게 만듭니다: versions.lock 한 줄이 각 이미지의 다이제스트(실행된 소프트웨어)를 고정하고, MANIFEST.sha256 한 줄이 각 데이터셋의 해시(그것이 만들어 낸 데이터)를 고정합니다. 저자가 AI의 도움을 받아 직접 제작한 그림입니다.

첫 번째 레코드는 이미지 핀으로, platform/versions.lock을 작성하는 make lock 타깃이 만들어 냅니다. 각 줄은 태그 뒤에 그 콘텐츠 다이제스트가 붙은 형태입니다 — timescale/timescaledb:2.17.2-pg17 sha256:<64-hex digest>. 태그는 변할 수 있는, 사람이 읽을 수 있는 라벨이고, sha256: 다이제스트는 실제로 실행된 정확한 이미지 레이어의 불변 콘텐츠 주소입니다. 태그는 여러분 모르게 다시 푸시될 수 있지만 다이제스트는 그럴 수 없습니다. (make lock이 다이제스트를 해결할 수 없을 때 — 예컨대 오프라인일 때 — 잘못된 값 대신 정직한 자리표시자 VERIFY-BEFORE-USE를 적어, 빈틈이 조용히 묻히지 않고 드러나게 합니다.) versions.lock은 해결된 다이제스트와 함께 커밋되어 있어, 독자가 저장소에서 곧바로 실행 중인 스택을 고정된 레코드와 대조해 감사할 수 있으며, make lock은 여러분이 실제로 풀(pull)하는 레지스트리에 대해 그것을 다시 생성합니다.

두 번째 레코드는 데이터 핀으로, make data가 작성하는 datasets/MANIFEST.sha256입니다. 각 줄은 sha256(file) filename 형태이고 그 사이에 두 칸 공백이 들어갑니다 — 예를 들어 e3a78c72…9701 batches.csv. 고정된 시드(SIM_SEED=2026)에서 make data를 다시 실행하면 모든 해시가 바이트 단위로 재현되어야 하며, 하나라도 어긋나면 단 하나의 차트가 여러분을 오도하기 전에 매니페스트가 알려 줍니다.

이 두 레코드가 함께 책의 형용사들을 시험으로 바꿔 놓습니다. 고정됨versions.lock의 다이제스트가 실행 중인 것과 일치한다는 뜻이고, 결정론적make data를 다시 실행하면 MANIFEST.sha256의 모든 해시가 재현된다는 뜻입니다. 어느 것도 마케팅 주장이 아니며, 각각은 여러분이 실행할 수 있는 명령입니다.

CI가 실제로 증명하는 것: "실행 가능"의 명명된 단언

README의 가장 강력한 문장 — CI는 책이 인쇄하는 바로 그 make 타깃들을 실행한다 — 은 그 뒤에 있는 단언만큼만 유효합니다. 구현 가능성의 증거는 make test가 실행하는 pytest 스위트(examples/tests/)이며, 그중 한 테스트가 특히 결정론 주장을 뒷받침합니다. tests/test_simulator.pytest_determinism_two_runs_identical은 골든 배치를 두 번 시뮬레이션하고 두 value 배열이 np.array_equal임을 단언합니다. 자매 테스트인 test_fedbatch_shape_and_quality는 그 배치의 형태 — 전체 실행에 걸친 16개 태그(온도나 pH 같은, 이름이 붙은 센서 신호), 그리고 이후 장들이 의존하는 정확히 그 7일 차 품질 일탈(데이터 품질이 의심스럽다고 표시되는 구간: 두 개 태그에 180분간의 Uncertain 품질) — 를 고정합니다. 이것들은 장식용 테스트가 아니라, "재현 가능"을 약속이 아니라 사실로 만드는 명명된 단언입니다. 둘 중 하나라도 실패했다면, 빌드는 책이 출간되기 전에 실패했을 것입니다.

현장에서의 정직한 하이브리드: 데이터 무결성 기록이 실제로 보여 주는 것

몇 절 아래의 일화 — 7일 차 일탈 동안 센서가 무엇을 하고 있었는지 아무도 재구성할 수 없어 3주를 끄는 배치 조사 — 는 수사적 장식이 아닙니다. 규제 당국은 지난 10년간 바로 이 실패 양상을 적어 왔습니다. MHRA의 GXP 데이터 무결성 지침 및 정의(GXP Data Integrity Guidance and Definitions)가 존재하는 까닭은, 감사 추적의 빈틈, 귀속 불가능한 기록, 재현 불가능한 데이터가 드문 사고가 아니라 GMP 실사에서 되풀이되는 인용 가능한 지적 사항이기 때문입니다 [11]. 그것은 ALCOA+ 속성 — 귀속 가능(Attributable), 가독(Legible), 동시 기록(Contemporaneous), 원본(Original), 정확(Accurate), 그리고 완전(Complete), 일관(Consistent), 영속(Enduring), 가용(Available) — 을 성문화하는데, 바로 각 속성이 실제 기록이 미흡했던 방식에 대응하기 때문입니다. PIC/S 가이드 PI 041-1은 50개가 넘는 규제 당국의 실사관들에게 같은 말을 합니다. 데이터 무결성 통제는 검증된 시스템과 그 절차에 속하며, 신뢰할 수 있는 감사 추적의 부재 자체가 결함이라는 것입니다 [12]. 이것이 우리의 실행 가능한 시연 아래 깔린 인용된 현실입니다. 23장에서 여러분이 감사 체인을 변조해 보고 스스로 잡아낼 때, 여러분은 그 부재가 이 지침 문서들을 채우는 바로 그 통제를 작은 규모로 행사하는 것입니다. 오픈소스는 변조를 탐지 가능하게 만들 수 있지만, 내려받기만으로 시스템을 검증된 상태로 만들 수는 없습니다 — 그것이 정직한 하이브리드가 존재하는 이유 전부입니다.

어디서나 보게 될 관례

  • 코드는 저장소에서 나온다. 각 블록은 그 출처 파일을 밝힙니다(예: in examples/platform/compose/compose.yaml). 우리는 API도, 플래그도, 출력 한 줄도 지어내지 않습니다.
  • 목(mock)은 목이라고 라벨링된다. 노트북에서 실행할 수 없는 시스템 — AVEVA PI, SAP, Emerson DeltaV, 상용 LIMS(각각 산업용 데이터 히스토리안, 전사적 자원 관리 소프트웨어, 공정 제어 시스템, 실험실 정보 관리 시스템) — 은 실제 API 계약(진짜 시스템이 노출하는 것과 같은 요청·응답 형태)을 따르는, 분명하게 라벨링된 목(mock, 진짜를 대신하는 가벼운 가짜)으로 FastAPI 또는 OPC UA로 만들어 표현되며, 운영에 들어갈 때 운영 엔드포인트(production endpoint, 진짜 시스템의 주소)로 교체하는 방법이 문서화되어 있습니다. 통합 코드는 진짜이며, 그 상대편이 시뮬레이션된 것일 때는 항상 알려 드립니다.
  • 인용은 본문 안에 있다. [1] 같은 숫자 표시는 이 장의 참고 문헌 목록으로 연결됩니다. 본문에 별도의 참고 문헌 절은 없습니다.
  • 한계에 대한 정직함은 하나의 기능이다. 오픈소스가 GxP, Part 11, 고가용성, 또는 벤더 책임성에 미치지 못하는 곳마다, 우리는 그것을 분명하게 말하고 하이브리드 또는 상용 답을 가리킵니다. 또한 2026년의 라이선스 함정 — TimescaleDB의 TSL(Timescale License) 기능, Grafana의 AGPL(도구를 호스팅 서비스로 제공하면 여러분의 소스 코드까지 공개하도록 강제할 수 있는 카피레프트 라이선스), 그 밖의 것들 — 도 표시합니다. "오픈"이라는 이유로 채택한 도구가 재배포나 SaaS(software-as-a-service, 즉 호스팅 제품으로 운영하는 것) 맥락에서 여러분을 놀라게 하지 않도록 말입니다.
  • 이중 언어. 이 책은 영어와 한국어로 출간됩니다. 코드, 식별자, 로그 출력은 두 언어 모두에서 그대로 유지됩니다.

왜 중요한가

생물공정은 데이터의 급류를 만들어 냅니다 — 분당 수천 개의 태그가 붙은 센서 판독값, 오프라인 분석값, 크로마토그램(chromatogram), 스펙트럼 — 그리고 대부분의 시설에서 그 데이터는 아무도 질의할 수 없는 히스토리안, 공유 드라이브 위의 스프레드시트, 그리고 빌려 쓰되 통제하지는 못하는 벤더 클라우드에 흩어져 있습니다. 그 비용은 추상적인 것이 아닙니다. 그것은 7일 차 온도 일탈(temperature excursion) 동안 센서가 무엇을 하고 있었는지 아무도 재구성할 수 없어서 3주가 걸리는 배치 조사로, 또는 수신 사이트가 발신 사이트의 태그 이름을 해석할 수 없어 멈춰 버리는 기술 이전(technology transfer)으로 나타납니다.

스택을 직접, 공개적으로 만드는 것은 그 데이터와 여러분의 관계를 바꿔 놓습니다. 여러분은 플랫폼을 마법으로 취급하기를 멈추고 엔지니어링으로 취급하기 시작합니다. 그리고 우리가 모든 것을 실행 가능하거나 인용되거나 규칙에 묶어 두기 때문에, 여러분은 벤더의 마케팅이 주장하는 것과 규정이 실제로 요구하는 것의 차이를 배우게 됩니다 — 검사관이 여러분의 시설에 서 있을 때, 그것만이 유일하게 중요한 구분입니다.

실제 현장에서는

정직한 하이브리드는 책을 팔기 위해 우리가 지어낸 타협이 아닙니다. 그것은 모든 바이오 제조 데이터 팀의 일상적 현실입니다. 현대적인 시설에 들어가 보면, 오픈소스 도구들 — Grafana, PostgreSQL, Python, MQTT — 이 검증된 상용 히스토리안과 수백만 달러짜리 MES(Manufacturing Execution System, 생산 현장의 제조를 지시하고 기록하는 소프트웨어)와 나란히 즐겁게 돌아가고 있는 것을 보게 됩니다. 업계가 실제로 값을 치르는 기술은 그 경계가 어디에 있는지, 그리고 거기에 있는지를 아는 것입니다.

표준 기구들도 이를 따라잡았습니다. 이제 2025년판으로 나온 ISA-95(IEC 62264)는 책 전체가 그 위에 구성되는, 현장의 센서에서 전사 시스템까지를 아우르는 계층화된 레벨 0–4 참조 모델(현장의 필드 센서인 레벨 0에서, 제어와 운영을 거쳐 전사 비즈니스 시스템인 레벨 4까지)을 제공합니다 [10]. GAMP 5 제2판은 검증된 수명 주기 안에서의 오픈소스 소프트웨어를 명시적으로 승인했고 [6], FDA의 컴퓨터 소프트웨어 보증 지침은 검증을 문서 연극(documentation theater)이 아니라 위험에 비례하는 보증으로 재정의했습니다 [7]. Part 11 [3], 그 범위 및 적용 지침 [4], 그리고 EU Annex 11 [5]과 함께 읽으면 메시지는 일관됩니다. 규제 당국은 여러분의 시스템이 통제되고 여러분의 데이터가 무결성을 갖추는지에 관심이 있지, 상자에 어느 로고가 박혀 있는지에는 관심이 없습니다.

핵심 용어

  • OSS(open-source software) — 오픈소스 소프트웨어: 사용, 연구, 수정을 허용하는 라이선스 아래에서 소스가 공개적으로 제공되는 소프트웨어. 이 책 스택의 토대입니다.
  • 정직한 하이브리드(honest hybrid): 순수 OSS가 생물공정 데이터 플랫폼의 대략 80%를 감당하고, GxP의 마지막 1마일(검증, 전자 서명, 고가용성(high availability, HA), 벤더 책임성)은 하드닝이나 상용 시스템으로 충족한다는 이 책의 입장.
  • 검증 / 검증된 시스템(validation / a validated system): 전산화 시스템이 의도한 일을 하며, 그것을 둘러싼 통제와 절차가 시스템을 계속 그렇게 유지한다는 문서화된, 위험 기반 증거 — 그래서 그 기록을 신뢰할 수 있게 합니다. 이 속성은 어느 한 도구가 아니라 시스템 전체에 속합니다.
  • GxP / cGMP: "Good x Practice" 품질 규정의 집합. cGMP는 현행 우수 제조 관리 기준으로, GxP 데이터 무결성 규정이 그 안에서 작동하는, FDA가 집행하는 품질 시스템입니다.
  • 21 CFR Part 11: 전자 기록 또는 서명이 종이를 대체할 만큼 충분히 신뢰할 수 있는 시점을 정의하는 FDA 규정.
  • EU Annex 11: 전산화 시스템에 관한 유럽 GMP 지침. Part 11에 대응하는 규제 상대물입니다.
  • GAMP 5: GxP 컴퓨터 시스템 검증을 위한 ISPE의 위험 기반 참조 문헌. 제2판은 오픈소스를 직접 다룹니다.
  • ISA-95(IEC 62264): 전사 시스템과 제어 시스템을 통합하기 위한 표준 계층 모델(레벨 0–4)로, 스택을 구성하는 데 사용됩니다.
  • FAIR: 찾을 수 있고, 접근 가능하고, 상호 운용 가능하고, 재사용 가능한 데이터 — 플랫폼이 만들어 내는 모든 것의 설계 목표입니다.
  • 유가식 CHO / 단백질 A(Fed-batch CHO / Protein A): 관통하는 공정 — 한 배치에 걸쳐 영양분을 공급받는 중국 햄스터 난소(Chinese Hamster Ovary) 세포, 그리고 단백질 A 친화 컬럼에서 포착되는 항체.
  • Docker Compose / 프로파일(profile): 하나의 YAML 파일에서 멀티 컨테이너 스택을 부팅하는 도구. 프로파일은 어느 서비스가 시작될지를 통제해, 여러분이 필요한 장만 로드하게 합니다.
  • 결정론적 시뮬레이터(deterministic simulator, SIM_SEED=2026): 모든 데이터셋을 바이트 단위로 재현 가능하게 만드는 고정 시드 엔진.
  • 출처 핀(provenance pin, versions.lock / MANIFEST.sha256): "고정됨(pinned)"과 "결정론적(deterministic)"을 검증 가능하게 만드는 두 개의 평문 레코드 — make lock이 각 이미지의 sha256: 다이제스트를 기록하고, make data가 각 데이터셋의 파일 해시를 기록합니다.
  • init-mount(docker-entrypoint-initdb.d): PostgreSQL 엔트리포인트가 처음 시작할 때 실행하는 디렉터리. platform/db/를 거기에 마운트하면 컨테이너가 추가 명령 없이 스스로 스키마(0060)를 구축합니다.

다음 이야기

이제 여러분은 약속을 압니다. 여러분이 직접 만들고 실행하는 오픈소스 우선 스택, 오픈소스가 멈추는 곳의 정직한 하이브리드, 그리고 우리를 포함한 모두를 정직하게 유지하는 실행 가능하거나 인용되거나 규칙입니다. 다음 장 참조 아키텍처: 하나의 스택, 계층별로(The Reference Architecture: One Stack, Layer by Layer)는 그 스택을 한 페이지에 펼쳐 놓습니다. 우리는 모든 계층 — 엣지 연결성(edge connectivity), 메시지 버스(message bus), 히스토리안, 배치 모델, 맥락화(contextualization), 의미론, 컴플라이언스, 분석 — 을 그 ISA-95 레벨과 우리가 선택한 오픈소스 도구에 대응시키고, OSS 대 상용의 경계를 잉크로 그어 둡니다. 그래서 여러분은 첫 조각을 만들기 전에 센서에서 허가까지의 여정 전체를 볼 수 있습니다.