안녕하세요, 저희는 하스피챗(Hospital Chat) 서비스를 개발한 10조 “참십조”입니다. 하스피챗은 한국어 의사소통이 어려운 외국인 여행자, 체류자, 이민자 등을 대상으로 하며, 증상 번역 및 AI 기반 병원 추천 서비스를 제공할 수 있습니다. 2009년 이후 지금까지, 국내에서 진료를 받는 외국인 환자 수는 꾸준히 증가하고 있으며, 특히 21년의 경우 지난 해에 비해 약 24% 증가한 14만 6천여명이 국내에서 진료를 받은 것으로 나타나고 있습니다. 저희 서비스는 영어, 중국어, 베트남어, 태국어, 일본어 등 입국자 비율 상위 7개 국가의 언어를 지원하고 있으며, 전체 입국자의 약 70%가 서비스 대상자가 될 수 있습니다.
서비스 시연 영상 저희 서비스에 접근하시면, 처음으로 Welcome 메시지를 보실 수 있습니다. 웰컴 페이지에서는 저희 사버스가 지원 가능한 언어를 소개하고 있으며, 서비스 사용자는 로그인, 회원가입을 수행할 수 있습니다. 로그인 또는 회원가입이 강제되는 것은 아니며, 회원가입을 통해 별도 정보를 수집, 긴급 서비스를 제공하기 위한 용도입니다.회원가입 페이지에서는 다음과 같은 정보를 수집합니다. 사용자의 닉네임, 패스워드, 이름, 전화번호, 생년월일, 성별, 보험유무 등입니다. 수집하는 정보는 재한 외국인이 국내 진료를 받기 위해 필요한 진료기록부 기입 양식 일부이며, 추천 대상 병원, 의료전문가, 또는 서비스 카운셀러의 존재를 가정하여 이들에게 즉각, 정확히 전달될 수 있도록 하기 위해 수집하고 있습니다. 다음 페이지에서는 서비스 사용자가 사용가능한 언어를 선택하도록 하고 있습니다. 저는 일본어를 선택해보겠습니다.서비스 사용자는 자신의 증상을 30자 이상, 500자 미만의 문장으로 서술할 수 있습니다. 샘플을 입력해보겠습니다.이제 검색 조건을 선택하실 수 있습니다. 위의 세 카테고리는 왼쪽부터 1. 약국만 검색, 2. 병원 검색, 3. 응급실 검색 옵션입니다. 아래의 두 카테고리는 왼쪽부터 1. 근거리 우선 검색, 2. 사용자 언어 지원 가능 병원 우선 검색 옵션입니다. 저는 일본어가 지원되는 병원을 검색하므로, 다음과 같이 정의할 것 입니다. 검색 결과, 외국어 지원 가능한 병원 중 가장 가까운 거리의 병원이 제일 먼저 추천되며, 병원 이름, 번역된 문장, 주소, 진료 가능한 분과명, 지원 가능한 언어를 서비스 사용자 언어에 맞게 번역하여 반환합니다. 서비스 사용자는 이 상태에서 병원까지의 최단 경로를 보거나, AI 서버를 통해 정밀검색할 수 있습니다.
서비스 아키텍쳐 설명 및 기술 도입 배경 하스피챗은 nodejs 기반 서비스입니다. nodejs의 비동기 처리 프로세스는, 병증을 다루는 서비스에서 요구되는 신속성에 대응할 수 있는 소프트웨어 플랫폼입니다. 저희 서비스는 Socket.io 기반 채팅룸을 제공하며, 서비스 사용자가 챗봇 또는 인간 카운셀러와 상호작용하도록 함으로써 정확하고 빠른 리스폰스에 초점을 두고 개발되었습니다. / NestJs는 근래들어 가장 핫한 express 기반 플랫폼일 뿐 아니라, 보안성, 데이터 벨리데이션, 다양한 내장 모듈, 여러개의 비의존적 모듈 사이의 의존성 주입을 통한 높은 확장성 등의 강점을 가지고 있습니다. 저희 서비스는 실제 상용화 계획을 가지고 개발되었는데, nodejs의 빠른 개발속도, 비동기 처리 및 nestjs의 확장성은 스타트업 서비스를 시작할 때 최선의 선택이 될 수 있을 것이라 생각합니다. 서비스를 구성하는 각 서버는 도커 & 엔진엑스로 패키징되어 있으며, 장기적으로 쿠버네티스 인그레스를 도입, 증가하는 사용자 수요에 대응할 예정입니다. AI 서버와 Cache 서버는 파이썬 플라스크로 구현되었습니다. 파이썬은 높은 확장성과 이식성을 바탕으로 Nestjs로 구현된 다른 서버와 상호작용하기 용이할 뿐더러, 인공지능을 위한 가장 대중적인 모듈들을 지원하고 있습니다. nodejs로 pytorch등 일부 AI 개발 툴을 지원하고 있으나, 모든 서비스를 반드시 Nestjs로 구현해야 할 이유를 찾지 못했고, 필요한 모든 모듈을 제공하는 것도 아니므로 불가피하게 제외하였습니다. / 병원 정보 검색을 위해 MySQL과 조건부로 TypeORM을 사용하였습니다. 병원 정보 검색은 mysql query로 이루어지는데, 이를 통해 조금 더 빠른 리스폰스 타임을 확보하기 위함이었습니다.. 마지막으로 express 기반 서버가 사용할 수 있는 보안 모듈인 helmet을 사용, xss filter, HSTS 등을 적용하였습니다.
기술적인 도전 및 트러블 슈팅
첫째, 저희 서비스는 오리지널 비즈니스 로직 중 하나로 TF-IDF 테이블 검색 기능을 두고 있습니다. 첫 TF-IDF 테이블의 경우, 약 20만 건의 증상 및 전문의 답변 세트로 학습시킨 결과물로써, 약 29만 3천개의 단어를 포함하고 있었습니다. 이 테이블을 사용한 탐색 Accuracy는 평균 23~4%로, 기대 수준인 80% 보다 매우 낮은 수준이었습니다. 이후 테이블 검색 성능 향상을 위하여 데이터 편향성이 적은 새로운 증상 및 전문의 답변 데이터셋을 20만개 더 추가하였으며, 데이터 전처리 코드를 전반적으로 개선함으로서 약 3만여개의 단어와 그 분과별 가중치가 포함된 TF-IDF 테이블을 새로 만들 수 있었습니다. 단어의 정보 밀도가 크게 상승한 결과, 약 1만개의 새로운 데이터로 테스트 했을 때 평균 83~4%의 accuracy를 확보할 수 있었습니다.
둘째, 저희 서비스는 병원 검색시 사용자의 위치를 기준으로 가장 가까운 거리 순으로 병원 데이터를 받아오도록 하고 있습니다. 기존에는 카카오맵 API의 resource를 사용하여 근거리순 데이터 수집 및 정렬을 구현하고 있었으나, 이후 2022년 10월 기준 서울시 소재 약 6만여개의 모든 병원의 중부좌표계를 DB에 추가함으로써 저희 서비스 로직 안에서 사용자 위치로부터 추천 병원까지 거리산정이 가능해졌고, 이로서 카카오맵 API 의존도를 크게 감소시키는데 성공했습니다.
셋째, 저희 서비스는 NestJs와 SocketIO 모듈 및 HTTPS를 기반으로 채팅룸을 구현하고 있습니다. 기존에 채팅 서버가 캐시서버, 웹서버, 또는 AI 서버와 커뮤니케이션 하는 경우 SSL 인증서 first certification failed 이슈가 발생하는 고질적인 문제가 존재했습니다. 이 문제를 해결하기 위하여, 채팅 서버를 HTTPS가 적용된 NGINX로 패키징하고, 내부 컨테이너에서 HTTP로 채팅 서버를 돌림으로써 우회적으로 문제 발생 상황을 제거할 수 있었습니다. 그 결과, 저희 서버 전반에 HTTPS를 적용하는 데 성공하였습니다.
성능개선 사항
저희 서비스의 경우 배포 서버 하나, 캐시 서버 2개, 하나의 AI 서버, 병원 DB를 저장하고 있는 웹 서버가 커뮤니케이션 하고 있습니다. AI 서버 두 개를 붙여 로드밸런싱하는 대신, 보다 작은 사이즈의 캐시 서버 두개를 로드밸런싱하고 리버스 프록시 서버를 통해 AI 서버와 상호작용하도록 함으로써 정확도-속도 사이의 trade-off 관계를 만들었고, 결과적으로 첫 reponse의 accuracy 84% 이상, 최종 accuracy 95% 이상, 서버 비용 약 40% 절감 및 평균 리스폰스 타임 25% 이상 감소하는데 성공하였습니다. 차트를 보시면, 이는 동시접속자 수 100인 , 200인, 250인 기준 리스폰스 타임의 중앙값을 도표로 나타낸 것 입니다. 테스트는 14개 진료과목 각 800여개씩 총 약 1만여개의 증상 샘플을 입력했을 때, 정확한 진료과목 및 병원을 추천하는 지 측정한 것입니다. 증상은 최소 30자, 최대 500자, 평균 150자의 길이를 가지고 있습니다. 파란 색 기둥은 AI서버만 통과하는 경우, 초록색 기둥은 Cache 서버만 통과하는 경우, 노란색 기둥은 평균 리스폰스 타임을 가리키고 있습니다. 동시접속자 200인을 기준으로, AI 서버만 이용하는 경우 약 7.8초, 캐시 서버만 이용하는 경우 2.7초, 평균 5.6초 소요되었습니다.진료 과목을 확언하기 어려운 모호한 문장일수록 반응속도가 길어집니다만, 반대로 명확한 문장일 경우 캐시 서버를 탐으로써 65% 이상의 반응속도 향상을 기대할 수 있습니다.동시접속자가 250인을 넘어설 경우, 리스폰스 타임의 P95와 median 사이의 격차가 커지는 경향을 보이는데, 이는 병목현상 때문인 것으로 예상됩니다. 부하테스트 결과, 현 서비스 수준의 경우, 최악의 경우에도 동시접속자 200인을 커버할 수 있을 것으로 예상하고 있습니다.현재 증상 데이터가 평균적으로 캐시서버 통과할 확률은 약 41%입니다. 첫 추천 결과의 정확도의 경우 AI 서버는 95.8%, 캐시서버는 83.85%, 평균 90.93%를 보입니다.마지막으로, 분과별 최상위/ 최하위 정확도를 살펴보시겠습니다. 안과, 산부인과, 신경과의 경우 캐시 서버 통과율 평균 57%, 캐시서버 어큐러시 평균 95%, AI 서버 어큐러시 100%를 기록하였습니다만, 최하위를 기록한 소아청소년과, 정신건강의학과, 치과의 경우 캐시 서버 통과율 평균 36.3%, 캐시서버 어큐러시 평균 71.3%, AI 서버 어큐러시 평균 93.3%를 기록하였습니다. 어큐러시가 높을수록, 증상 데이터가 캐시서버만 경유하는 비율이 감소하는 경향을 보였는데, 이는 진료과목 등 구분이 모호한 문장일수록 캐시서버에서 탐색하기보다 AI 서버를 경유하는 비율이 증가하기 때문인 것으로 보입니다. 즉, 캐시서버는 난이도가 높은 문장은 AI 예측에 의존함으로써, 서비스 전반 어큐러시를 높이는데 기여할 수 있습니다. AI 서버는 난이도 높은 문장에 대해서도 90% 이상의 높은 어큐러시를 보장하고 있어, 서비스의 신뢰도를 보장하고 있습니다. 최종적으로, 캐시서버를 사용하는 것은 AI 서버를 두 대 사용하여 로드밸런싱 하는 것 보다 어큐러시가 크게 차이나지 않으면서, AI 서버 비용의 1/10 수준만으로도 상당한 어큐러시를 보장해주고 있으며, 리스폰스 타임을 최소 25% 이상 개선하는데 성공하였습니다.