대시보드
서버 리소스
연결 지형도
최근 감사 이벤트
| 시각 | 주체 | 동작 | 결과 | 병원 |
|---|
병원 관리
| 연결 | 병원ID | 이름 | 구성 | 인증서 | 운영자 이메일 | 상태 |
|---|
병원 구성도
운영 시연
서버가 볼 수 있는 전부 — 봉인된 응답
수신자만 볼 수 있는 것 — 브라우저 안 복호화
분산 보관 — 민감정보 반반 저장
병원 보관 반쪽 (ShareA)
서버 보관 반쪽 (ShareB)
에이전트
| 상태 | 병원 ID | Agent ID | 보안 | 인증서 만료 | 전송 | 연결 시각 |
|---|
API 토큰
/v1/* 를 호출할 때 사용하는 Bearer 토큰. 시크릿은 발급 시 한 번만 표시됩니다.| 라벨 | ID | 범위 | 발급 | 만료 | 마지막 사용 |
|---|
사용자 관리
| 사용자 ID | 권한 | 생성일 |
|---|
내 비밀번호 변경
감사 로그
| 시각 | 릴레이 | 주체 | 동작 | 결과 | 병원 | Command |
|---|
보안 점검
| 영역 | 항목 | 상태 | 현재 값 · 문제가 되는 이유 |
|---|
알림 설정
환경 설정
온보딩
1. 병원 에이전트 등록 토큰 발급 관리자
enroll 하여 인증서를 받습니다. 목록에 없으면 먼저 병원 관리에서 등록하세요(ID 자동 부여).2. 앱 수신자 키 등록
recipientKid로 등록하면, 병원 Agent가 그 키로 응답을 봉인합니다.
키 생성은 다운로드 탭 샘플의 keygen 참조.
소속 병원을 지정하면 그 병원의 Agent만 이 키를 받아, 다른 병원 데이터가 이 앱으로 봉인되는 일이 구조적으로 불가능해집니다. 비워두면 모든 병원이 이 앱으로 봉인할 수 있습니다(권장하지 않음).
| recipientKid | 공개키(앞 16자) | 소속 병원 |
|---|
다운로드
MediBridge 설명서
1. 핵심 개념
병원 내부 Agent가 방화벽 밖으로 아웃바운드(WSS/443/mTLS) 연결만 만들고, 그 연결을 통해 명령과 응답을 주고받습니다. 병원은 인바운드 포트를 아무에게도 열지 않습니다. 외부 앱은 오직 이 중앙 플랫폼(중계서버)하고만 통신하며, 병원으로 직접 가는 경로는 존재하지 않습니다.
2. 병원 연결 절차 — 실제 작업 순서
새 병원 한 곳을 연결할 때 실제로 수행하는 순서입니다. 배지는 그 단계를 어디서 작업하는지를 뜻합니다: 콘솔이 화면, 병원 PC병원 내부 컴퓨터, 외부 앱데이터를 받아볼 우리 쪽 프로그램.
3. 비즈니스 로직은 어디에 있나 — 병원별 커스텀 개발 가이드
로직은 한 곳이 아니라 양 끝단에 나뉘며, 가운데(중계서버)는 의도적으로 로직이 없습니다. 외부 앱은 SQL을 전혀 모르고 명령 이름과 파라미터만 보냅니다. 프로시저를 실제로 호출하는 주체는 병원 내부에서 실행 중인 Agent입니다(DB 입장에선 내부망의 평범한 클라이언트 접속).
원칙: 계약은 표준, 구현은 병원별 커스텀
병원마다 DB 구조·업무 로직이 다르므로 커스텀은 프로시저 구현 안에 숨깁니다.
명령(commandType)의 이름·파라미터·응답 필드는 전 병원 공통 표준 계약으로 유지하세요.
예: GET_PAYMENT_STATUS(transactionId) → status·amount·currency 는 모든 병원에서 동일하고,
A병원 프로시저는 자체 수납 테이블을, B병원 프로시저는 차트사 뷰를 조회해도 됩니다.
이렇게 하면 외부 앱은 병원이 몇 곳이든 같은 코드로 호출하고, 병원 추가·변경 시 중계서버 배포가 전혀 필요 없습니다.
새 기능(명령) 추가 절차 — 병원 커스텀 개발 워크플로
GET_DAILY_TOTAL(date) → total·count). 응답 필드명 = 프로시저 결과 컬럼명
2. 병원측 구현병원 DBA/벤더가 프로시저 작성 (조회 전용 계정 권한). DB 직접 접근 불가 병원이면 벤더가 HTTP API로 제공(언어 자유 — Agent의 http-fhir/http-hl7 커넥터가 호출)
3. Agent 설정config.yaml procs에 GET_DAILY_TOTAL: usp_GetDailyTotal 매핑 + policy.yaml에 명령·파라미터 형식 허용 추가
4. 검증운영자앱/샘플로 명령 전송 → 복호화 결과 확인. 콘솔 감사 로그에서 SEALED 확인
5. 앱 반영외부 앱에서 새 commandType 호출 + 업무 처리. 중계서버는 변경 없음
병원 전용 특수 명령이 필요하면 그 병원 policy.yaml에만 허용하면 됩니다 — 정책이 병원별 파일이라 자연스럽게 격리됩니다. Agent 자체를 확장해야 하는 특수 케이스(신규 커넥터 타입 등)는 다운로드 탭의 병원측 구성요소 소스 코드로 직접 수정·재빌드할 수 있습니다.
4. 데이터 흐름
외부 앱 ─(REST, API 토큰)─▶ 중계서버 ─(서명된 명령, WSS 터널)─▶ 병원 Agent
│ 정책검증 · 조회 · E2E 봉인
외부 앱 ◀─(봉인된 응답, 앱만 복호화)── 중계서버 ◀───────┘ (중계는 암호문만 취급)
5. 보안 계층
6. 외부 앱 연동 (API)
① 이 콘솔의 API 토큰 탭에서 토큰을 발급합니다. ② 앱이 X25519 키쌍을 만들고 공개키를 온보딩 탭에서 등록해 recipientKid를 받습니다(자유 라벨이 아니라 등록된 키입니다 — 이 키로 응답이 봉인됩니다). ③ 아래처럼 호출합니다.
결제 상태 조회
POST https://medibridge.thebestpos.co.kr/v1/commands
Authorization: Bearer <API 토큰>
Content-Type: application/json
{
"hospitalId": "HOSPITAL-001",
"connectorId": "PAYMENT-01",
"commandType": "GET_PAYMENT_STATUS",
"parameters": { "transactionId": "TX-00001" },
"recipientKid": "recipient-01",
"egressFields": ["status","amount","currency"],
"maxRows": 1
}
egressFields·maxRows는 반출 제한입니다 — 비우면 전체(모든 필드/행)가 반환됩니다.
응답은 봉인된 봉투(SealedEnvelope)이며, 수신자 개인키를 가진 앱만 복호화합니다. 복호화 결과는
{"rows":[{...}]} 형태(모든 값 문자열)입니다. 복호화 상세는 다운로드 탭의 언어별 샘플/README 참조.
GET /v1/commands/{id} 폴링(재-POST 금지)
400/401/403본문 오류 / 토큰 무효 / 토큰 scope 밖
410지연 명령 유실 → 새 명령으로 재제출
422명령·정책 실패(종료)
429/503rate limit / Agent 미연결·포화 → Retry-After 후 재시도
Idempotency-Key 헤더(1–200자)를 실으면 같은 키의 재-POST 가
재실행 없이 첫 명령의 상태를 돌려줍니다(네트워크 단절 후 이중 실행 방지). 상세는 다운로드 탭 README.
7. 엔드포인트
8. 운영 안내
이 콘솔은 운영자 로그인 세션으로 보호됩니다. 운영자는 두 권한 등급이 있습니다: admin(사용자 추가·삭제·권한변경 가능)과 operator(로그인·조회만). 사용자 관리는 admin만 접근하며, 마지막 admin은 삭제·강등이 차단되어 콘솔 잠금이 발생하지 않습니다. 모든 사용자는 헤더의 비밀번호 버튼으로 본인 비밀번호를 변경할 수 있습니다. 외부 API 접근은 API 토큰으로 분리되어 있으며(병원·커넥터 scope 지정 가능), 토큰은 언제든 폐기할 수 있습니다. 감사 로그는 개인정보를 포함하지 않으며 해시체인으로 위변조가 탐지됩니다.
자주 묻는 질문 (Q&A)
Q.병원 방화벽이 인바운드를 전부 막고 있는데 어떻게 통신이 되나요?
방화벽이 막는 것은 정확히는 "외부에서 새로 들어오는 연결 시도"입니다. 일단 안에서 밖으로 시작된 연결은, 그 연결 위에서 양방향으로 데이터가 오가는 것을 허용합니다(스테이트풀 방화벽의 연결 추적). 전화와 같습니다 — 누가 걸었든 통화가 이어지면 양쪽 다 말할 수 있습니다.
병원 Agent가 서버로 아웃바운드 443(wss) 연결 하나를 걸고 끊지 않고 유지합니다. 서버는 병원으로 새 연결을 만드는 게 아니라, 병원이 걸어와 대기 중인 이 연결에 명령을 써넣을 뿐입니다. 그래서 인바운드 개방·포트포워딩·DDNS·VPN이 전혀 필요 없습니다. 카카오톡 수신, 원격지원 프로그램이 모두 같은 원리입니다.
Q.DB 서버는 인바운드를 폐쇄망(내부망)만 허용합니다. Agent가 어떻게 DB에 연결하나요?
Agent는 DB에 "밖에서" 접근하지 않습니다. Agent가 설치된 PC 자체가 병원 내부망의 구성원이므로, DB 입장에서 Agent의 접속은 원무과 청구 프로그램과 똑같은 내부망 클라이언트 접속입니다. DB 방화벽 규칙을 바꿀 필요가 없습니다.
즉 연결은 두 다리로 나뉩니다: ① Agent→DB (내부망, DB가 이미 허용하는 경로) ② Agent→중앙서버 (아웃바운드 443). 설치 PC의 조건은 "내부망으로 DB에 닿고, 인터넷 443이 나갈 것" 두 가지뿐입니다.
Q.고정 IP나 DDNS, 공유기 설정이 필요한가요?
전부 불필요합니다. Agent가 아웃바운드로만 연결하므로 병원이 유동 IP·NAT·CGNAT 뒤에 있어도 되고, 요구사항은 아웃바운드 HTTPS(443) 허용 하나뿐입니다. 웹 브라우저가 되는 PC면 충족입니다. 프록시 강제망·폐쇄망·WebSocket 차단망도 대응 수단이 있습니다(상세는 관리자 콘솔 FAQ).
Q.Agent가 병원 DB에서 직접 쿼리문을 실행하나요?
DB에 직접 접속하는 것은 맞지만, 임의 쿼리문은 절대 실행하지 않습니다. Agent는 사전 등록된 저장 프로시저만 호출하고, 파라미터는 바인딩 방식으로 전달합니다. 외부에서 오는 명령에는 SQL이 아예 담기지 않으므로(명령 이름+파라미터뿐) SQL 인젝션이 구조적으로 불가능하고, 중계서버가 해킹돼도 등록된 프로시저 외의 것을 시킬 수 없습니다.
Q.그 프로시저를 호출하는 주체는 어디인가요? 병원 호스트가 아닌가요?
병원 호스트가 맞습니다. 요청의 출발점(외부 앱)과 실행 주체(Agent)를 구분하면 됩니다: 외부 앱은 "결제상태 알려줘"라는 명령 이름만 보내고, 프로시저를 실제로 호출하는 것은 병원 내부망에서 실행 중인 Agent 프로세스입니다. DB 접속 정보는 병원 내부에만 있고 서버로 전송되지 않습니다 — 중계서버는 DB가 어디 있는지조차 모릅니다.
Q.이거 역터널링 아닌가요? 병원 보안팀이 우려합니다.
연결 방향은 역방향(아웃바운드)이 맞지만, ngrok·SSH -R 같은 범용 역터널과는 결정적으로 다릅니다. 일반 역터널은 임의의 바이트 스트림을 나르므로 내부 포트가 사실상 외부에 노출됩니다 — 중계지점이 뚫리면 내부 서비스(DB 포트 등)에 자유롭게 접속할 수 있어 보안팀이 우려하는 것이 정당합니다.
MediBridge 터널은 범용 통로가 아니라 서명 검증된 명령 메시지만 통과하는 채널입니다: ① 병원의 어떤 포트도 외부에서 도달 불가(TCP 수준 접속 자체가 존재하지 않음) ② 통과 가능한 것은 HSM 서명 + 병원 정책 화이트리스트를 통과한 명령뿐 ③ Agent가 병원 안에서 서명·정책을 독립 검증 ④ 돌아나가는 데이터는 지정 수신자만 열 수 있는 암호문. 분류하자면 ngrok보다 AWS IoT·클라우드 에이전트의 아웃바운드 명령 채널에 가깝습니다.
보안팀 설명 문구: "아웃바운드 443 연결 하나만 사용하며, 범용 터널이 아니라 서명 검증된 명령만 통과하는 채널입니다. 병원의 어떤 포트도 노출되지 않고, 중계서버가 침해되어도 명령 위조·데이터 열람이 암호학적으로 불가능합니다."
Q.중계서버가 해킹당하면 환자 데이터가 유출되나요?
구조적으로 불가능하게 설계했습니다. 응답은 병원 Agent가 수신자 공개키로 봉인(E2E 암호화)한 뒤 서버를 통과하므로 서버는 암호문만 봅니다. 명령은 HSM 서명이 있어야 Agent가 실행하므로 서버가 위조할 수 없습니다. 서버가 완전히 장악돼도 공격자는 ① 데이터를 읽을 수 없고 ② 가짜 명령을 만들 수 없고 ③ DB에 접속할 경로 자체가 없습니다.
Q.환자 개인정보가 중계서버에 저장되나요?
아니요. 중계서버는 암호문을 통과시킬 뿐이며, 평문 환자 데이터를 읽을 수도 저장할 수도 없습니다. 대용량(영상 등) 릴레이도 봉인된 암호문 상태로만 일시 보관 후 전달·삭제됩니다. 서버에 남는 것은 감사 로그의 메타데이터뿐입니다(명령ID·병원ID·결과코드·시각 — 환자 정보 없음).
Q.통신 구간 암호화는 어떻게 되어 있나요?
이중 암호화입니다. ① 전송 구간: TLS 1.3 (+ 병원 Agent는 mTLS 클라이언트 인증서로 신원 증명) ② 데이터 자체: HPKE(X25519 + AES-256-GCM)로 종단간 봉인. TLS는 서버에 도착하면 벗겨지지만, 봉인은 최종 수신 앱까지 유지되므로 서버 내부에서도 데이터는 여전히 암호문입니다.
Q.명령 위조나 재사용(리플레이) 공격은 어떻게 막나요?
모든 명령은 서명 서버(Ed25519, HSM 보관)가 서명하고, 병원 Agent가 병원 안에서 독립적으로 검증합니다 — 서명키는 게이트웨이에 없으므로 게이트웨이 침해로도 위조가 불가능합니다. 각 명령에는 nonce(1회용 번호)와 만료시각이 들어 있어, 가로챈 명령을 다시 보내는 리플레이도 Agent가 거부합니다.
Q.API 토큰이 유출되면 어떻게 되나요?
토큰만으로는 데이터를 열 수 없습니다 — 응답이 수신자 공개키로 봉인되므로, 복호화에는 별도의 수신자 개인키가 필요합니다. 토큰의 권한도 발급 시 지정한 병원·커넥터·수신자 범위로 제한되며 만료를 걸 수 있고, 즉시 폐기할 수 있습니다. 유출 시 피해는 "허용된 명령을 호출해 볼 수 있다"까지이고, 범위 밖 시도는 403으로 거부되면서 감사 로그와 권한 위반 알림으로 드러납니다.
Q.Agent가 설치된 병원 PC가 해킹되면요?
정직하게 말하면 이 경우는 그 병원 범위 안의 위험이 존재합니다 — 공격자가 그 PC를 장악하면 Agent의 DB 계정으로 허용된 조회를 할 수 있게 됩니다. 그래서 피해 범위를 제한하는 장치를 겹겹이 둡니다: ① DB 계정은 조회 전용(변조·삭제 불가) ② 정책 파일로 조회 범위 제한 ③ 모든 활동이 감사 로그·알림에 기록 ④ 병원별 키·인증서가 분리되어 다른 병원이나 중앙 플랫폼으로 확산 불가. PC 자체의 보안(백신·OS 패치·물리 접근 통제)은 병원의 기본 수칙으로 유지되어야 합니다 — 이는 기존 병원 업무 PC와 동일한 요구사항입니다.
Q.누가 언제 무엇을 조회했는지 추적할 수 있나요?
네. 모든 명령 제출·실행·오류·Agent 연결/끊김이 해시체인 감사 로그로 기록됩니다 — 각 기록이 이전 기록의 해시를 물고 있어 중간 수정·삭제가 체인 검증에서 즉시 탐지됩니다. 기록은 개인정보 없는 메타데이터(행위자·명령·병원·결과·시각)로만 구성됩니다.