미니프로젝트 첫날에는 어르신 돌봄 서비스에 필요한 AutoHealing(장애 발생 시 자동으로 복구를 시도하는 기능)과 SQLite 저장 기반을 다뤘다. 둘째 날에는 새 기능을 추가하는 것보다 팀원들의 코드를 연결하고, 장애 상황에서 의도한 복구가 실제로 이루어지는지 검증하는 작업에 집중했다.
내 담당 영역은 바이탈 데이터 저장과 조회, 장애 발생 시 재시도와 캐시 기반 복구, 복구 로그 및 지표 산출이었다. 여기에 프로필 지역 정보 연동과 보호자 화면의 가독성 개선도 진행했다.
이번 작업을 통해 개별 기능을 구현하는 것만큼이나 데이터 계약을 맞추고, 장애 상황을 재현하며, 결과를 객관적인 기록으로 남기는 과정이 중요하다는 것을 확인했다.
1. 부분 바이탈 데이터 저장과 데이터 계약 정리
첫 번째로 해결한 문제는 바이탈 수집 API와 데이터베이스 저장 함수가 서로 다른 입력 조건을 요구한다는 점이었다.
API에서는 심박수와 측정 시각만으로 요청을 받을 수 있었지만, 실제 저장 함수와 DB에서는 혈압·체온·산소포화도까지 요구하고 있었다. 이 때문에 API 검증을 통과한 요청이 저장 단계에서 실패하는 문제가 발생했다.
이를 해결하기 위해 필수 항목과 선택 항목을 구분했다.
| 심박수, 측정 시각 | 필수 입력 |
| 최고혈압, 체온, 산소포화도 | 선택 입력 |
| 누락된 선택 항목 | NULL로 저장 |
여기서 중요했던 것은 누락된 값을 임의의 정상 수치로 채우지 않는 것이었다. 측정하지 않은 값과 실제로 측정한 정상 수치는 의미가 다르기 때문이다.
또한 데이터를 저장할 수 있다는 것과 해당 데이터로 위험도를 판정할 수 있다는 것은 별개의 문제였다. 일부 바이탈만 수집되더라도 저장은 가능하지만, 위험 판정에는 별도의 입력 조건이 필요할 수 있다.
최저혈압은 초기 저장 구조에 포함했지만, 이후 팀에서 최고혈압만 사용하기로 정리하면서 최신 데이터 계약에 맞춰 제외했다.
이번 작업에서 배운 점은 API, 저장 함수, DB가 각각 동작하더라도 세 영역의 입력 조건이 일치하지 않으면 전체 흐름은 실패할 수 있다는 것이다. 기능 하나의 완성도보다 데이터가 시스템의 각 계층을 통과하는 과정에서 같은 의미를 유지하는지 확인하는 것이 중요했다.
2. 기존 데이터를 보존하는 DB 마이그레이션
데이터 구조를 변경하면서 기존 데이터베이스를 어떻게 처리할지도 함께 고민했다.
새로 생성하는 DB만 수정하면 기존 app.db에는 이전 테이블 구조가 남아 오류가 발생할 수 있다. 반대로 DB를 삭제하고 다시 생성하면 기존 측정 이력과 로그가 사라질 수 있다.
이를 해결하기 위해 이전 테이블 구조를 현재 구조로 변환하는 마이그레이션을 구현했다.
마이그레이션은 기존 데이터베이스의 구조를 변경하면서 저장된 데이터를 새로운 구조에 맞게 옮기는 작업이다. 실제 서비스에서는 데이터가 계속 누적되기 때문에, 단순히 테이블을 새로 만드는 방식만으로는 충분하지 않다.
이번 작업에서는 다음 항목을 확인했다.
-
기존 행 ID와 측정 이력 보존
-
자동 증가 번호와 조회 인덱스 유지
-
기존 DB에 대한 구조 변환
-
반복 초기화 시 정상 동작 여부
-
변환 도중 오류가 발생했을 때 롤백되는지 확인
특히 변환 도중 문제가 발생하면 변경 사항을 되돌릴 수 있도록 처리했다.
이 과정을 통해 DB 변경은 새로운 스키마를 만드는 것으로 끝나지 않는다는 점을 체감했다. 기존 데이터의 연속성과 실패 시 복구 가능성까지 고려해야 실제 운영 환경에서 사용할 수 있는 구조가 된다.
3. 프로필 지역 정보를 병원 검색 흐름에 연결
병원 정보를 검색하는 데 필요한 지역값이 프로필 DB에 없다는 요청도 처리했다.
profiles 테이블에 선택 컬럼인 area를 추가하고, 기존 DB에도 해당 컬럼이 없으면 추가하도록 구현했다. 가상 프로필의 지역 정보는 팀의 Mock 데이터와 일치시켰다.
기존에 저장된 지역 정보를 무조건 덮어쓰지 않고, 확인된 가상 프로필 중 지역값이 비어 있는 경우에만 보충했다.
또한 모니터링 과정에서 이미 조회한 프로필 정보를 재사용해 지역값을 전달하도록 연결했다. 같은 데이터를 얻기 위해 불필요한 DB 조회를 반복하지 않도록 한 것이다.
지역 정보가 없거나 프로필 조회에 실패한 경우에는 None을 유지했다. 지역 정보가 없다는 이유만으로 전체 돌봄 흐름이 중단되지 않도록 하기 위해서였다.
이 작업에서 중요했던 부분은 새로운 데이터를 추가하는 것뿐 아니라, 선택 정보가 없을 때 시스템이 어디까지 정상적으로 진행되어야 하는지 정하는 일이었다.
모든 데이터가 항상 존재한다고 가정하면 예외 상황에서 전체 기능이 쉽게 실패한다. 반대로 필수 정보와 선택 정보를 구분하면 일부 정보가 누락되더라도 나머지 기능을 유지할 수 있다.
4. 캐시 대신 Mock이 호출되던 원인 분석
둘째 날 작업 중 가장 의미 있었던 부분 중 하나는 heat + vital 장애 시연에서 예상과 다른 복구 경로가 실행된 문제를 추적한 것이었다.
문서에는 바이탈 조회에 실패하면 캐시를 사용한다고 설명되어 있었지만, 실제 실행에서는 MCP Mock이 호출되고 있었다.
원인을 확인해 보니 두 가지 문제가 연결되어 있었다.
첫째, 시뮬레이터의 요청에 scenario 값이 빠져 있었다. 시나리오별 조회에서 필요한 데이터를 찾지 못하면서 의도한 정상 조회 흐름이 제대로 만들어지지 않았다.
둘째, MCP 대체 Mock은 캐시에 저장되지 않는 구조였다. 따라서 정상 조회를 수행했다고 생각하더라도 실제 캐시가 준비되어 있지 않을 수 있었다.
문제를 해결하기 위해 요청에 scenario를 추가하고, 캐시 준비부터 장애 주입까지 이어지는 통합 시험을 구성했다.
캐시 기반 장애 복구 검증 흐름
1. Heat 측정값 전송
API를 통해 데이터 저장
2. 동일 프로필·시나리오 정상 조회
복구에 사용할 캐시 준비
3. Vital 장애 주입
조회 재시도 수행
4. 재시도 소진 후 캐시 복구
준비된 캐시가 실제로 사용되는지 검증
추가로 복구 과정에서 MCP Mock이 호출되면 시험이 실패하도록 만들어, 단순히 요청이 성공했다는 사실만으로 캐시 복구를 인정하지 않도록 했다.
대체 Mock을 자동으로 캐시에 저장하는 정책 자체는 변경하지 않았다. 문제의 원인을 해결하면서 기존 시스템의 정책까지 불필요하게 바꾸지 않으려는 방향이었다.
이번 경험에서 배운 점은 정상 응답을 받았다는 사실과 장애 복구에 필요한 상태가 준비되었다는 사실은 다르다는 것이다.
캐시 복구를 검증하려면 캐시가 실제로 존재하는지, 올바른 프로필과 시나리오에 연결되어 있는지, 장애 발생 후 그 캐시가 사용되었는지까지 확인해야 한다.
5. 장애 시험 자동화와 복구율 산출
복구 기능을 구현한 뒤에는 장애 상황별 동작을 반복해서 확인하고, 그 결과를 기록할 수 있도록 시험 실행기를 만들었다.
실제 FastAPI 앱과 임시 SQLite DB를 사용하고, 외부 MCP와 LLM은 시험용 응답으로 대체했다. 네 종류의 장애를 각각 세 번씩 실행해 총 12회의 시험을 수행했다.
| 바이탈 조회 장애 | 유효한 캐시로 복구 |
| 기기 제어 장애 | 재시도 소진 후 실패 처리 및 직접 조치 안내 |
| CCTV 분석 장애 | 영상 판단이 불가능한 상태로 처리하고 바이탈 중심으로 진행 |
| LLM 출력 장애 | 교정 재요청 후 템플릿으로 안내 |
12회 모두 사전에 정한 처리 방식대로 동작했다. 하지만 이를 전부 자동 복구 성공으로 계산하지는 않았다.
예를 들어 CCTV 분석에 실패했지만 바이탈 중심으로 흐름을 이어간 경우는 기능 저하에 해당한다. 기기 제어가 끝내 실패했다면 재시도와 안내가 정상적으로 이루어졌더라도 장애 자체가 복구된 것은 아니다.
최신 재검증 결과는 다음과 같다.
완료한 장애 시험
12건
4종 × 각 3회
캐시·템플릿 복구
6건
복구로 분류한 건수
자동 복구율
50%
6 ÷ 12 × 100
복구 성공 건 평균 시간
893ms
기술 흐름 실행시간 기준
평균 시간은 장애 처리 요청과 필요한 승인 처리 요청의 실행시간을 합산한 값이다. 캐시 준비 시간과 사람의 승인 대기시간은 포함하지 않았다.
여기서 50%라는 수치는 이번 로컬 시험 세트에서 자동 복구로 분류한 비율이다. 실제 운영 환경의 복구율이나 서비스 전체의 성능을 의미하지 않는다. 외부 네트워크와 LLM의 응답시간도 반영하지 않았기 때문이다.
이 작업을 통해 장애 대응에서는 성공과 실패를 이분법적으로만 나누기보다, 복구·기능 저하·최종 실패를 구분해 기록하는 것이 중요하다는 점을 확인했다.
6. 최신 팀 코드에 대한 회귀 검증
팀원들의 코드가 계속 병합되면서 센서 범위 검사와 /logs API도 연결됐다. 새로운 코드가 추가되면 기존에 정상 동작하던 기능이 깨지지 않았는지 다시 확인해야 했다. 이런 검증을 회귀 테스트라고 한다.
이번에는 다음 항목을 중점적으로 확인했다.
-
센서 범위를 벗어난 최신값이 정상 캐시를 덮어쓰지 않는지
-
잘못된 캐시나 Mock 응답이 복구 성공으로 잘못 처리되지 않는지
-
습도만 잘못된 경우 정상 온도까지 함께 버려지지 않는지
-
/logs API의 실행 ID 필터와 조회 건수 제한이 정상 동작하는지
-
로그가 의도한 순서대로 반환되는지
또한 Git 정보가 없는 소스 사본에서도 시험 보고서를 생성할 수 있도록 실행기를 보완했다. 특정 저장소 환경에만 의존하지 않고 결과를 재현할 수 있도록 하기 위해서였다.
CCTV 분석과 관련해서는 백엔드 대기 제한과 내부 비전 호출 제한을 구분해 보고서에 기록했다. 두 제한은 비슷해 보이지만 적용되는 계층과 의미가 다르기 때문에, 문서와 실제 코드가 같은 내용을 설명하도록 정리할 필요가 있었다.
최종 마무리 시점에 확인한 테스트 결과는 다음과 같다.
| 백엔드 테스트 | 471개 |
| MCP 테스트 | 136개 |
이는 프로젝트 전체 테스트 실행 결과이며, 모든 테스트를 내가 직접 작성한 것은 아니다. 내가 맡은 구현과 별개로 팀 전체 코드가 어느 정도 검증되었는지 확인하는 지표로 활용했다.
이번 작업을 통해 테스트 개수 자체보다도 어떤 조건을 검증했으며, 실패했을 때 무엇이 잘못되었는지 추적할 수 있는지가 중요하다는 점을 다시 느꼈다.
7. 보호자 화면의 가독성 개선
백엔드 검증과 별도로 프런트엔드 디자인 보완도 진행했다. 기존 로그인·승인·결과·로그 기능은 유지하면서 HTML과 CSS를 활용해 보호자가 정보를 더 쉽게 읽을 수 있도록 화면을 정리했다.
바이탈·실내 환경·CCTV 분석 정보를 카드 형태로 배치하고, 보호자의 판단에 불필요한 원시 도구 인자 등의 정보는 화면에서 줄였다.
직접 화면을 확인하면서 발견한 가독성 문제도 수정했다.
-
로그인 안내와 진행 상태의 글자색 및 크기 개선
-
아이디·비밀번호 라벨과 입력창의 대비 개선
-
안내 상자의 글자색 개선
-
취약도 하·중·상을 파랑·노랑·빨강으로 구분
이 과정에서 기능이 정상적으로 동작하는 것과 사용자가 내용을 쉽게 읽을 수 있는 것은 별개의 문제라는 점을 확인했다.
백엔드에서는 데이터의 정확성과 장애 대응을 고려해야 한다면, 프런트엔드에서는 그 결과를 사용자가 올바르게 이해할 수 있도록 전달해야 한다. 특히 어르신 돌봄 서비스에서는 기술적인 정보가 많더라도 보호자가 현재 상태와 필요한 조치를 빠르게 파악할 수 있어야 한다.
최신 main 기준 프런트엔드 테스트는 55개가 통과했고, 작업이 main에 반영된 것도 확인했다.
8. 둘째 날의 회고: 구현보다 중요한 연결과 검증
이번 미니프로젝트 둘째 날에는 새로운 기능을 많이 만드는 것보다 이미 구현된 기능들이 서로 올바르게 연결되는지 확인하는 데 집중했다.
작업을 진행하면서 처음에는 비슷해 보였던 개념들이 실제로는 서로 다른 상태라는 점을 구체적으로 확인할 수 있었다.
-
데이터를 저장할 수 있는 것과 위험 판정에 사용할 수 있는 것은 다르다.
-
정상 조회를 수행한 것과 복구에 필요한 캐시가 준비된 것은 다르다.
-
장애 발생 후 요청을 처리한 것과 장애 자체를 복구한 것은 다르다.
-
테스트가 통과한 것과 실제 운영 환경에서 성능이 보장되는 것은 다르다.
-
화면에서 기능이 동작하는 것과 사용자가 정보를 쉽게 이해하는 것은 다르다.
특히 AutoHealing은 단순히 오류가 발생했을 때 재시도하는 기능이 아니었다. 어떤 오류가 발생했는지, 재시도할 수 있는지, 이전 정상값을 사용할 수 있는지, 기능이 제한된 상태로 진행할지, 사람의 직접 조치가 필요한지를 구분해야 했다.
그리고 이러한 판단을 로그와 보고서로 남겨야 나중에 같은 장애가 발생했을 때 원인을 추적하고 개선할 수 있었다.
현재 완료한 부분과 남은 부분
내가 담당한 데이터 저장·조회 보완, 캐시 복구 검증, 장애 시험 실행기와 보고서 작업은 마무리했다. 프로필 지역 정보 연동과 보호자 화면의 가독성 개선도 진행하고 팀 코드에 반영된 내용을 확인했다.
다만 이번에 확인한 결과는 로컬 시험 환경을 기준으로 한다. 실제 외부 모델의 응답, 전체 화면의 통합 흐름과 AWS 배포 환경에서의 동작은 별도로 확인해야 한다.
앞으로는 테스트가 통과했다는 결과만 확인하는 데 그치지 않고, 어떤 조건에서 성공했으며 어떤 조건에서는 실패하는지를 더 명확하게 구분하는 연습이 필요하다. 특히 부분 데이터 처리와 캐시 유효성 검증, 장애별 복구 기준을 지속해서 복습하고 싶다.
이번 둘째 날의 가장 큰 성과는 복구 기능이 있다는 사실을 확인한 데서 끝나지 않고, 어떤 장애가 발생했을 때 어떤 방식으로 처리했는지 다시 확인할 수 있도록 시험 결과와 기록을 남겼다는 것이다.
AI 에이전트 시스템을 개발할 때는 정상적인 실행 흐름을 만드는 능력뿐 아니라, 예상하지 못한 상황에서도 시스템이 어떤 판단을 내렸는지 설명하고 검증할 수 있는 능력이 중요하다는 것을 배웠다.
핵심 정리
-
데이터 계약: API, 저장 함수, DB의 입력 조건을 일치시키고 부분 바이탈 데이터를 안전하게 처리했다.
-
DB 마이그레이션: 기존 기록을 보존하면서 스키마 변경과 롤백을 검증했다.
-
AutoHealing: 캐시 준비부터 장애 주입, 재시도, 복구까지 실제 흐름을 통합 시험했다.
-
장애 검증: 12회의 장애 시험과 복구 지표 산출을 통해 복구·기능 저하·실패를 구분했다.
-
회귀 테스트: 센서 범위 검사, 로그 API와 팀 코드의 통합 상태를 확인했다.
-
사용자 경험: 보호자가 돌봄 상태를 쉽게 파악할 수 있도록 화면의 가독성을 개선했다.
'AI 오케스트레이션 캠프 > 미니프로젝트' 카테고리의 다른 글
| 3번째 미니프로젝트 1일차 회고|AutoHealing·SQLite·장애 복구 (0) | 2026.10.12 |
|---|---|
| 2번째 미니프로젝트 3일차 회고|LawPath 최종 발표와 프로젝트 마무리 (0) | 2026.09.10 |
| 2번째 미니프로젝트 2일차 회고|LawPath 통합·저장 이력·법률 검색 고도화 (1) | 2026.09.09 |
| 2번째 미니프로젝트 1일차|법률 AI Agent 기획과 팀 협업 시작 (Family 엔코아 SK 네트웍스 멀티 AI 에이전트) (0) | 2026.09.08 |
| 1번째 미니프로젝트 3일차|공공임대 청약 통합 안내 서비스 미니프로젝트 최종 발표 (Family 엔코아 SK 네트웍스 멀티 AI 에이전트) (0) | 2026.08.12 |
댓글