프로젝트 1: 웹앱 — 완성 + 배포
지난주에 입력→처리→출력 흐름과 기획을 시작했어요. 오늘은 그 코드를 탄탄하게 다듬고 완성해서, 진짜로 인터넷에 올립니다.
오늘 배우는 것
오늘은 프로젝트 1의 마지막 시간이에요. AI 연동을 더 든든하게 다듬고, 코드 구조를 이해한 뒤, 배포까지 마치고 노션에 기록을 남깁니다.
본격 구현 3단계
지난주는 흐름이 한 번은 돌아가는 프로토타입을 만들었어요. 오늘은 여러 번 써도 안 깨지는 진짜 앱으로 다듬는 시간이에요.
st.text_area로 입력받고, ask_ai로 AI에게 일을 시키고, st.write로 결과를 보여줬죠. 오늘은 이 뼈대에 안정성과 기억 기능을 더해요.- 한 번 돌아가니까 다 됐다고 생각해요 → 빈 입력·연속 클릭도 견디는지 확인하세요.
- 코드를 전부 이해하려다 지쳐요 → 입력·처리·출력 세 칸만 잡으면 충분해요.
- 배포부터 하려고 해요 → 먼저 내 컴퓨터에서 여러 번 눌러 보고 배포하세요.
"일단 돌아가는 것"을 넘어 "여러 번 써도 안 깨지는 것"으로 성장하는 시간이에요. 모든 줄을 다 알 필요는 없어요 — 큰 구조만 내 말로 설명할 수 있으면 충분합니다.
st.session_state란?
Streamlit 앱은 버튼을 누를 때마다 코드를 처음부터 다시 실행해요. 그래서 방금 만든 결과가 자꾸 사라지는 문제가 생겨요. st.session_state는 이 결과를 기억해 두는 저장 공간이에요.
st.session_state도 화면이 새로고침돼도 그 안에 넣어둔 값은 그대로 남아 있어요.st.session_state는 노트예요. 화면이 지워져도 노트에 적어둔 값은 그대로 남아 있어서 다시 꺼내 볼 수 있어요.st.session_state는 이어보기 기능이에요. 지난번에 어디까지 봤는지 기억해서, 이전에 쌓은 결과를 잃지 않게 해줘요.st.session_state 쓰는 3단계
사물함을 쓰는 순서와 똑같아요. ① 칸이 없으면 만들고 → ② 값을 넣고 → ③ 필요할 때 꺼내요.
if "history" not in st.session_state: — 아직 사물함에 그 칸이 없을 때만 빈 목록을 만들어요.st.session_state.history.append(result) — 새 결과를 사물함 칸 안에 하나씩 쌓아 넣어요.for item in st.session_state.history: — 사물함에 쌓인 값을 하나씩 꺼내 화면에 보여줘요.- 칸을 안 만들고 바로 값을 넣어요 → 먼저
if ... not in st.session_state로 빈 칸부터 준비하세요. - 매번
= []로 덮어써요 → 그럼 이전 값이 지워져요. 쌓을 땐.append()를 쓰세요. - 값을 넣기만 하고 꺼내는
for문을 안 써요 → 화면엔 아무것도 안 보여요.
history라고 붙여 보세요. 실행할 때마다 그 칸에 답을 한 줄씩 적어 넣는 상상을 하면, 코드가 훨씬 잘 이해돼요.st.session_state는 화면이 새로고침돼도 안 지워지는 저장 공간이에요. 딱 이 한 문장만 기억하면 충분해요.
AI 연동 다듬기
지난주 앱은 AI를 한 번 부르면 딱 한 번 답이 나오는 수준이었어요. 오늘은 두 가지를 더해 여러 번 써도 든든한 앱으로 만듭니다 — 더 정확한 프롬프트와 실패해도 안 멈추는 처리.
① 프롬프트를 더 구체적으로 — system prompt 활용
지난주 배운 system prompt, 기억나시나요? "AI에게 역할을 미리 알려주는 말"이었죠. 오늘은 그 역할 설명에 출력 형식·말투·길이까지 더 구체적으로 담아봅니다.
다듬은 후: "다음 글을 정확히 세 문장으로, 존댓말로 요약해줘. 각 문장은 40자를 넘지 않게 해줘." — 결과가 훨씬 예측 가능해져요.
def ask_ai(prompt):
system_msg = (
"너는 친절한 요약 도우미야. "
"항상 세 문장, 존댓말로만 답해."
)
res = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_msg},
{"role": "user", "content": prompt}
]
)
return res.choices[0].message.contentsystem_msg = ( ... ){"role": "system", ...}{"role": "user", ...}✅ 오늘 회의는 3시에 시작합니다.
자료는 미리 공유해 주세요.
질문은 채팅으로 받겠습니다.- 규칙을 사용자 입력에 섞어 써요 → 역할은
system, 이번 내용만messages에 넣으세요. - 한 번에 10가지를 요구해요 → 형식·말투·길이 중 한두 개만 정해도 충분히 달라져요.
- "짧게"처럼 모호하게 써요 → "세 문장", "40자 이내"처럼 숫자로 적으면 결과가 안정돼요.
🔒 힌트 — AI가 규칙을 자꾸 어겨요
세 가지를 점검해 보세요.
① 규칙을 숫자로 바꿨나요? "짧게" 대신 "세 문장, 각 40자 이내"처럼.
② 규칙이 system에 들어갔나요? 사용자 입력(messages)에 섞이면 약해져요.
③ 규칙이 서로 안 부딪히나요? "한 문장" + "자세히"는 모순이라 AI가 헷갈려요.
② 실패해도 앱이 안 멈추게 — try/except
AI 서버가 잠깐 응답을 안 하거나, 입력이 이상하면 앱이 빨간 에러 화면으로 멈춰버려요. try/except는 "혹시 실패하면 이렇게 대신 보여줘"라고 미리 정해두는 안전장치예요.
try/except도 같아요. AI 호출이 실패할 확률은 낮지만, 실패했을 때 앱이 멈추지 않고 안내 문구를 보여주도록 미리 준비해 두는 거예요.if st.button("요약하기"):
try:
result = ask_ai(user_text)
st.success(result)
except Exception as e:
st.error("AI 응답에 실패했어요. 잠시 후 다시 시도해주세요.")try:except Exception as e:st.error(...)합쳐 보기 — 다듬은 미션 1 전체 코드
system prompt와 try/except를 함께 넣으면 이렇게 돼요. 두 장치가 어디에 들어가는지 확인해 보세요.
def ask_ai(prompt):
system_msg = (
"너는 친절한 요약 도우미야. "
"항상 세 문장, 존댓말로만 답해."
)
res = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role":"system","content":system_msg},
{"role":"user","content":prompt}
]
)
return res.choices[0].message.content
if st.button("요약하기"):
try:
st.success(ask_ai(user_text))
except Exception as e:
st.error("다시 시도해주세요.")[정상 응답]
✅ 요약이 완료되었습니다.
핵심 내용을 세 문장으로 정리했어요.
[빈 입력]
⚠️ 내용을 먼저 입력해 주세요.
[AI 서버 지연·실패]
⚠️ AI 응답에 실패했어요. 잠시 후 다시 시도해주세요.ask_ai 함수 안에서 AI에게 역할을 알려줘요. try/except는 그 함수를 부르는 곳을 감싸 실패에 대비해요. 역할은 안쪽, 안전벨트는 바깥쪽이에요.try/except도 같아요. AI 호출이 실패할 확률은 낮아도, 실패하는 그 순간 앱이 튕겨 나가지 않게 늘 매어두는 안전벨트예요.try안에 화면 그리는 코드까지 다 넣어요 → AI 호출처럼 실패할 부분만 감싸세요.except에서 아무 안내도 안 해요 → 사용자는 왜 멈췄는지 몰라요.st.error()로 알려주세요.- 실패해도 성공한 척 넘어가요 →
except에서return이나 안내로 확실히 끊어주세요.
🔒 힌트 — 어디까지 try로 감싸야 하나요?
기준은 하나예요 — "인터넷·외부에 기대는 줄"만 감싸요.
AI를 부르는 ask_ai(...) 한 줄이 대표적이에요. 이 줄은 서버 상태에 따라 실패할 수 있거든요.
반대로 st.text_area나 st.write처럼 화면만 그리는 줄은 감쌀 필요가 없어요.
- system prompt에 너무 많은 것을 한꺼번에 요구해요 → 형식·말투·길이 중 한두 가지부터 시작하세요.
try블록 안에 거의 모든 코드를 다 넣어요 → AI 호출처럼 실패할 수 있는 부분만 감싸세요.- 에러 메시지를 영어 그대로 보여줘요 →
st.error()로 사람이 이해할 문구를 따로 써주세요.
코드 완성하고 이해하기
이제 지난주 기획한 핵심 기능 3가지를 마저 완성할 차례예요. 그런데 AI에게 묻기 전에, 먼저 스스로 짚어봐요.
예:
st.text_area → 입력 / ask_ai → 처리 / st.session_state에 저장 후 st.write → 출력.st.session_state.history.append(result) 이 줄을 지운다면 화면이 어떻게 변할지 먼저 상상해 보세요. (힌트: 결과가 쌓이지 않고 매번 하나만 보여요.) 그다음 실제로 확인해 보면 이 줄의 역할이 확 와닿아요.코드 3덩어리 — 입력 · 처리 · 출력
코드를 다 외울 필요는 없어요. 아래처럼 세 덩어리로만 나누면 큰 구조가 한눈에 보여요.
import streamlit as st
if "history" not in st.session_state:
st.session_state.history = []
# ── ① 입력: 사용자에게 받기 ──
user_text = st.text_area("내용을 입력하세요")
# ── ② 처리: AI에게 일 시키고 기억해두기 ──
if st.button("실행"):
result = ask_ai(user_text)
st.session_state.history.append(result)
# ── ③ 출력: 쌓인 기록 모두 보여주기 ──
for item in st.session_state.history:
st.write(item)[처음 한 번 실행]
[입력] 내일 회의 일정 정리해줘
[출력] • 내일 오전 10시 회의
• 장소: 3층 회의실
[두 번째 실행 — 결과가 쌓임]
• 내일 오전 10시 회의 … ← 이전 결과
• 장소: 3층 회의실
────────────────────
• 오후 2시 자료 공유 … ← 새 결과가 아래 추가
append는 노트에 한 줄씩 이어 적는 거예요. 새로 적어도 앞 내용이 지워지지 않죠. 그래서 버튼을 여러 번 눌러도 이전 답들이 위로 차곡차곡 남아 있어요.if "history" not in st.session_state:user_text = st.text_area(...)st.session_state.history.append(result)for item in st.session_state.history:한 걸음 더 — 결과에 번호 붙이기
기록이 쌓일 때 몇 번째 결과인지 번호를 붙이면 훨씬 보기 좋아요. enumerate로 순번을 함께 꺼내요.
# ③ 출력: 번호와 함께 보여주기
for i, item in enumerate(st.session_state.history, 1):
st.write(f"#{i}번째 결과")
st.write(item)#1번째 결과
• 오늘 회의는 오후 3시 …
#2번째 결과
• 내일 오전 10시 팀 점검 …enumerate(..., 1)은 목록을 순번과 함께 하나씩 꺼내요(1부터 세라는 뜻). f"#{i}번째 결과"는 그 순번 i를 문장에 끼워 넣어요.enumerate에 , 1을 안 붙여요 → 번호가 0부터 시작해요.- 번호
i를 따로 안 써요 → 그럼 굳이enumerate를 쓸 이유가 없어요.
코드 로직 파악 활동지
아래 활동지에 내 코드 구조를 직접 정리해 봅니다.
코드가 길어 어디가 뭔지 모르겠다면, 앞서 배운 입력·처리·출력 3덩어리 구조를 다시 떠올리며 내 말로 정리해 보세요.
🔒 힌트 — 어떤 줄이 '처리'인지 헷갈려요
간단한 질문 하나면 돼요 — "이 줄이 무언가를 바꾸거나 만드나요?"
화면에서 값을 받으면 입력, 계산하거나 AI를 부르거나 저장하면 처리, 화면에 보여주면 출력이에요.
ask_ai(...)와 .append(...)는 값을 만들고 저장하니 처리, st.write는 보여주니 출력이에요.
① 입력 : user_text = st.text_area(...) → 내용을 받는 줄
② 처리 : result = ask_ai(user_text) → AI가 처리하는 줄
② 처리 : st.session_state.history.append(...) → 결과를 기억해두는 줄
③ 출력 : for item in st.session_state.history: → 쌓인 결과를 꺼내는 줄
③ 출력 : st.write(item) → 화면에 보여주는 줄- 코드가 너무 길어 어디가 뭔지 몰라요 → AI에게 3부분 분류를 요청한 뒤 내 말로 재정리.
- AI 설명을 그대로 베껴요 → 내 말로 다시 써야 진짜 내 것이 돼요.
- 모든 줄을 다 이해하려 해요 → 큰 구조(입력·처리·출력)만 잡으면 충분해요.
배포하고 노션에 정리하기
이제 마지막이에요. 1주차에 배운 방법 그대로, Streamlit Community Cloud에 올리면 폰으로 접속되는 주소가 생겨요. 기초 6주차에서 정적 HTML을 GitHub Pages에 올려본 것과는 다른 방식이라는 점, 기억해 두세요 — 이번엔 파이썬으로 만든 앱이라서 Streamlit Community Cloud를 씁니다.
배포 3단계
실제 화면으로 따라가기
아래 화면을 순서대로 따라가면 GitHub 저장소 만들기부터 Streamlit 앱 생성까지 진행할 수 있어요. 1주차에 해본 것과 같은 과정이라 낯익을 거예요.
1단계 — GitHub에 코드 올리기 (①~②)
- 저장소를 Private로 만들면 무료 배포가 안 돼요 → 반드시 Public으로 생성.
requirements.txt를 깜빡하고 코드 파일만 업로드 → 다음 단계에서 실행 중 에러가 납니다.
2단계 — Streamlit Cloud 로그인·앱 생성 (③~⑥)
- 다른 사람의 GitHub 계정으로 로그인 → 자신의 저장소가 안 보여요. 반드시 본인 계정으로.
- 로그인 창이 팝업 차단으로 안 떠요 → 브라우저의 팝업 차단 알림을 확인하고 허용하세요.
Secrets 칸은 어떻게 채우나요?
배포 화면의 Secrets 칸은 "이름 = 값" 형태로 키를 넣어요. 실제 키 값은 선생님이 알려줘요 — 아래는 형식만 보여주는 예시예요.
OPENAI_API_KEY = "여기에_선생님이_준_키"OPENAI_API_KEY라는 이름표로 키를 찾아요. 그래서 Secrets에도 똑같은 이름표로 값을 넣어야 코드가 키를 찾을 수 있어요. 이름표가 틀리면 앱은 키를 못 찾아요.- 이름표를 다르게 적어요 → 코드가 쓰는 이름과 글자까지 똑같이 맞추세요.
- 값에 따옴표를 빼먹어요 → 값은
" "안에 넣어요. - 키를 코드에도 또 적어요 → 키는 Secrets에만. 코드엔 절대 적지 마세요.
내 앱 주소 뜯어보기
배포가 끝나면 ...streamlit.app 주소가 생겨요. 주소의 각 부분이 뭘 뜻하는지 살펴봐요.
- 파이썬 앱을 GitHub Pages에 올리려 해요 → 파이썬은 안 돌아가요. Streamlit Community Cloud를 쓰세요.
- 주소를 안 저장해요 → 나중에 못 찾아요. 노션에 꼭 붙여두세요.
배포 전 체크 — requirements.txt
배포하려면 "이 앱은 어떤 라이브러리가 필요해요"를 알려주는 목록 파일이 있어야 해요. 없으면 AI에게 "이 앱의 requirements.txt를 만들어줘"라고 요청하세요.
streamlit
openaistreamlit은 화면(입력 칸·버튼·글씨)을 그리는 도구, openai는 ask_ai가 AI를 부를 때 쓰는 도구예요. 둘 중 하나라도 빠지면 그 기능에서 에러가 나요.requirements.txt는 여행 짐 목록이에요. 앱을 낯선 컴퓨터(클라우드)로 보낼 때, "이것들 꼭 챙겨줘"라고 알려주는 목록이죠. 목록에서 하나라도 빠지면 그 도구가 없어서 앱이 안 켜져요.- 파일을 아예 안 만들어요 → 배포하면 흰 화면/에러가 떠요. 꼭 저장소에 넣으세요.
- 내가 안 쓰는 라이브러리를 잔뜩 적어요 → 실제로
import한 것만 적으세요. - 파일 이름을
requirement.txt로 오타 → 정확히requirements.txt(s)여야 해요.
🃏 선택지 카드 — 배포 전 마지막 다듬기
배포하기 전, 앱을 하나만 더 다듬어 봅시다. 하나를 골라 AI에게 요청해 보세요.
🔒 힌트 — 카드 요청을 넣었더니 코드가 꼬였어요
한 번에 한 카드씩, 작게 요청하는 게 비결이에요.
① AI에게 "이 부분만 바꿔줘, 나머지는 그대로 둬"라고 못박아 말하세요.
② 바꾼 뒤 바로 실행해 확인하고, 잘 되면 다음 카드로 넘어가세요.
③ 꼬였다면 바꾸기 직전 코드로 되돌리고 다시 한 카드만 요청하세요.
배포가 끝나면 https://...streamlit.app 주소가 생겨요. 폰으로 직접 열어 보고, 친구에게도 보내 실제로 써보게 하세요. 내가 만든 서비스가 인터넷에 올라가 있는 거예요.
- 흰 화면/에러가 떠요 → 대부분
requirements.txt누락 또는 Secrets에 키를 안 넣어서예요. - GitHub에
.env(키) 파일을 올리면 절대 안 돼요 → 키는 배포 화면의 Secrets에만. - 코드를 다시 올렸는데 앱이 그대로면 → 잠시 기다리거나 'Reboot'을 눌러요.
🔒 힌트 — 배포한 앱에서 에러가 떠요
가장 흔한 원인 두 가지예요.
① requirements.txt 누락 — AI에게 "이 앱의 requirements.txt를 만들어줘"라고 요청해 저장소에 추가.
② Secrets 미설정 — 배포 설정의 Secrets 칸에 키를 넣었는지 확인. 형식은 선생님 안내를 따르세요.
📓 오늘 만든 프로젝트를 노션에 기록하기
배포까지 끝냈다면, 잊기 전에 노션에 짧게 남겨두세요. 다음 주부터는 프로젝트마다 이렇게 기록이 쌓여 나만의 포트폴리오가 됩니다.
핵심 기능: 무엇을 하는 앱인가? 오늘 완성한 기능 한두 가지.
배운 점: 오늘 새로 알게 된 것, 막혔다 푼 경험.
문제 : 긴 공지를 읽기 귀찮아서
핵심 : 글을 붙이면 3문장으로 요약
배운점: try/except로 앱이 안 멈추게 함
링크 : https://my-summary.streamlit.app- 기록을 나중에 하려다 잊어버려요 → 배포 직후 3줄만 바로 남기세요.
- 배포 링크를 안 붙여요 → 나중에 앱을 못 찾아요. 링크는 꼭 함께 저장.
- 너무 길게 쓰려다 못 써요 → 딱 세 줄이면 충분해요.
🔒 힌트 — 배운 점에 뭘 써야 할지 모르겠어요
오늘 하루를 되짚어 이 중 하나만 골라 적어 보세요.
① 막혔다 푼 순간 — 어떤 에러가 났고 어떻게 넘겼나요?
② 새로 안 것 — st.session_state, try/except 중 새로 이해한 것.
③ 다음에 고칠 점 — 시간이 더 있었다면 뭘 더 하고 싶었나요?
더 해보고 싶다면
미션 3까지 끝내고 시간이 남는다면 도전해 보세요. 끝내지 못해도 괜찮습니다.
보너스 · 가이드 페이지
앱 사용법을 접었다 펼 수 있는 안내 영역을 만들어 봅니다.
# 접었다 펼 수 있는 사용법 안내 영역
with st.expander("📖 사용법 보기"):
st.write("1. 내용을 입력하세요")
st.write("2. '실행' 버튼을 눌러요")
st.write("3. 결과가 아래에 계속 쌓여요")with st.expander("📖 사용법 보기"):st.write("1. ...")st.expander는 서랍 같아요. 평소엔 닫혀 있어 화면이 깔끔하고, 필요할 때만 열어 보죠. 사용법·자주 묻는 질문처럼 가끔만 보는 내용을 넣기 딱 좋아요. 주의: 안내 문장은 with 아래에 꼭 들여쓰기하고, 핵심 3~4줄만 넣으세요.보너스 · 기록 쌓기 + 초기화 버튼
결과가 아래로 쌓이게 만들고, 한 번에 비우는 버튼까지 더해 봅니다. 앞서 배운 st.session_state를 그대로 활용해요.
# 지금까지 쌓인 기록을 한 번에 비우기
if st.button("🧹 기록 지우기"):
st.session_state.history = []
st.success("기록을 모두 지웠어요.")if st.button("🧹 기록 지우기"):st.session_state.history = []#3 • 금요일까지 보고서 제출 …
#2 • 내일 오전 10시 팀 점검 …
#1 • 오늘 회의는 오후 3시 …✅ 기록을 모두 지웠어요. 새로 시작할 수 있어요.
아직 쌓인 요약이 없어요.🔒 힌트 — 초기화 버튼을 눌러도 안 지워져요
두 가지를 확인해 보세요.
① 지우는 대상이 같은 이름인가요? 쌓을 때 쓴 history와 지울 때 쓴 이름이 똑같아야 해요.
② = []로 빈 목록을 넣었나요? .append()가 아니라 통째로 새 빈 목록으로 바꿔야 비워져요.
오늘의 핵심 정리
try/except — 실패해도 앱이 안 멈추게 하는 안전벨트.
requirements.txt — 배포할 때 챙길 도구 목록(여행 짐 목록).
프로젝트 1(웹앱)이 끝났어요. 다음 프로젝트부터는 데이터를 저장하고 다시 불러오는 앱을 만듭니다. 오늘 배포한 앱 주소를 가족·친구에게 공유하고 사용 후기를 한 줄 받아오세요.
② 받은 후기를 노션에 한 줄씩 적어두기.
③ 다음에 고치고 싶은 점을 하나만 메모하기.
🔧 막혔을 때 — 자가 디버깅 4단계
에러가 떠도 당황하지 마세요. 선생님께 묻기 전에 이 순서대로 스스로 해결해 봅니다.
아래는 이번 주 자주 만나는 에러 세 가지와 넘기는 법이에요.
if "history" not in ...로 칸부터 만드세요.requirements.txt에 그 라이브러리를 빠뜨린 거예요.지난주 앱 vs 오늘 완성한 앱
같은 앱이 어떻게 달라졌는지 나란히 보면, 오늘 배운 것이 한눈에 정리돼요.
지난주 — 프로토타입 (한 번 돌아가는 버전)
import streamlit as st
# 입력
user_text = st.text_area("내용을 입력하세요")
# 처리
if st.button("실행"):
result = ask_ai(user_text)
# 출력
st.write(result)- 버튼을 다시 누르면 이전 결과가 사라져요.
- AI 호출이 실패하면 앱이 통째로 멈춰요.
- AI 답의 형식·길이가 들쭉날쭉해요.
오늘 — 완성 버전 (여러 번 써도 안 깨지는 버전)
import streamlit as st
if "history" not in st.session_state:
st.session_state.history = []
# 입력
user_text = st.text_area("내용을 입력하세요")
# 처리 (안전장치 + 기억)
if st.button("실행"):
try:
result = ask_ai(user_text)
st.session_state.history.append(result)
except Exception as e:
st.error("다시 시도해주세요.")
# 출력 (쌓인 기록 모두)
for item in st.session_state.history:
st.write(item)완성 버전이라고 코드가 완전히 새로운 게 아니에요. 지난주 뼈대에 세 가지 장치만 더한 거예요. 이게 "프로토타입 → 실전 앱"의 핵심이에요.
st.session_state 조금 더 깊이
오늘 쓴 history 말고도, 세션 상태는 여러 값을 기억하는 데 쓸 수 있어요. 자주 쓰는 패턴 두 가지를 소개해요.
패턴 ① 숫자 세기 (카운터)
버튼을 몇 번 눌렀는지 기억하려면 숫자를 저장해요.
if "count" not in st.session_state:
st.session_state.count = 0
if st.button("실행"):
st.session_state.count += 1
st.write(f"지금까지 {st.session_state.count}번 실행했어요")st.session_state.count = 0st.session_state.count += 1지금까지 3번 실행했어요패턴 ② 마지막 결과만 기억하기
모든 기록이 아니라 가장 최근 결과 하나만 저장하고 싶을 때도 있어요.
if st.button("실행"):
st.session_state.last = ask_ai(user_text)
if "last" in st.session_state:
st.write(st.session_state.last)append하면 전부 쌓이고, 값 하나에 그냥 넣으면 마지막 것만 남아요. 만들고 싶은 앱에 맞게 골라 쓰면 돼요.- 칸을 안 만들고 바로
+= 1해요 → 먼저= 0으로 시작하세요. - 목록인데
append대신=로 덮어써요 → 그럼 하나만 남아요. - 저장은 했는데 꺼내 쓰는 줄이 없어요 → 화면엔 아무것도 안 보여요.
🔒 힌트 — 언제 목록이고 언제 값 하나예요?
"여러 개를 쌓아 보여주고 싶다" → 목록([]) + append.
"항상 최신 하나만 보여주면 된다" → 값 하나에 그냥 저장.
"몇 번인지 세고 싶다" → 숫자에 += 1.
선택지까지 다 넣은 완성 예시
오늘 배운 것과 선택지 카드(빈 입력 처리·기록 초기화·사용 안내)를 모두 넣으면 이렇게 돼요. 참고용이니, 내 앱에 맞게 골라 쓰세요.
import streamlit as st
st.title("📝 요약 도우미")
st.info("내용을 넣고 실행을 눌러 주세요")
if "history" not in st.session_state:
st.session_state.history = []
user_text = st.text_area("내용을 입력하세요")
if st.button("실행"):
if not user_text:
st.warning("내용을 먼저 입력해 주세요")
else:
try:
result = ask_ai(user_text)
st.session_state.history.append(result)
except Exception as e:
st.error("다시 시도해주세요")
if st.button("🧹 기록 지우기"):
st.session_state.history = []
for i, item in enumerate(st.session_state.history, 1):
st.write(f"#{i}번째 결과")
st.write(item)if not user_text), 안전장치(try/except), 기억(append), 초기화(= []), 번호 붙인 출력(enumerate)이 각각 어디 있는지 짚어 보세요.- 통째로 복사만 하고 이해를 건너뛰어요 → 각 줄이 입력·처리·출력 중 어디인지 짚어 보세요.
- 내 앱과 기능이 달라 그대로 안 맞아요 → 필요한 부분만 골라 가져가세요.