# FHIR 레코드에 검사 결과 가져오기

> 튜토리얼: CSV 및 HL7 v2 ORU^R01 형식의 검사 보고서를 LOINC 코드 및 참조 범위가 포함된 FHIR R4 Observation으로 가져오고, 매핑되지 않은 마커와 재전송된 보고서를 처리하며, 각 결과를 검사실에 추적합니다.

Source: https://developers.anpheros.com/ko/guides/import-lab-results-fhir

**이 튜토리얼에서는 CSV 파일 및 HL7 v2 ORU^R01 메시지 형식의 검사 보고서를 각각 한 번의 요청으로 환자의 HL7 FHIR R4 레코드에 가져오고, 그 결과로 얻게 되는 것들을 보여줍니다. 즉, LOINC 코드, 참조 범위 및 출처가 포함된 검사실 `Observation` 리소스입니다.** 또한 모든 검사 통합에서 발생하는 두 가지 문제, 즉 자동으로 매핑할 수 없는 마커와 두 번 전송되는 보고서도 다룹니다. 모든 과정은 무료 샌드박스에서 합성 환자를 사용하여 진행됩니다.

## 검사 결과 저장의 어려움

검사 보고서는 간단해 보입니다. 마커, 값, 단위, 참고 범위, 날짜. 하지만 실제로는 각 검사실마다 마커 이름을 다르게 사용합니다("Hemoglobina glicozilata", "HbA1c", "Glycated haemoglobin"). 소수점 표기에 쉼표나 점을 사용하고, 참고 범위를 `4,0-5,6`, `<5` 또는 `>3.5`와 같이 표기하며, 오류가 발생하면 동일한 보고서를 다시 보냅니다. 이러한 결과들을 자유 텍스트로 저장하면 시간이 지남에 따라 비교하거나, 차트로 만들거나, 다른 애플리케이션과 공유하거나, AI 모델에 자신 있게 제공할 수 없습니다.

FHIR 레코드는 각 결과를 LOINC 코드, UCUM 단위, 값, 참고 범위 및 날짜를 포함하는 `Observation`으로 저장하고, 누가 보냈는지를 `Provenance` 리소스에 기록합니다. [랩 커넥터](https://developers.anpheros.com/ko/guides/lab-connector)가 이러한 변환을 대신 수행합니다.

```
 lab report (CSV, HL7 v2, JSON)
        │  POST /v1/patients/{id}/labs/import
        ▼
 ┌──────────────────────────────────────────────┐
 │ parse rows → map marker to LOINC → parse     │
 │ value, unit, range → stable id per row       │
 └──────────────────────────────────────────────┘
        │
        ▼
 Observation (category laboratory) + Provenance (author_type import, source system, report id)
        │
        ├─► the patient's app and every app they consented to
        └─► webhooks: resource.created per Observation
```

## 시작하기 전에

[platform.anpheros.com/dashboard](https://platform.anpheros.com/dashboard/)에서 샌드박스 키(`sk_test_…`)를 발급받아야 합니다 (**샌드박스 키 받기**). 예제에서는 `curl`를 사용하며, [SDK](https://developers.anpheros.com/ko/guides/sdks)에서도 동일한 호출(`labs.importCsv`, `labs.importHl7`, `labs.importItems`)을 제공합니다.

```bash
export BASE=https://platform.anpheros.com
export KEY=sk_test_…
# Elena Ionescu, a synthetic patient with type 2 diabetes
export PID=$(curl -s "$BASE/fhir/R4/Patient?identifier=https://anpheros.com/fhir/sid/sandbox-persona|p02" \
  -H "Authorization: Bearer $KEY" | jq -r '.entry[0].resource.id')
```

## 1단계: CSV 보고서 가져오기

루마니아 실험실에서 보고서를 내보내는 방법은 다음과 같습니다. 세미콜론, 소수점 쉼표, 루마니아어 열 이름 및 `DD.MM.YYYY` 형식의 날짜가 사용됩니다. 커넥터는 루마니아어 및 영어 열 이름을 인식합니다.

```bash
cat > report.csv <<'EOF'
Analiza;Rezultat;UM;Interval de referinta;Data
Hemoglobina glicozilata (HbA1c);6,9;%;4,0-5,6;01.10.2026
Glicemie;131;mg/dL;70-100;01.10.2026
TSH;2,1;mUI/L;0,4-4,0;01.10.2026
Marker foarte rar;12;U/L;0-20;01.10.2026
EOF

curl -X POST "$BASE/v1/patients/$PID/labs/import" -H "Authorization: Bearer $KEY" \
     -H "Content-Type: text/csv" -H "X-Anpheros-Source-System: labx" \
     -H "Idempotency-Key: report-2026-10-01-elena" --data-binary @report.csv
```

응답(`201`):

```json
{"created": 4, "skipped": 0, "unmapped": ["Marker foarte rar"], "warnings": [],
 "observations": [
  {"id": "ff0bbb44-…", "marker": "Hemoglobina glicozilata (HbA1c)", "code": "4548-4", "system": "http://loinc.org", "value": 6.9, "unit": "%", "date": "2026-10-01"},
  {"id": "ebe5522f-…", "marker": "Glicemie", "code": "2345-7", "system": "http://loinc.org", "value": 131.0, "unit": "mg/dL", "date": "2026-10-01"},
  {"id": "bace44a8-…", "marker": "TSH", "code": "3016-3", "system": "http://loinc.org", "value": 2.1, "unit": "mUI/L", "date": "2026-10-01"},
  {"id": "26fd2270-…", "marker": "Marker foarte rar", "code": "marker_foarte_rar", "system": "urn:anpheros:lab-code", "value": 12.0, "unit": "U/L", "date": "2026-10-01"}]}
```

HbA1c, glucose 및 TSH는 이름에서 LOINC로 매핑되었습니다. 소수점 쉼표는 숫자로 바뀌었고, 범위는 `referenceRange`으로 바뀌었습니다. `unmapped`에서 한 행이 반환되었습니다. 실험실 자체 코드(`urn:anpheros:lab-code`) 아래에 보고서의 정확한 텍스트와 함께 여전히 저장되어 있으므로 아무것도 손실되지 않습니다.

## 2단계: 매핑되지 않은 마커 처리

일부 이름은 결정이 필요합니다. "Glicemie"(혈당)는 좋은 예입니다. LOINC에는 혈청 또는 혈장 내 포도당(`2345-7`, 실험실에서 채취한 정맥 샘플)에 대한 코드와 전혈 내 포도당(`2339-0`, 예를 들어 손가락 채혈)에 대한 코드가 있습니다. 실험실 보고서에서 "Glicemie"만 있는 경우 혈청 또는 혈장으로 매핑됩니다. "capilar", "capillary" 또는 "sânge integral"이라고 하는 이름은 전혈로 매핑됩니다.

```json
{"created": 1, "skipped": 0, "unmapped": [], "warnings": [],
 "observations": [{"id": "00480a6d-…", "marker": "Glicemie capilara", "code": "2339-0", "system": "http://loinc.org", "value": 140.0, "unit": "mg/dL", "date": "2026-10-02"}]}
```

커넥터가 인식하지 못하는 마커의 경우 코드를 조회하십시오.

```bash
curl "$BASE/v1/terminology/loinc?q=glucose" -H "Authorization: Bearer $KEY"
```

```json
{"data": [
  {"system": "http://loinc.org", "code": "2339-0", "display": "Glucose [Mass/volume] in Blood", "display_ro": "Glicemie (sânge)", "category": "laboratory", "unit": "mg/dL"},
  {"system": "http://loinc.org", "code": "2345-7", "display": "Glucose [Mass/volume] in Serum or Plasma", "display_ro": "Glicemie (ser)", "category": "laboratory", "unit": "mg/dL"}],
 "total": 2}
```

그런 다음 코드를 `LOINC` 열에 포함합니다. 보고서의 코드는 항상 이름보다 우선합니다. 해당 매핑을 자체적으로 실험실별로 유지하고 해당 실험실의 모든 보고서에 열을 추가하십시오.

```
Analiza;Rezultat;UM;Interval de referinta;Data;LOINC
Glicemie;99;mg/dL;70-100;04.10.2026;2339-0
```

"Marker foarte rar"와 같이 LOINC에서 전혀 다루지 않는 마커는 실험실의 코드 아래에 그대로 둘 수 있습니다. 환자에게 표시되고 기록에 포함됩니다. 다른 실험실 결과와 비교할 수 없습니다.

## 3단계: 동일한 보고서 두 번 보내기

실험실에서는 보고서를 다시 보냅니다. 각 행은 보고서 ID, 코드, 날짜 및 값으로 구성된 안정적인 식별자를 가지므로, 동일한 보고서를 두 번 가져오면 아무것도 생성되지 않습니다.

```json
{"created": 0, "skipped": 4, "unmapped": ["Marker foarte rar"], "warnings": [], "observations": []}
```

변경된 행(예: 수정된 값)은 새 결과로 가져와집니다. `Idempotency-Key` 헤더는 두 번째 보증을 추가합니다. 동일한 키로 네트워크 재시도를 하면 첫 번째 응답이 변경되지 않고 반환됩니다.

## 4단계: HL7 v2 ORU^R01 메시지 가져오기

대부분의 실험실 정보 시스템은 HL7 v2를 사용합니다. 메시지를 그대로 (ER7 텍스트, CR 또는 LF로 구분된 세그먼트) 전송하십시오.

```
MSH|^~\&|LABX|LAB1|ANPHEROS|EHR|202610010930||ORU^R01|MSG00077|P|2.5.1
PID|1||12345||Ionescu^Elena||19850903|F
OBR|1||R-77|24331-1^Lipid panel^LN|||202610010800
OBX|1|NM|2093-3^Cholesterol [Mass/volume] in Serum or Plasma^LN||212|mg/dL|<200|H|||F|||202610010800
OBX|2|NM|2085-9^HDL Cholesterol^LN||52|mg/dL|>40|N|||F|||202610010800
```

```bash
curl -X POST "$BASE/v1/patients/$PID/labs/import" -H "Authorization: Bearer $KEY" \
     -H "Content-Type: x-application/hl7-v2+er7" --data-binary @oru.hl7
```

```json
{"created": 2, "skipped": 0, "unmapped": [], "warnings": [],
 "observations": [
  {"id": "b562045b-…", "marker": "Cholesterol [Mass/volume] in Serum or Plasma", "code": "2093-3", "system": "http://loinc.org", "value": 212.0, "unit": "mg/dL", "date": "2026-10-01T08:00:00Z"},
  {"id": "9b3274e4-…", "marker": "HDL Cholesterol", "code": "2085-9", "system": "http://loinc.org", "value": 52.0, "unit": "mg/dL", "date": "2026-10-01T08:00:00Z"}]}
```

`OBX-3`은 `LN` 코딩 시스템과 함께 LOINC로 직접 사용됩니다. `OBX-7`는 참조 범위를, `OBX-8`(`H`, `N`)는 해석을 나타냅니다. `OBR-3`(`R-77`)은 provenance의 보고서 ID로 유지됩니다. 환자는 URL에 있는 환자입니다. `PID` 세그먼트는 환자를 찾는 데 사용되지 않으므로 잘못된 `PID`은 다른 사람에게 결과를 첨부할 수 없습니다.

이미 파싱된 결과가 있습니까? JSON을 전송하십시오: `{"date": "2026-10-01", "origin": "report-77", "items": [{"marker": "Ferritin", "value": 38, "unit": "ng/mL", "ref_low": 15, "ref_high": 150}]}`. Ferritin은 LOINC `2276-4`에 매핑됩니다.

## 5단계: FHIR 형식으로 결과 읽기

```bash
curl "$BASE/fhir/R4/Observation?patient=$PID&code=http://loinc.org|4548-4&_sort=-date&_count=1" \
     -H "Authorization: Bearer $KEY"
```

가져온 HbA1c 저장 방식:

```json
{
  "resourceType": "Observation",
  "id": "62b1b0c0-…",
  "meta": {"versionId": "1", "lastUpdated": "2026-10-12T20:05:57.011Z"},
  "identifier": [{"system": "urn:anpheros:lab-import", "value": "c52d3cd6449291d34f6bef1516d0ac05"}],
  "status": "final",
  "category": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/observation-category", "code": "laboratory"}]}],
  "code": {"coding": [{"system": "http://loinc.org", "code": "4548-4", "display": "Hemoglobin A1c/Hemoglobin.total in Blood"}],
           "text": "Hemoglobina glicozilata (HbA1c)"},
  "subject": {"reference": "Patient/…"},
  "effectiveDateTime": "2026-10-01",
  "valueQuantity": {"value": 6.9, "unit": "%"},
  "referenceRange": [{"low": {"value": 4.0, "unit": "%"}, "high": {"value": 5.6, "unit": "%"}}]
}
```

LOINC 표시는 표준 영어 이름입니다. `code.text`는 실험실 자체 용어를 유지하므로 환자는 종이 보고서에 있던 내용을 그대로 볼 수 있습니다. 리소스 및 검색에 대한 자세한 내용은 [FHIR 플랫폼](https://developers.anpheros.com/ko/guides/fhir) 가이드 및 [FHIR 코드 시스템](https://developers.anpheros.com/ko/guides/fhir-code-systems)을 참조하십시오.

## 6단계: 발신자 확인

```bash
curl "$BASE/v1/patients/$PID/provenance/Observation/62b1b0c0-…" -H "Authorization: Bearer $KEY"
```

```json
{"data": [{"version": 1, "activity": "CREATE", "recorded": "2026-10-12T20:05:57.011000Z",
           "author_type": "import", "author": "proj_…", "source_system": "labx", "origin_id": null,
           "fhir": "Provenance/f15c4fee-…"}], "total": 1}
```

`author_type: import` 및 `source_system: labx`은 값과 함께 유지됩니다. AI 애플리케이션이 나중에 [컨텍스트 API](https://developers.anpheros.com/ko/guides/llm-healthcare-data)를 통해 이 결과를 읽을 때, 이는 `[import/labx]`로 레이블이 지정되므로 모델은 실험실 결과와 환자가 직접 입력한 값을 구별할 수 있습니다.

## 다음 단계

- 환자는 앱에서 결과를 확인합니다. 환자가 동의한 모든 애플리케이션은 해당 애플리케이션의 범위 내에서 결과를 읽을 수 있습니다 ([동의 및 액세스 모델](https://developers.anpheros.com/ko/guides/consent)).
- 각 Observation에 대해 `resource.created` [웹훅](https://developers.anpheros.com/ko/guides/webhooks)이 발생하므로, 클리닉 대시보드 또는 AI 요약이 폴링 없이 업데이트될 수 있습니다.
- `POST /fhir/R4/Observation/$validate?profile=eu-lab`는 결과가 HL7 Europe 실험실 보고서 프로필에 어떻게 부합하는지 보고합니다.
- 요청당 최대 500개 행; 제한 사항은 [제한 및 속도 제한](https://developers.anpheros.com/ko/guides/limits)에 나열되어 있습니다.

## 자주 묻는 질문

### FHIR로 어떤 검사 보고서 형식을 가져올 수 있나요?
헤더 행이 있는 CSV (쉼표, 세미콜론 또는 탭, 소수점 쉼표 허용), HL7 v2 ORU^R01 메시지 및 JSON입니다. PDF 보고서는 문서로 저장할 수 있으며, 거기서 추출된 값은 해당 문서로 다시 연결됩니다.

### LOINC 코드가 없는 마커는 어떻게 되나요?
실험실 자체 코드 아래에 보고서의 정확한 텍스트와 함께 저장되며 `unmapped`에 나열됩니다. 해당 실험실에 대한 LOINC 열을 추가하면 매핑됩니다. 보고서의 코드는 항상 이름보다 우선합니다.

### 보고서를 다시 보내도 안전한가요?
예. 각 행은 보고서, 코드, 날짜 및 값으로 구성된 안정적인 식별자를 가지므로 이미 가져온 행은 건너뛰고, 변경된 행은 새 결과로 가져옵니다.

### 실험실에서 모든 환자의 결과를 가져올 수 있나요?
아니요. 실험실은 자신이 생성한 프로젝트의 환자에게 가져오거나, OAuth를 통해 해당 사람과 공유한 기록이 있는 환자에게 가져옵니다. 다른 환자는 해당 실험실에 존재하지 않습니다 (`404`).

## 관련 정보

- [Laboratory results API](https://developers.anpheros.com/ko/guides/lab-results-api): HL7 v2와 FHIR 비교, 결과에 포함되어야 하는 항목
- [Lab connector](https://developers.anpheros.com/ko/guides/lab-connector): 모든 컬럼 이름, HL7 필드 및 응답 필드
- [Healthcare data interoperability](https://developers.anpheros.com/ko/guides/interoperability): 코드와 출처가 교환된 데이터를 유용하게 만드는 이유
- [Healthcare integrations](https://developers.anpheros.com/ko/guides/healthcare-integrations): 클리닉, 실험실, 기기 및 타사 앱
- [Medical data API](https://developers.anpheros.com/ko/guides/medical-data-api): 단일 관찰, 상태 및 약물 작성
- [FHIR 백엔드를 사용한 AI 헬스케어 앱 구축 방법](https://developers.anpheros.com/ko/guides/build-ai-healthcare-app): AI 답변에 이러한 결과 활용
