7장. 웹 UI 연동과 배포
최종 동작 테스트: 로컬과 웹에서
식당은 문을 열기 전에 직원끼리 손님 역할을 나눠 맡아 리허설을 합니다. 주문서가 주방에 잘 가는지 확인하고, 그다음 가족을 불러 실제처럼 먹어 보게 하고, 개업 첫날에는 사장이 직접 손님 자리에 앉아 처음부터 끝까지 겪어 봅니다. 챗봇 앱도 세 겹으로 시험합니다. AppTest 로 화면의 부품을 코드로 확인하고, 내 PC 의 브라우저에서 직접 써 보고, 배포한 주소에서 처음 온 손님처럼 다시 써 봅니다.
세 상자는 왼쪽부터 빠르고 좁은 시험에서 느리고 넓은 시험으로 갑니다. 첫 상자(AppTest)는 몇 초 만에 같은 결과가 나와 고칠 때마다 돌리기 좋고, 둘째 상자(내 PC 브라우저)는 말풍선이 흘러나오는 모습과 배치를 눈으로 보고, 셋째 상자(배포 주소)는 클라우드에서 패키지와 비밀 값과 파일이 제대로 갖춰졌는지 확인합니다. 여기서 직원끼리의 리허설이 AppTest, 가족 시식이 내 PC 의 브라우저, 개업 첫날이 배포 주소입니다. 비유와 다른 점은, 앱은 코드를 고칠 때마다 세 겹을 다시 지나야 한다는 것입니다. 그래서 가장 빠른 첫 겹을 자동으로 돌게 만들어 둡니다.
세 겹의 시험에서 볼 것
| 시험 | 어떻게 | 잘 잡는 것 | 못 잡는 것 |
|---|---|---|---|
| AppTest | AppTest.from_file(…).run() 후 at.exception, at.title, at.chat_message | 오류, 빠진 부품, 기록 수, 캐시 횟수 | 배치, 흘러나오는 모습, 클라우드의 설치 문제 |
| 내 PC 브라우저 | streamlit run app.py | 화면 배치, 스트리밍, 새로 고침 뒤 기록이 사라지는 것 | 내 PC 에만 있는 파일·패키지·.env 에 기댄 것 |
| 배포 주소 | 공유 주소를 다른 브라우저나 휴대폰에서 연다 | 빠진 패키지, 빠진 파일, Secrets 누락 | (실제 손님의 다양한 질문은 써 봐야 안다) |
배포한 뒤 처음 온 손님처럼 확인할 것입니다.
짧은 예시
AppTest 는 앱이 도는 동안 난 오류를 at.exception 에 모아 둡니다. 일부러 오류를 낸 앱으로 확인합니다.
from streamlit.testing.v1 import AppTest
APP = """
import streamlit as st
st.title("구름다리여행 여행 비서")
rules = {"환불": "출발 10일 전까지 전액 환불"}
st.write(rules["예약 변경"]) # 없는 열쇠를 꺼내 KeyError 가 난다
"""
at = AppTest.from_string(APP).run()
# exception: 앱이 도는 동안 난 오류의 목록. 비어 있어야 통과다
print("오류 수:", len(at.exception))
print("오류 글:", at.exception[0].message)
print("오류 앞의 제목은 그려졌나:", at.title[0].value)오류 수: 1
오류 글: '예약 변경'
오류 앞의 제목은 그려졌나: 구름다리여행 여행 비서AppTest 는 오류가 나도 멈추지 않고 오류를 목록에 담아 돌려줍니다. 브라우저에서는 이 오류가 빨간 상자로 화면에 뜹니다. 오류가 난 줄 앞의 제목은 이미 그려졌으므로, "제목이 보인다"만으로는 앱이 멀쩡하다고 말할 수 없습니다. 그래서 점검할 때는 len(at.exception) == 0 을 함께 봅니다. 프로젝트에서 이 검사를 배포 점검표에 넣습니다.
코드가 의미하는 것
이 코드는 리허설 중에 일부러 실수를 해 보고, 점검표에 그 실수가 적히는지 보는 것입니다. 없는 열쇠를 꺼내는 앱을 돌리고 at.exception 을 꺼냅니다.
| 코드 | 하는 일 | 챗봇에서 뜻하는 것 |
|---|---|---|
rules["예약 변경"](앱 안) | 사전에 없는 열쇠를 꺼낸다 | 챗봇 앱에서 흔한 실수(빠진 설정, 없는 항목)를 대신한 줄입니다 |
len(at.exception) | 앱이 도는 동안 난 오류 수를 센다 | 배포 전 점검에서 "0 이어야 통과"로 쓰는 값입니다 |
at.exception[0].message | 오류의 글을 꺼낸다 | 무엇이 틀렸는지 알려 주는 단서입니다 |
at.title[0].value | 오류 앞의 제목을 꺼낸다 | 화면 일부가 그려졌어도 앱이 멀쩡하다는 뜻은 아님을 확인합니다 |
결과에서 읽을 것은 두 가지입니다.
- 오류가 하나 잡혔습니다. 오류 글은 없는 열쇠의 이름 '예약 변경' 입니다.
- 제목은 이미 그려졌습니다. "구름다리여행 여행 비서" 가 꺼내졌으므로, 제목만 보고 통과라고 할 수 없습니다.
주의할 점
AppTest의 한 번 실행은 기본 3초 안에 끝나야 합니다. 진짜 모델을 부르거나 큰 색인을 만들 때는at.run(timeout=60)처럼 늘립니다.AppTest는 브라우저에서만 생기는 일(스트리밍이 끊기는 모습, 화면 폭에 따라 깨지는 배치)을 보지 못합니다. 코드 시험을 통과해도 브라우저에서 한 번은 직접 써 봅니다.