프로젝트/EWHA 캡스톤 졸업프로젝트

[졸업프로젝트] handDoc BE ERD 및 API 설계

rngPwns 2025. 11. 23. 15:54

   본 글에서는 handDoc 서비스에서의 API 구현 과정을 정리해보겠다.
   예약 생성 → 예약 조회 → 의사 수락 → Telemed 연동까지 이어지는 전체 흐름을 기준으로 설명한다.

 

1. 로컬 개발 환경 구성

   handDoc 백엔드는 모든 팀원이 동일한 환경에서 개발할 수 있도록 Docker 기반으로 구성된다.

1) 필요 도구 설치

  • IntelliJ IDEA
  • Docker Desktop (로컬 실행 시 항상 켜둬야 함)

2) 리포지토리 클론

git clone https://github.com/handdoc/backend.git
 

3) 통합 개발 환경 (docker-compose)

   레포지토리에는 docker-compose.yml이 포함되어 있으며, MySQL, Redis 등 필요한 모든 로컬 환경을 자동으로 띄우도록 설정돼 있다.

docker-compose up -d
 

실행 후 Docker Desktop에서 모든 컨테이너가 정상적으로 올라온 것을 확인할 수 있다!

  

4) .env 설정

   팀 공용 .env 템플릿을 기준으로 로컬에서 사용할 환경변수를 생성한다.

 

 

2. 데이터베이스 연결 방식

1) 로컬 DB 연결

   로컬 개발 시 인텔리제이 Database 탭에서 docker-compose.yml에 정의된 설정대로 연결한다.

2) 배포 환경 DB

  • MongoDB Atlas (채팅/요약 로그 저장)
  • MySQL RDS (서비스 핵심 엔티티)

 

3. 브랜치 전략

  • main : 배포 브랜치
  • develop : 통합 개발 브랜치
  • 이슈 단위로 feature/{issue-name} 브랜치 생성 후 개발

GitHub 이슈 → Development → Create a branch 기능을 사용해 브랜치를 자동 생성하도록 했다.

 

 


 

이제 본격적으로 ERD와 API를 설계한 구조에 대해 설명해보려 한다.

1. ERD 설계 및 Domain 구조

   기능 구현 전, 진료 예약 과정에 필요한 엔티티 구조를 우선 정의했다.

 

   본 ERD(Entity Relationship Diagram)은 비대면 진료 서비스(handDoc) 를 구성하는 핵심 데이터 모델을 나타낸다. 

   시스템은 크게 예약, 실시간 비대면 진료, 진료 요약, 사용자 / 의사 정보, 병원 정보 다섯 영역으로 구성되어 있으며, 각각이 자연스럽게 연결되어 하나의 진료 플로우를 형성한다.

 

1. 예약(Reservation): 전체 흐름의 기준점

   Reservation 테이블은 시스템의 중심 역할을 한다. 환자가 입력한 증상, 통역 여부, 진료 날짜/시간, 담당 의사 프로필 등의 정보가 기록된다. 예약 ID는 이후 Telemed(비대면 진료)Summary(진료 요약) 로 이어지는 모든 과정의 기준이 된다.

 

주요 필드

  • 증상(symptom), 세부설명(description)
  • 통역 필요 여부(interpolation_option)
  • 진료 날짜(slot_date), 시작/종료 시간(start_time, end_time)
  • doctor_profile_id / user_id FK

 

2. 비대면 진료(Telemed): 실시간 세션 관리

   Telemed 테이블은 예약을 기반으로 생성되며, 실제로 의사와 환자가 접속해 진료를 진행하는 세션 상태를 기록한다.

 

주요 내용

  • 세션 시작/종료 시간
  • 의사/환자 입장 여부
  • 예약 ID(FK)와 연결

   진료 중 발생하는 대화 로그는 RDB가 아닌 MongoDB 의 Telemed_Chat_Log 컬렉션에 저장하여, 로그성 데이터의 특성과 확장성을 고려했다.

 

3. Summary: 진료 종료 후 생성되는 요약

   진료가 종료되면 Summary 엔티티가 생성된다.
   Telemed 또는 Reservation과 연결되어 있고, 의사가 작성한 요약 정보가 저장된다.

 

포함되는 정보

  • 증상 요약(symptom)
  • 의사 소견(impression)
  • 처방(prescription)
  • 진료실 ID(room_id)

4. 사용자 / 의사 프로필 정보

Users

   환자와 의사 모두를 포함하는 공통 사용자 테이블이다. 이메일, 이름, 로그인 타입(소셜/일반), 주민등록번호 등 기본적인 사용자 정보가 저장된다.

 

Doctor_Profile

   의사 전용 상세 프로필로 전문의 과목, 병원명, 소개글, 의사 상태 등이 포함된다. Users와 1:1 관계로 연결되어 있어, 사용자 계정을 기반으로 의사 프로필이 확장되는 형태다.

 

Doctor_Tag

   의사의 전문분야를 태그 형식으로 추가할 수 있는 구조이다.

 

5. 병원 정보(Hospital 도메인)

Hospital

   병원 개별 정보(주소, 위도/경도 등)를 저장한다.

Hospital_Hours

   병원의 요일별 운영시간을 가지고 있으며, '병원-운영시간(1:N)' 구조로 설계되어 있다.

의사 프로필은 병원명과 연결되어 있어, 같은 병원 소속 의사 여러 명이 존재할 수 있다.

전체 구조 흐름 요약

  1. 환자(Users) 가 진료를 예약 → Reservation
  2. 예약 시간에 맞춰 비대면 진료(Telemed) 세션 시작
  3. 진료 내용은 MongoDB Chat Log 에 저장
  4. 종료 후 Summary 생성
  5. 모든 과정은 병원(Hospital)의사(Doctor_Profile) 정보와 종합적으로 연결됨

 

2. API

   그 다음으로, API 구성은 다음과 같다. handDoc 서버는 기능별로 API를 모듈화해 관리한다. 각 도메인은 명확한 prefix를 가지고 있으며, 역할 단위로 구분되어 확장성과 유지보수성을 높였다.

 

Map: GET으로 지도에서 주변 병원 조회, POST로 공공데이터 병원 정보 DB 적재

Diagnosis: POST로 진료 세션 생성, POST로 수어 텍스트 저장, POST로 의사 음성(CLOVA CSR) 저장, PATCH로 진료종료, GET으로 진료 요약을 제공한다.

 

 

 

 

Auth: POST로 소셜로그인, 일반 회원가입, 일반로그인을 진행한다.

Reservation: 환자-의사 간 진료 예약을 관리하는 API이다. POST로 환자 진료 예약을 진행하고, DELETE로 예약을 취소한다. 또 GET으로 단건 예약을 조회하고 GET으로 의사 전체 예약을 조회한다. 

 

 

 

 

 

Doctor: 환자 화면에서 의사를 검색하는 API이다. GET으로 의사목록과 의사 상세 조회를 진행한다.

 

 

 

 

Telemed: 실시간 화상진료(WebRTC)와 관련된 모든 기능을 담당하는 API이다. POST로 진료실 입장을 하고 DELETE로 진료를 종료한다. POST로 환자 수어 텍스트를 전달하고 POST로 환자 음성을 STT하고 GPT에 입력해 3개후보로 나타낸다. 또 POST로 선택한 문장을 의사에게 전달한다. 그리고 GET으로 진료요약조회, 진료내역조회를 진행한다.

 

 

 

 

User: 기초 환자정보를 입력하는 API이다.

POST로 이름을 작성하고 resident-id 주민등록번호를 입력한다.

 

 

트러블슈팅 - Telemed 연동에서 발생한 문제 및 해결

Telemed 초기 구현은 다음과 같은 흐름을 사용했다.

findByUserId → 최근 예약 1건 조회

 

   하지만 실제 진료 로직은 reservationId 기반이므로 findByUserId 자체가 필요하지 않은 구조였다. 다만 기존 코드 오류 방지를 위해 <최근 예약 한 건만 가져오는 nativeQuery> 를 최소 수정으로 추가해두었다.

  이후 실제 Telemed 연동은 reservationId 기반으로 처리되므로 해당 메서드는 사용되지 않아도 무관하다.

 

7. 개발 완료 후 PR 작성

기능 구현 → 로컬 테스트 → GitHub PR 생성

레포지토리에서 PR 관리 정책을 따르고 있으며, 리뷰 후 merge 하는 구조다.