한눈에
- 요양시설에서 수급자 기록·직원 근무·재고·청구·안전 호출이 따로 놀기 쉬운데, 이걸 하나의 웹 시스템으로 묶은 팀 프로젝트다. 나는 데이터베이스 설계와 백엔드(서버 로직·API) 대부분, 그리고 음성인식(STT) 서버를 맡았다.
- 31개 테이블을 정규화해 설계하고, 화면을 실제 데이터와 연결하고(API), 기록이 어긋나지 않게 하는 규칙(청구 단가 스냅샷·기간형 이력·소프트삭제)을 서버에 직접 넣었다.
- 어르신의 음성 호출(“허리가 너무 아파”)을 자동으로 글로 바꿔 기록되게, 한국어 방언까지 알아듣는 Whisper 음성인식 서버를 따로 띄워 시스템에 붙였다.
내가 맡은 범위
요양시설은 수급자 기록·직원 근태·재고·청구·안전이 제각각 흩어져 관리되기 쉽다. 이걸 하나의 웹 시스템으로 묶는 팀 프로젝트다. 도메인별로 나눠 맡았고, 나는 시스템의 데이터와 백엔드를 책임졌다.
- DB 설계 (31개 테이블) — 직원·수급자·시설/재고·모니터링 전 도메인의 테이블 구조를 직접 설계했다.
- 백엔드·API 대부분 — 위 네 도메인의 서버 로직과, 화면을 실제 데이터베이스에 연결하는 API.
- 목업을 동작하는 화면으로 — 팀의 퍼블리셔가 만든 UI 목업을 실제 데이터와 연결하고, 사용 흐름과 예외 상황(엣지케이스)을 다듬고, 필요하면 그 자리에서 DB 스키마를 고쳤다. 일부 화면은 직접 만들기도 했다.
- STT 음성인식 서버 — 음성 호출을 글로 바꾸는 별도 서버.
실시간 채팅(메신저), CCTV 스트리밍, 낙상 감지 AI(YOLO), 재활 자세추정은 다른 팀원이 맡았다.
내가 내린 설계 결정
데이터가 어긋나지 않는 31개 테이블
이 시스템의 토대는 데이터베이스다. 수급자·직원·재고·청구·간호기록이 서로 얽혀 있어, 한 곳이 틀어지면 전체가 어긋난다. 그래서 31개 테이블을 정규화해 설계하고, 어긋남을 막는 규칙을 스키마에 직접 넣었다. 몇 가지 예:
- 청구 항목에 “청구 당시 단가”를 따로 저장 — 나중에 물건값이 바뀌어도 과거 청구 금액이 그대로 보존된다.
- 배정·입원·고용은 “시작~끝” 기간 표로 — 지금 상태만이 아니라 바뀐 이력이 남는다(누가 언제 어느 침상을 썼는지 추적 가능).
- 지워도 실제로 안 지우고 “삭제 표시”만 — 과거 청구·이력이 깨지지 않는다.
- 보호자는 수급자와 여러 대 여러(N:M)로 연결 — 한 보호자가 여러 어르신을, 한 어르신이 여러 보호자를 가질 수 있다.
인수인계를 보드 하나로 — 디지털 게시판
요양시설은 3교대라 인수인계·공지가 말로만 오가면 흩어지기 쉽다. 그래서 종이나 말 대신 모두가 같이 보는 디지털 게시판에 포스트잇으로 남기게 했다. 누가 올렸고(작성자) 누가 처리했는지(처리자)를 따로 기록하고, 완료된 메모는 일정 시간(72시간) 뒤 목록에서 자동으로 빠지게 해 보드가 끝없이 쌓이지 않게 했다. 급한 건 공지로 따로 강조한다.
처방과 “실제 먹은 것”을 따로
처방(의사 지시)과 실제 투약(매번 먹인 것)을 한 표에 섞으면 기록이 엉킨다. 그래서 처방은 “계획” 표, 투약은 “실제 1회” 표로 분리했다. 처방 한 건(매일 1회, 3개월)에 매일의 투약 기록이 여러 건 달려도 깔끔하게 쌓이고, 처방의 유효기간(시작~종료일)으로 “오늘 유효한 처방”만 골라 보여준다.
건강을 한눈에 — 바이탈을 모아 그래프로
혈압·맥박·체온·혈당·체중 같은 바이탈을 표로만 보면 추세를 못 본다. 그래서 서버에서 날짜별 평균을 미리 계산해 그래프 데이터로 내려주고(하루만 보면 시간별로), 화면에서 추세 그래프로 보여줬다. 측정 안 한 항목은 0이 아니라 “빈 값”으로 구분해, 그래프가 0으로 곤두박질치지 않게 했다.
청구와 납부를 따로 — 부분 납부도 깔끔하게
한 번 청구한 본인부담금을 여러 번 나눠 낼 수 있다. 그래서 청구(낼 돈)와 납부(낸 돈)를 다른 표로 분리(1:N)하고, 납부가 쌓일 때마다 누적액과 본인부담금을 비교해 미납/부분 납부/완납을 서버에서 판정했다. 청구를 지울 때는 매달린 납부 기록을 먼저 정리해 데이터가 깨지지 않게 했다.
생활실 정원을 바꾸면 침상이 알아서
생활실 정원을 바꿀 때 침상을 손으로 맞추면 실수가 난다. 그래서 정원만큼 침상이 자동 생성되고, 정원을 늘리면 침상이 추가, 줄이면 뒤 번호부터 삭제되며 번호가 1번부터 다시 정렬되게 했다. 단, 사용 중인 침상이 있으면 삭제를 거부해 배정된 어르신이 사라지지 않게 막았다. 침상의 “사용 중” 상태는 손으로 못 바꾸고 오직 배정/이동 흐름으로만 바뀐다(데이터가 실제와 어긋나지 않게).
음성 호출을 글로 — 한국어 방언 음성인식
요양시설 어르신의 음성 호출(“허리가 너무 아파”)을 직원이 일일이 받아적기 어렵다. 그래서 음성을 자동으로 글로 바꾸는 음성인식(STT) 서버를 따로 만들었다. 한국어 방언까지 알아듣도록 방언으로 미세조정한 Whisper 모델을 쓰고(이전 프로젝트 ‘늘곁에’에서 만든 모델 재활용), 정확도를 위해 잡음 제거 → 저주파 필터 → 음량 정규화로 소리를 다듬은 뒤 인식하게 했다. 긴 음성은 30초씩 겹치게 잘라 처리하고, 외부에서 접속할 수 있게 ngrok으로 공개 주소를 열었다. 자바 본체는 이 서버로 음성을 보내, 받은 글을 호출 기록에 저장한다.
갖춘 기능
내가 맡은 도메인을 정리했다. 모든 화면은 로그인한 직원만 접근할 수 있고, 핵심 데이터는 실제 DB와 연결돼 동작한다.
- 대시보드 — 흩어진 업무를 한눈에 보는 집계 위젯(미처리 호출·재고 부족·오늘의 근무자·침상 현황 등)
- 디지털 게시판 — 포스트잇으로 인수인계·공지(작성자/처리자 기록, 완료 자동 정리)
- 수급자 — 본인·보호자 등록, 입소/퇴소·생활실 배정, 처방·투약, 간호 일지, 바이탈(그래프), 외출·외박, 본인부담금 청구·수납
- 직원·근태 — 승인 기반 로그인, 출퇴근(교대 근무 반영), 근무 일정, 직원 정보·고용 이력
- 식단 — 주간 식단표 엑셀 업로드 → 요일×식사 달력
- 시설·재고 — 시설 정보, 생활실·침상(정원 자동 동기화), 소모품 재고·청구·결제
- 모니터링 — 음성·긴급 호출, 낙상 감지 결과 조회·처리 (감지 자체는 팀원 담당)
- STT 음성인식 서버 — 음성 호출을 글로 바꾸는 별도 Whisper 서버(한국어 방언)
직원 관리(좌) — 직원 목록과 기본정보·계정·근태·입사퇴사 이력 탭. 근무일정(우) — 월별 근무 편성을 주간(D)/오후(E)/야간(N)으로 한눈에.
식단(좌) — 주간 식단표 엑셀을 올리면 요일×식사 달력으로 파싱해 표시. 낙상 기록(우) — 감지 결과를 영상·시각과 함께 조회·처리(감지 자체는 팀원).
전체 기능 펼쳐 보기
대시보드
- 미처리 호출·재고 부족·신규 비품 요청·외출 수급자·오늘의 근무자(D/E/N)·최근 포스트잇·침상 현황을 실데이터로 집계
디지털 게시판
- 포스트잇 작성/처리/복구, 작성자·처리자 기록, 본인 글만 수정, 공지·우선순위·색상 구분, 완료 후 일정 시간만 목록 유지
- 개인 To-Do(미완료 우선 정렬)
수급자
- 본인·보호자 등록(보호자 N:M), 나이는 생일로 서버에서 계산
- 입소/퇴소(모든 입소기록 종료 시 침상 자동 반납), 재입소, 생활실·침상 배정 이력
- 처방(계획)과 실제 투약(1회)을 분리 기록, 유효 기간으로 현재 처방 판별
- 간호 일지(낙상·욕창·실금·섬망 등 위험지표 체크), 외출·외박 신청·관리
- 바이탈 기록 + 추세 그래프(서버 집계, 미측정은 빈 값 처리)
- 본인부담금 청구·수납(부분 납부·완납 판정, 아임포트 PG 결제, 청구 삭제 시 납부 먼저 정리)
직원·근태
- 회원가입(이름·이메일·휴대폰 형식·중복 검사) → 가입 직후 “승인 대기” 상태, 관리자 승인 전까지 로그인 불가
- 로그인 4단계 판정(미가입/미승인/비활성/정상)과 상태별 안내, 관리자 기능은 매 요청마다 권한 재확인
- 출퇴근 — 직전 근무가 끝난 뒤에만 출근 허용, 야간 근무 종료를 다음 날로 보정, 퇴근 시 자동 로그아웃
- 근무 일정 등록·수정(같은 날 중복 편성 차단), 근무 유형(주간/오후/야간)
- 직원 정보·고용 이력(퇴사·재입사 누적), 프로필 사진, 임시 비밀번호 메일 재발급(Gmail SMTP)
식단
- 주간 식단표 엑셀(.xlsx) 업로드 → Apache POI로 읽어 요일×식사 표로 파싱·표시
시설·재고
- 시설 정보 관리(관리자 전용)
- 생활실 등록 시 정원만큼 침상 자동 생성, 정원 변경 시 침상 추가·삭제·번호 재정렬, 사용 중 침상 보호
- 침상은 배정/이동 흐름으로만 점유(직접 “사용중” 변경 차단), 침상 이동(전실)
- 소모품 재고·변동 이력(트랜잭션으로 수량+이력 한 묶음), 부족 품목 청구(영수증·항목·당시 단가), 결제 승인 시 입고
- 결제는 아임포트(PG) 카드 결제 연동
모니터링
- 음성·긴급 호출 조회, 현장 확인 내용(메모) 기록으로 처리 완료 표시
- 음성 호출은 STT 텍스트와 원본 오디오를 함께 표시, 실시간 호출 수신 시 자동 전사
- 낙상 감지 결과(영상·카메라·시각) 조회·처리 (감지 AI는 팀원)
STT 음성인식 서버 (별도)
- 방언 미세조정 Whisper, 잡음 제거→저주파 필터→음량 정규화 전처리, 30초 겹침 분할, API 키 인증, ngrok 공개 주소
정직하게 — 내가 한 일
이 시스템의 코드는 AI를 페어로 구현했다. 화면의 UI 목업은 팀의 퍼블리셔가 만들었고, 나는 그 화면들을 실제 데이터베이스·API와 연결해 동작하게 만들고, 사용 흐름과 예외 상황을 다듬고, 필요할 때 DB 스키마를 고쳤다(일부 화면은 직접 만들었다). 커넥션 풀 같은 공통 모듈 일부는 이미 있는 라이브러리를 가져다 썼다.
내가 책임진 핵심은 데이터를 어떻게 구조화하고(31개 테이블), 업무 규칙을 어떻게 서버에 녹일지(재고·청구·배정·근태·처방) 정하고 연결한 것, 그리고 음성인식 서버를 만들어 시스템에 붙인 것이다. 화려한 화면보다, 기록이 어긋나지 않고 업무가 흐르게 만드는 백엔드를 맡았다.