전체 과정 P1 시뮬레이터와 장비 알아보기 · 약 100분 · 초급

CH01시뮬레이터 시작하기

HPLC가 무엇을 하는 장비인지 큰 그림을 잡고, 시뮬레이터를 실행해 3D 화면 · 제어판 · Python Playground의 구성을 익힙니다.

학습 목표#

  • 이동상 · 정지상 · 분배라는 말로 HPLC가 물질을 분리하는 원리를 설명할 수 있습니다.
  • 역상 C18 컬럼에서 극성이 낮은 물질이 더 늦게 나오는 이유를 말할 수 있습니다.
  • 시료가 지나가는 길(용매병 → 탈기 → 펌프 → 오토샘플러 → 컬럼 → 검출기 → 폐액)을 순서대로 적을 수 있습니다.
  • 크로마토그램에서 머무름 시간(tR) · 피크 면적 · 피크 높이 · 베이스라인을 찾아 읽을 수 있습니다.
  • 시뮬레이터를 실행하고 3D 장비 뷰 · 상태 패널 · 크로마토그램 · 이벤트 로그 · Python Playground가 어디에 있는지 찾을 수 있습니다.

이론#

1교시 — HPLC는 무엇을 하는 장비인가#

고성능 액체 크로마토그래피(High-Performance Liquid Chromatography, HPLC) 는 섞여 있는 여러 물질을 분리하고, 각 물질이 얼마나 들어 있는지 재는 장비입니다. 커피 속 카페인, 약 속 유효 성분, 물 속 오염 물질 등을 분석할 때 씁니다.

원리는 세 단어로 정리됩니다.

용어뜻HPLC에서의 실체
이동상(mobile phase)흐르면서 시료를 실어 나르는 액체물 + 아세토니트릴(또는 메탄올) 혼합 용매
정지상(stationary phase)움직이지 않고 시료를 붙잡는 물질컬럼 안에 채운 작은 실리카 입자 표면의 C18 사슬
분배(partition)물질이 이동상과 정지상 사이를 오가며 나뉘는 것정지상 쪽에 오래 머무는 물질일수록 늦게 나옴

물질마다 정지상을 "좋아하는 정도"가 다릅니다. 정지상에 오래 머무는 물질은 컬럼을 늦게 빠져나오고, 이동상에 주로 머무는 물질은 빨리 빠져나옵니다. 이렇게 나오는 시간의 차이로 물질이 분리됩니다. 이 정도를 숫자로 나타낸 것이 머무름 계수(retention factor, k) 입니다.

  • tR = t0 × (1 + k) — t0 는 정지상에 전혀 붙지 않는 물질이 컬럼을 빠져나오는 시간(불감 시간, dead time)입니다.
  • k = 0 이면 t0 에 바로 나오고, k 가 클수록 늦게 나옵니다.
비유로 이해하기

복도(컬럼)를 지나가는 학생들(물질)을 떠올려 보세요. 복도 벽에 게시판(정지상)이 붙어 있습니다. 게시판에 관심이 많은 학생은 자주 멈춰 서서 늦게 도착하고, 관심이 없는 학생은 곧장 지나갑니다. 사람들의 흐름(이동상)은 모두에게 같습니다.

역상(Reversed-Phase) C18 컬럼#

가장 많이 쓰는 방식은 역상 크로마토그래피입니다. "역상"이라는 이름은 옛날 방식(극성 정지상 + 비극성 이동상)과 극성이 반대라서 붙었습니다.

  • 정지상: 실리카 입자 표면에 탄소 18개짜리 사슬(옥타데실, C18)을 붙인 것 → 비극성(기름 같은 성질)
  • 이동상: 물 + 유기 용매 → 극성

비슷한 것끼리 잘 어울리므로(like dissolves like), 극성이 낮은(기름에 가까운) 물질은 C18 사슬에 오래 붙어 있어 늦게 나오고, 극성이 높은(물에 잘 녹는) 물질은 이동상과 함께 빨리 나옵니다. 이동상에 유기 용매 비율을 높이면 이동상 자체가 덜 극성이 되어 모든 물질이 빨리 나옵니다 (이동상 조성을 바꾸는 방법은 ch03에서 다룹니다).

python시뮬 실행 가능
# 머무름 계수 k 와 머무름 시간: tR = t0 * (1 + k)
t0 = 1.0   # 머무르지 않는 물질이 컬럼을 빠져나오는 시간 (min, 가정값)

# 가상의 물질 3개. k 가 클수록 정지상(C18)에 오래 붙어 있습니다.
compounds = {
    "A (극성 큼)":   0.8,
    "B (중간)":      2.5,
    "C (극성 작음)": 6.0,
}

for name, k in compounds.items():
    tR = t0 * (1 + k)
    in_stationary = k / (1 + k) * 100     # 정지상에 머문 시간 비율 (%)
    print(f"{name:<12} k = {k:4.1f}  tR = {tR:4.1f} min  정지상 체류 {in_stationary:4.1f} %")

실행하면 극성이 작은 C가 7.0 min으로 가장 늦게 나오고, 시간의 약 86 %를 정지상에 붙어 보낸다는 것을 확인할 수 있습니다.

시료가 지나가는 길#

① 용매병 이동상 A · B ② 탈기 기포 제거 ③ 펌프 혼합 · 고압 송액 ④ 오토샘플러 시료 주입 ⑤ 컬럼 C18 · 분리 ⑥ 검출기 UV 흡광도 폐액 waste 크로마토그램 신호 → 데이터 시스템 굵은 화살표 = 액체 흐름 · 점선 = 전기 신호 펌프 출구부터 컬럼까지 고압 구간
HPLC 유로. 펌프 출구부터 컬럼까지는 수백 bar의 고압이 걸리는 구간입니다.
순서장치하는 일
①용매병이동상(예: A = 물, B = 아세토니트릴)을 담아 둡니다.
②탈기(degasser)용매에 녹은 공기를 빼서 펌프와 검출기에 기포가 생기지 않게 합니다.
③펌프용매를 정해진 비율로 섞고, 정해진 유속(mL/min)으로 밀어냅니다. 컬럼 저항 때문에 압력이 생깁니다.
④오토샘플러바이알에서 시료를 정해진 부피(µL)만큼 뽑아 흐르는 이동상에 넣습니다(주입, injection).
⑤컬럼시료 속 물질이 분배되며 서로 다른 시간에 빠져나옵니다. 온도조절기 안에 넣어 온도를 일정하게 둡니다.
⑥검출기빠져나온 물질이 빛(UV)을 얼마나 흡수하는지 재서 전기 신호로 바꿉니다.
—폐액검출기를 지난 액체는 폐액 통으로 갑니다. 시료는 다시 쓰지 않습니다.

크로마토그램 읽기#

검출기 신호를 시간에 따라 그린 그래프가 크로마토그램(chromatogram) 입니다.

신호 (mAU) 시간 (min) tR₁ tR₂ 피크 높이 피크 면적 (색칠한 넓이) 베이스라인 늦게 나온 물질 먼저 나온 물질 주입 0
크로마토그램의 네 가지 요소. 가로축은 주입 후 지난 시간, 세로축은 검출기 신호입니다.
요소읽는 법알려 주는 것
베이스라인(baseline)물질이 없을 때의 평평한 바닥선장비가 안정했는지 (흔들리면 기포 · 온도 변화 의심)
머무름 시간(tR)주입부터 피크 꼭대기까지의 시간무슨 물질인지 (같은 조건이면 같은 물질은 같은 tR)
피크 높이(height)베이스라인에서 꼭대기까지양에 비례 (보조 지표)
피크 면적(area)피크와 베이스라인 사이 넓이얼마나 들어 있는지 (정량의 기본 값)

정성(무엇인가)은 tR로, 정량(얼마나인가)은 주로 면적으로 판단합니다. 면적으로 농도를 구하는 검량선은 ch07에서 다룹니다.

python시뮬 실행 가능
import numpy as np

# 가상의 크로마토그램: 가우스 모양 피크 2개 + 약간의 잡음
dt = 0.01                                  # 0.01 min 간격으로 기록
t = np.arange(0, 6, dt)                    # 0 ~ 6 min
rng = np.random.default_rng(0)

def peak(t, tR, height, sigma):
    return height * np.exp(-0.5 * ((t - tR) / sigma) ** 2)

baseline = 0.5                             # 베이스라인 (mAU)
signal = (baseline
          + peak(t, 1.8, 40.0, 0.05)       # 극성이 큰 물질: 먼저 나옴
          + peak(t, 3.6, 25.0, 0.08)       # 극성이 작은 물질: 늦게 나옴
          + rng.normal(0, 0.2, t.size))

def measure(t0, t1):
    m = (t >= t0) & (t < t1)
    y = signal[m] - baseline               # 베이스라인을 빼고 잽니다
    i = np.argmax(y)
    return t[m][i], y[i], np.sum(y) * dt   # tR, 높이, 면적(mAU*min)

for name, (t0, t1) in {"피크 1": (1.4, 2.2), "피크 2": (3.1, 4.1)}.items():
    tR, h, a = measure(t0, t1)
    print(f"{name}: tR = {tR:.2f} min, 높이 = {h:.1f} mAU, 면적 = {a:.2f} mAU*min")

# 글자로 그린 크로마토그램 (1.0 ~ 4.4 min, 0.1 min 마다 한 줄)
print("\n t(min)  신호")
for k in range(100, 440, 10):
    bar = "#" * int(max(signal[k], 0))
    print(f"{t[k]:5.1f}  {bar}")

두 피크의 높이는 40과 25로 다르지만 면적은 둘 다 약 5.0 입니다. 늦게 나온 피크는 넓게 퍼지기 때문입니다. "높이가 크면 양이 많다"고 단정하면 안 되는 이유가 여기에 있습니다.

애질런트 1260 Infinity II 모듈 스택#

애질런트(Agilent) 1260 Infinity II 는 기능별 모듈을 위아래로 쌓아(stack) 하나의 시스템으로 씁니다. 이 시뮬레이터는 아래 구성을 기본으로 모사합니다. 실제 실험실 장비는 모듈 종류(예: DAD 검출기, 다른 펌프)가 다를 수 있으니 장비 앞판의 라벨로 확인합니다.

용매 캐비닛 (Solvent Cabinet) 가변파장 검출기 VWD G7114A 컬럼 온도조절기 MCT G7116A 바이알 샘플러 (Vialsampler) G7129A 4원 펌프 (Quaternary Pump) G7111B · 탈기 장치 내장 용매병을 올려 두는 칸 (넘친 용매를 받아 냄) 컬럼에서 나온 성분의 UV 흡광도를 측정 컬럼을 넣고 온도를 일정하게 유지 바이알에서 시료를 정해진 부피만큼 뽑아 주입 용매를 섞고 일정한 유속으로 고압 송액 정면에서 본 스택 (위 → 아래)
시뮬레이터 기본 구성의 모듈 스택 (정면). 모델 번호는 Agilent 1260 Infinity II 제품군 기준입니다.
모듈모델 번호역할유로에서의 위치
4원 펌프 (Quaternary Pump)G7111B용매 최대 4종을 섞어 송액, 탈기 장치 내장② ③
바이알 샘플러 (Vialsampler)G7129A바이알 시료를 자동 주입④
다중 컬럼 온도조절기 (Multicolumn Thermostat, MCT)G7116A컬럼 온도 유지⑤
가변파장 검출기 (Variable Wavelength Detector, VWD)G7114A한 파장(또는 몇 개)의 UV 흡광도 측정, 중수소 램프 사용⑥
용매 캐비닛 (Solvent Cabinet)—용매병 · 폐액 받침①

최대 압력 · 유속 범위 같은 세부 사양은 모델과 옵션에 따라 다르므로 이 차시에서는 외우지 않습니다. 필요할 때 정보 카드와 아래 참고자료의 공식 사용자 설명서를 확인합니다 (펌프 사양은 ch03, 샘플러 · 컬럼 · 검출기 사양은 ch04).

시뮬레이터로 익히는 것, 실물에서만 익히는 것#

시뮬레이터로 충분히 익힐 수 있는 것실물에서만 익힐 수 있는 것
모듈 이름 · 위치 · 유로 순서피팅을 손으로 조일 때의 감각(너무 세게 · 너무 약하게)
압력 · 유속 · 온도 · 램프 상태 읽기누설(leak) — 피팅 주변의 작은 물방울, 마른 염 결정
메서드 · 시퀀스 입력 순서용매 냄새 · 환기, 장갑 · 보안경 착용 습관
크로마토그램 해석, 계산펌프 소음 · 진동의 변화로 이상 알아차리기
잘못된 조작의 결과를 안전하게 미리 보기실제 폐액 처리, 용매병 교체
시뮬레이터는 실물 실습을 대신하지 않습니다

이 강좌는 실물 장비를 쓰기 전에 순서와 개념을 몸에 익히는 것이 목적입니다. 실물 HPLC를 처음 사용할 때는 반드시 실험실 담당자의 교육을 받고, 실험실 안전 수칙(보안경 · 장갑 · 용매 취급)을 따르세요.

2교시 — 시뮬레이터 실행과 화면 구성#

이 단원에서 할 일#

강좌 사이트를 열고, 시뮬레이터 화면의 네 영역과 Python Playground의 위치 · 조작법을 익힙니다.

사이트 접속 또는 로컬 실행#

배포된 강좌 사이트 주소가 있으면 브라우저로 바로 접속합니다. 내 PC에서 실행하려면 다음 순서를 따릅니다.

  1. Python 3 가 설치되어 있는지 확인합니다. 명령 프롬프트(<kbd>Win</kbd>+<kbd>R</kbd> → cmd → <kbd>Enter</kbd>)에서 python --version 을 입력합니다.
  2. 강좌 저장소 폴더(맨 위에 build.py 가 있는 폴더)로 이동합니다.
  3. 아래 명령을 실행합니다. Windows에서는 저장소에 start.bat 이 있으면 더블클릭해도 같습니다.
  4. 미리보기: http://localhost:8000 (Ctrl+C 로 종료) 라는 줄이 나오면 브라우저 주소창에 http://localhost:8000 을 입력합니다.
  5. 다 쓴 뒤에는 명령 창에서 <kbd>Ctrl</kbd>+<kbd>C</kbd> 를 눌러 서버를 끕니다.
bash
cd 강좌저장소폴더
python build.py --serve
text
미리보기: http://localhost:8000  (Ctrl+C 로 종료)
시뮬레이터 화면은 단계적으로 공개됩니다

3D 장비 모델과 시뮬레이터 화면은 강좌 진행에 맞춰 추가됩니다. 사이드바나 차시 머리에 3D 뷰어 · 시뮬레이터 버튼이 보이지 않으면 아직 준비 중인 것입니다. 그동안은 이 차시의 Playground 실습(numpy 계산)으로 같은 내용을 익히고, 모델이 준비되면 아래 따라하기를 다시 해 봅니다.

화면 구성#

상단 도구 막대 ▶ 유로 애니메이션 · ⟲ 뷰 초기화 · 앞판 열기/닫기 · Python Playground ↗ A 3D 장비 뷰 왼쪽 드래그 회전 · 오른쪽 드래그 이동 · 휠 확대/축소 모듈 클릭 → 정보 카드 B 모듈 상태 패널 압력 (bar) 유속 (mL/min) 컬럼 온도 (°C) 램프 (켜짐 / 꺼짐) 모듈 상태 (Ready · Run · Error) C 실시간 크로마토그램 D 이벤트 로그 10:02:11 Pump On 10:02:40 VWD Lamp on 10:05:03 Injection 1
시뮬레이터 화면 구성도. A 3D 장비 뷰 · B 모듈 상태 패널 · C 실시간 크로마토그램 · D 이벤트 로그.
영역이름보는 것
위상단 도구 막대유로 애니메이션 재생, 뷰 초기화, 앞판 열기/닫기, Playground 열기
A3D 장비 뷰모듈 스택과 배관. 돌려 보고 모듈을 클릭합니다.
B모듈 상태 패널압력(bar) · 유속(mL/min) · 컬럼 온도(°C) · 램프 상태 · 모듈 상태(Ready/Run/Error)
C실시간 크로마토그램분석 중 검출기 신호. 위 1교시의 그래프와 같은 모양입니다.
D이벤트 로그펌프 켜짐, 램프 켜짐, 주입, 오류 같은 사건이 시간순으로 쌓입니다.
상태는 패널, 원인은 로그

압력이 갑자기 0이 되면 B 패널에서 먼저 알아차리고, 왜 그런지는 D 이벤트 로그에서 찾습니다. 실물 장비의 데이터 시스템도 같은 구조(상태 표시 + 로그북)를 가지므로 지금부터 습관을 들여 두면 좋습니다.

3D 뷰 조작#

  1. 3D 장비 뷰(A) 안에 마우스 포인터를 올립니다.
  2. 왼쪽 버튼을 누른 채 끌면 장비 둘레로 시점이 회전합니다. 좌우로 끌어 측면 · 후면을 봅니다.
  3. 오른쪽 버튼을 누른 채 끌면 화면이 평행 이동합니다. 배관이 화면 밖으로 나갔을 때 씁니다.
  4. 마우스 휠을 굴려 확대/축소합니다. 피팅 연결부를 가까이 볼 때 씁니다.
  5. 시점이 엉켰으면 상단 도구 막대의 뷰 초기화 버튼을 눌러 정면 시점으로 돌아옵니다.
  6. 모듈을 클릭하면 정보 카드(모델 번호 · 역할 · 주요 사양)가 열립니다. 카드의 닫기(×)로 닫습니다.
  7. 모듈을 선택한 상태에서 앞판 열기/닫기를 누르면 앞 덮개가 열려 안쪽 부품(예: 펌프 헤드, 샘플러 니들, 컬럼)을 볼 수 있습니다.

3D 시뮬레이터 열기

3D 뷰어 열기

Python Playground#

Playground는 브라우저 안에서 Python(Pyodide)을 실행하는 편집기입니다. 이 강좌의 계산 실습과, 시뮬레이터를 코드로 조작하는 실습에 씁니다.

  1. 사이드바 또는 차시 머리의 Python 버튼을 누르거나, 코드 블록의 Playground에서 열기 버튼을 누릅니다.
  2. 처음 열 때 Python 실행 환경을 내려받느라 몇 초 ~ 수십 초 걸립니다. ▶ 실행 버튼이 눌리는 상태가 될 때까지 기다립니다.
  3. 편집기에 코드를 쓰고 ▶ 실행(<kbd>Ctrl</kbd>+<kbd>Enter</kbd>)을 누릅니다. 결과는 출력 창에 나옵니다.
  4. 오래 도는 코드는 ■ 정지 버튼으로 멈춥니다. 시간 제한(초) 이 지나도 자동으로 멈춥니다.
  5. 위쪽 타깃 목록에서 Simulator 를 고르고 오른쪽 상태 표시를 확인합니다. 시뮬레이터가 준비되지 않았으면 "찾을 수 없음"이 표시되며, 이 차시의 numpy 실습은 타깃과 관계없이 실행됩니다.

Python Playground 열기

동작방법
코드 실행▶ 실행 또는 <kbd>Ctrl</kbd>+<kbd>Enter</kbd>
실행 멈춤■ 정지
편집기에서 빠져나오기<kbd>Esc</kbd>
3D 회전 / 이동 / 확대왼쪽 드래그 / 오른쪽 드래그 / 휠
브라우저 강력 새로고침(캐시 무시)<kbd>Ctrl</kbd>+<kbd>F5</kbd> (또는 <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>R</kbd>)
로컬 서버 끄기명령 창에서 <kbd>Ctrl</kbd>+<kbd>C</kbd>

브라우저 권장 사양#

  • Chrome 또는 Edge 최신 버전을 권장합니다. 3D 화면은 WebGL 을 사용합니다.
  • 노트북은 전원을 연결하고, 3D 화면이 끊기면 다른 탭을 닫습니다.
  • 학교 · 회사 PC에서 하드웨어 가속이 꺼져 있으면 3D 화면이 비어 보일 수 있습니다(아래 오류 1번).
자주 하는 실수
  • lessons/ch01.html 같은 파일을 탐색기에서 더블클릭해 file:// 주소로 엽니다 → 3D 모델 · Playground가 동작하지 않습니다. 반드시 http://localhost:8000 으로 엽니다.
  • 서버를 켠 명령 창을 닫아 버립니다 → 페이지가 "연결할 수 없음"이 됩니다. 실습이 끝날 때까지 창을 열어 둡니다.
  • 3D 뷰에서 휠을 너무 많이 굴려 장비가 사라졌다고 생각합니다 → 뷰 초기화를 누릅니다.

실습 (시뮬레이터)#

실습 A — 유로 순서 받아 적기 (1교시)
  1. 시뮬레이터 상단 도구 막대에서 ▶ 유로 애니메이션을 누릅니다. (시뮬레이터가 아직 없으면 위 그림 "HPLC 유로"를 보고 합니다.)
  2. 이동상이 빛나는 점으로 흐르는 것을 보며, 지나가는 장치를 6단계로 받아 적습니다.
  3. 아래 코드의 my_notes 에 적은 순서를 넣고 실행해 맞았는지 확인합니다.
python시뮬 실행 가능
# 시료가 지나가는 길: 6단계 순서 확인하기
answer = ["용매병", "탈기", "펌프", "오토샘플러", "컬럼", "검출기"]

# TODO: 유로 애니메이션을 보며 받아 적은 순서로 아래 리스트를 고치세요
my_notes = ["용매병", "펌프", "탈기", "컬럼", "오토샘플러", "검출기"]

for i, (a, b) in enumerate(zip(answer, my_notes), start=1):
    mark = "OK" if a == b else "XX"
    print(f"{i}단계 [{mark}] 정답={a:<8} 내 기록={b}")

score = sum(a == b for a, b in zip(answer, my_notes))
print(f"\n맞힌 단계: {score}/6")
풀이

탈기는 펌프 앞(용매에서 공기를 먼저 빼야 펌프에 기포가 들어가지 않음), 주입은 컬럼 앞(시료가 컬럼을 지나야 분리됨)입니다.

python시뮬 실행 가능
answer = ["용매병", "탈기", "펌프", "오토샘플러", "컬럼", "검출기"]
my_notes = ["용매병", "탈기", "펌프", "오토샘플러", "컬럼", "검출기"]

score = sum(a == b for a, b in zip(answer, my_notes))
print(f"맞힌 단계: {score}/6")
print(" -> ".join(my_notes + ["폐액"]))
실습 B — 크로마토그램에서 면적이 큰 피크 찾기 (1교시)

아래 코드는 피크 3개짜리 가상 크로마토그램을 만듭니다. TODO 를 채워 각 피크의 tR · 높이 · 면적을 출력하고, 면적이 가장 큰 피크를 고르세요.

python시뮬 실행 가능
import numpy as np

dt = 0.01
t = np.arange(0, 8, dt)
baseline = 1.0

def peak(t, tR, height, sigma):
    return height * np.exp(-0.5 * ((t - tR) / sigma) ** 2)

signal = (baseline + peak(t, 1.5, 60, 0.04)
                   + peak(t, 3.2, 30, 0.10)
                   + peak(t, 5.8, 20, 0.20))

windows = {"피크 1": (1.0, 2.0), "피크 2": (2.6, 3.8), "피크 3": (4.8, 6.8)}

for name, (t0, t1) in windows.items():
    m = (t >= t0) & (t < t1)
    y = signal[m] - baseline
    # TODO: tR(꼭대기 시간), height(꼭대기 높이), area(면적 = 합 x dt)를 구하세요
    tR = 0
    height = 0
    area = 0
    print(f"{name}: tR={tR:.2f} min  높이={height:.1f}  면적={area:.2f}")
풀이
python시뮬 실행 가능
import numpy as np

dt = 0.01
t = np.arange(0, 8, dt)
baseline = 1.0

def peak(t, tR, height, sigma):
    return height * np.exp(-0.5 * ((t - tR) / sigma) ** 2)

signal = (baseline + peak(t, 1.5, 60, 0.04)
                   + peak(t, 3.2, 30, 0.10)
                   + peak(t, 5.8, 20, 0.20))

windows = {"피크 1": (1.0, 2.0), "피크 2": (2.6, 3.8), "피크 3": (4.8, 6.8)}
result = {}
for name, (t0, t1) in windows.items():
    m = (t >= t0) & (t < t1)
    y = signal[m] - baseline
    i = np.argmax(y)
    tR, height, area = t[m][i], y[i], np.sum(y) * dt
    result[name] = area
    print(f"{name}: tR={tR:.2f} min  높이={height:.1f}  면적={area:.2f}")

print("면적이 가장 큰 피크:", max(result, key=result.get))

가장 높은 피크 1(높이 60)이 아니라, 가장 낮지만 넓은 피크 3의 면적(약 10.0)이 가장 큽니다.

확인 문제 1

역상 C18 컬럼에서 같은 이동상 조건으로 분석할 때, 가장 늦게 나올 가능성이 큰 물질은?

  1. 물에 아주 잘 녹는 극성 물질
  2. 극성이 낮아 기름에 잘 녹는 물질
  3. 이동상과 똑같은 물질
  4. 정지상에 전혀 붙지 않는 물질
정답 보기② — C18 정지상은 비극성이라 극성이 낮은 물질과 잘 어울립니다. 정지상에 오래 머물수록(k가 클수록) tR이 길어집니다. ④는 t0에 가장 먼저 나옵니다.
확인 문제 2

크로마토그램에서 시료 속 물질이 얼마나 들어 있는지 판단할 때 기본으로 쓰는 값은?

  1. 머무름 시간(tR)
  2. 베이스라인의 높이
  3. 피크 면적
  4. 분석 총 시간
정답 보기③ — 피크 면적은 검출기를 지나간 물질의 총량에 비례합니다. tR은 "무슨 물질인가"(정성)를 알려 주고, 베이스라인은 장비 안정성을 보여 줍니다. 실습 B처럼 높이만 보면 넓은 피크의 양을 과소평가합니다.
실습 C — 정면 · 측면 · 후면 돌려 보고 모델 번호 표 만들기 (2교시)
  1. 3D 장비 뷰에서 뷰 초기화를 눌러 정면에서 시작합니다.
  2. 왼쪽 드래그로 약 90° 씩 돌려 오른쪽 측면 → 후면 → 왼쪽 측면 을 차례로 봅니다. 후면에서 모듈 사이를 잇는 배관과 전원 · 통신 케이블 위치를 관찰합니다.
  3. 정면으로 돌아와 모듈을 하나씩 클릭하고 정보 카드에서 모델 번호를 찾습니다.
  4. 아래 코드의 표를 완성해 실행합니다. (3D 모델이 준비되지 않았다면 위 "모듈 스택" 그림과 표에서 찾습니다.)
python시뮬 실행 가능
# 모듈 정보 카드에서 찾은 모델 번호를 표로 정리하기
modules = [
    # (스택 위치, 모듈 이름, 모델 번호, 역할)
    ("1층(맨 아래)", "Quaternary Pump",          "G7111B", "용매 혼합 + 송액, 탈기 내장"),
    ("2층",          "Vialsampler",              "TODO",   "TODO"),
    ("3층",          "Multicolumn Thermostat",   "TODO",   "TODO"),
    ("4층",          "Variable Wavelength Det.", "TODO",   "TODO"),
]

print(f"{'위치':<10}{'모듈':<28}{'모델':<8}역할")
print("-" * 70)
for pos, name, model, role in modules:
    print(f"{pos:<10}{name:<28}{model:<8}{role}")

todo = sum(row.count("TODO") for row in modules)
print(f"\n남은 TODO: {todo}개")
풀이
python시뮬 실행 가능
modules = [
    ("1층(맨 아래)", "Quaternary Pump",          "G7111B", "용매 혼합 + 송액, 탈기 내장"),
    ("2층",          "Vialsampler",              "G7129A", "바이알 시료 자동 주입"),
    ("3층",          "Multicolumn Thermostat",   "G7116A", "컬럼 온도 유지"),
    ("4층",          "Variable Wavelength Det.", "G7114A", "UV 흡광도 측정"),
]

print(f"{'위치':<10}{'모듈':<28}{'모델':<8}역할")
print("-" * 70)
for pos, name, model, role in modules:
    print(f"{pos:<10}{name:<28}{model:<8}{role}")
실습 D — 카메라가 어디에 있어야 각 면이 보일까 (2교시, numpy)

3D 뷰의 "회전"은 카메라를 장비 둘레로 돌리는 것입니다. 장비 중심을 원점, 정면 방향을 +z 로 두고, 카메라를 y축 둘레로 돌렸을 때 위치를 계산합니다. TODO 를 채워 정면 · 오른쪽 측면 · 후면 · 왼쪽 측면의 각도를 넣으세요.

python시뮬 실행 가능
import numpy as np

def rot_y(deg):
    r = np.radians(deg)
    return np.array([[ np.cos(r), 0, np.sin(r)],
                     [ 0,         1, 0        ],
                     [-np.sin(r), 0, np.cos(r)]])

camera = np.array([0.0, 0.3, 2.0])   # 장비 정면 2 m 앞, 0.3 m 위

# TODO: 각 면을 보는 회전 각도(deg)를 채우세요
views = {"정면": 0, "오른쪽 측면": None, "후면": None, "왼쪽 측면": None}

for name, deg in views.items():
    if deg is None:
        print(f"{name}: TODO")
        continue
    x, y, z = np.round(rot_y(deg) @ camera, 2) + 0.0
    print(f"{name:<8} {deg:3d} deg -> 카메라 x={x:5.2f}, y={y:4.2f}, z={z:5.2f}")
풀이
python시뮬 실행 가능
import numpy as np

def rot_y(deg):
    r = np.radians(deg)
    return np.array([[ np.cos(r), 0, np.sin(r)],
                     [ 0,         1, 0        ],
                     [-np.sin(r), 0, np.cos(r)]])

camera = np.array([0.0, 0.3, 2.0])
views = {"정면": 0, "오른쪽 측면": 90, "후면": 180, "왼쪽 측면": 270}

for name, deg in views.items():
    x, y, z = np.round(rot_y(deg) @ camera, 2) + 0.0
    print(f"{name:<8} {deg:3d} deg -> 카메라 x={x:5.2f}, y={y:4.2f}, z={z:5.2f}")

후면(180°)에서 카메라의 z 가 −2.00 이 됩니다. 장비 뒤쪽 2 m 에서 바라보는 것입니다. 높이 y 는 회전해도 변하지 않습니다.

확인 문제 3

3D 장비 뷰를 이리저리 돌리다가 장비가 화면에서 사라졌습니다. 가장 먼저 할 일은?

  1. 브라우저를 닫고 컴퓨터를 다시 시작한다
  2. 상단 도구 막대의 뷰 초기화 버튼을 누른다
  3. Playground에서 ■ 정지를 누른다
  4. 명령 창에서 Ctrl+C 를 누른다
정답 보기② — 뷰 초기화는 카메라를 정면 기본 시점으로 되돌립니다. ④는 로컬 서버를 꺼 버려 오히려 페이지가 동작하지 않게 되고, ③은 Python 실행만 멈춥니다.
확인 문제 4

압력 값이 갑자기 0 bar 로 떨어졌습니다. 원인을 찾기 위해 먼저 볼 화면 영역은?

  1. A 3D 장비 뷰
  2. B 모듈 상태 패널
  3. C 실시간 크로마토그램
  4. D 이벤트 로그
정답 보기④ — 상태 패널(B)은 "지금 값"을 보여 주어 이상을 알아차리게 하고, 이벤트 로그(D)는 펌프 꺼짐 · 오류 같은 사건을 시간순으로 남겨 "왜"를 알려 줍니다.

자주 나는 오류와 해결#

1) 3D 뷰가 검은(또는 흰) 화면으로 비어 있음#

text
THREE.WebGLRenderer: Error creating WebGL context.
  • 원인: 브라우저의 하드웨어 가속(WebGL)이 꺼져 있거나, 그래픽 드라이버가 WebGL 을 막고 있습니다. 원격 데스크톱 · 가상 머신에서도 자주 생깁니다.
  • 해결:
    1. Chrome: <b>설정 › 시스템 › 가능한 경우 그래픽 가속 사용</b>을 켜고 다시 시작합니다. Edge: <b>설정 › 시스템 및 성능 › 가능한 경우 그래픽 가속 사용</b>.
    2. 주소창에 chrome://gpu (Edge는 edge://gpu)를 입력해 WebGL 항목이 "Hardware accelerated" 인지 확인합니다.
    3. 그래도 안 되면 다른 PC나 브라우저에서 시도하고, 그동안은 Playground 실습으로 진행합니다.

2) 사이트를 고쳤거나 갱신했는데 화면이 예전 그대로이거나 일부가 빈 칸#

  • 원인: 브라우저가 이전 파일을 캐시에서 불러왔습니다.
  • 해결: <kbd>Ctrl</kbd>+<kbd>F5</kbd> 로 강력 새로고침합니다. 그래도 같으면 개발자 도구(<kbd>F12</kbd>)를 연 상태에서 새로고침 버튼을 길게 눌러(또는 우클릭) 캐시 비우기 및 강력 새로고침을 고릅니다.

3) python build.py --serve 실행 시 포트 오류#

text
OSError: [WinError 10048] 각 소켓 주소(프로토콜/네트워크 주소/포트)는 하나만 사용할 수 있습니다
  • 원인: 8000 번 포트를 이미 다른 프로그램(대개 앞서 켜 둔 같은 서버)이 쓰고 있습니다.
  • 해결: 앞서 열어 둔 명령 창을 찾아 <kbd>Ctrl</kbd>+<kbd>C</kbd> 로 끄거나 창을 닫은 뒤 다시 실행합니다. 이미 서버가 켜져 있다면 새로 켤 필요 없이 http://localhost:8000 으로 접속하면 됩니다.

4) 'python'은(는) 내부 또는 외부 명령 ... 이 아닙니다#

text
'python'은(는) 내부 또는 외부 명령, 실행할 수 있는 프로그램, 또는 배치 파일이 아닙니다.
  • 원인: Python 이 설치되지 않았거나 PATH 에 등록되지 않았습니다.
  • 해결: py --version 이 되면 py build.py --serve 로 실행합니다. 안 되면 python.org 에서 Python 3 를 설치할 때 Add python.exe to PATH 에 체크합니다.

5) 페이지를 열었더니 3D 모델 · Playground 가 동작하지 않음 (주소가 file:///...)#

  • 원인: HTML 파일을 탐색기에서 더블클릭해 열었습니다. 브라우저는 file:// 페이지에서 모델 파일 · Python 실행 환경을 불러오지 못하게 막습니다.
  • 해결: 로컬 서버를 켜고 http://localhost:8000 으로 엽니다.

6) Playground 의 ▶ 실행 버튼이 계속 회색(눌리지 않음)#

  • 원인: Python 실행 환경(Pyodide)을 아직 내려받는 중이거나, 인터넷이 막혀 내려받지 못했습니다.
  • 해결: 수십 초 기다립니다. 계속 그대로면 인터넷 연결(학교 방화벽 포함)을 확인하고 <kbd>Ctrl</kbd>+<kbd>F5</kbd> 로 새로고침합니다.

과제 / 팀 미션#

실습 과제 (객관식) — 유로와 화면 구성 점검

아래 다섯 문제를 풀고, 각 답의 근거를 한 줄씩 적어 제출합니다.

  1. 펌프 바로 앞에 오는 장치는? ① 컬럼 ② 탈기 장치 ③ 검출기 ④ 오토샘플러
  2. 시료를 유로에 넣는 모듈의 시뮬레이터 기본 모델 번호는? ① G7111B ② G7114A ③ G7116A ④ G7129A
  3. 이동상의 아세토니트릴 비율을 높이면 역상 컬럼에서 일반적으로? ① 모든 피크가 빨리 나온다 ② 모든 피크가 늦게 나온다 ③ 피크 면적이 두 배가 된다 ④ 변화 없다
  4. 실물에서만 익힐 수 있는 것은? ① 유로 순서 ② 모듈 이름 ③ 피팅 누설을 눈과 손으로 찾기 ④ 크로마토그램 읽기
  5. 마우스 오른쪽 드래그의 3D 뷰 동작은? ① 회전 ② 평행 이동 ③ 확대/축소 ④ 정보 카드 열기
정답 보기1-② 탈기 후 펌프로 들어갑니다. 2-④ G7129A 바이알 샘플러. 3-① 이동상이 덜 극성이 되어 물질이 정지상에서 더 쉽게 떨어집니다. 4-③ 누설 · 손 감각은 실물에서만 익힙니다. 5-② 왼쪽 = 회전, 휠 = 확대/축소입니다.

참고자료#

  • Agilent 1260 Infinity II LC 시스템 제품 페이지: https://www.agilent.com/en/product/liquid-chromatography/hplc-systems/analytical-hplc-systems/1260-infinity-ii-lc-system
  • Agilent 1260 Infinity II 모듈별 사용자 설명서(User Manual) — Agilent 문헌 라이브러리에서 모델 번호(G7111B · G7129A · G7116A · G7114A)로 검색: https://www.agilent.com/en/support
  • Agilent, The LC Handbook — Guide to LC Columns and Method Development (역상 크로마토그래피 · 머무름 개념): https://www.agilent.com/cs/library/primers/public/LC-Handbook-Complete-2.pdf
  • Pyodide (브라우저 Python): https://pyodide.org/
  • 이 사이트의 도구: Python Playground · 3D 뷰어 · 3D 시뮬레이터
  • 다음 차시: ch02 1260 모듈과 배관 연결 이해