AI 파이썬 Lab · 심화 · 1주차
심화 · 웹 배포

나만의 웹서비스 런칭

지금까지 만든 프로그램은 내 컴퓨터에서만 돌았어요. 오늘은 누구나 폰으로 접속하는 웹서비스를 만들어 인터넷에 올립니다.

오늘의 목표

오늘 배우는 것

심화 과정의 첫 수업입니다. 오늘은 화면이 있는 웹앱을 만들고, 그 앱을 인터넷에 배포해 누구나 접속할 수 있는 주소를 만드는 것까지 해봅니다.

🖥️
GOAL 1
Streamlit으로 버튼·입력창이 있는 웹앱 화면을 만든다
🤖
GOAL 2
AI를 연결해 '오늘의 운세'를 생성하는 기능을 넣는다
🌍
GOAL 3
인터넷에 배포해 폰으로 접속되는 진짜 주소를 만든다
새 도구 ①

Streamlit (스트림릿)이란?

파이썬 코드만으로 웹앱 화면을 만들 수 있게 해주는 도구예요. 버튼·입력창·제목 같은 화면 요소를 st.button(), st.title()처럼 짧은 코드 한 줄로 만들 수 있어요.

보통은
웹사이트 = 언어 3개
원래 웹사이트를 만들려면 HTML·CSS·자바스크립트를 따로 배워야 해요.
Streamlit은
파이썬 하나로
우리가 이미 아는 파이썬만으로 화면을 만들 수 있어요. 그래서 코딩을 막 배운 사람도 빠르게 웹앱을 만들 수 있어요.
📌 왜 Streamlit을 쓸까?
데이터 분석·AI 결과를 화면으로 보여주는 앱을 가장 빠르게 만들 수 있어서예요. 실제로 많은 개발자·연구자가 결과를 공유할 때 Streamlit을 씁니다.
새 개념 ②

인터넷 주소(URL)는 어떻게 생겼을까?

우리가 만든 앱을 인터넷에 올리면 주소가 하나 생겨요. 이 주소(URL)는 아무렇게나 생긴 게 아니라, 정해진 구조가 있어요. 주소만 알면 전 세계 누구나 같은 페이지를 찾아올 수 있게 하는 약속이에요.

https://weather.example.com/today
https://
프로토콜
정보를 주고받는 방식(약속). 자물쇠가 달린 안전한 통신이에요.
weather
서브도메인
큰 사이트 안의 세부 구역. 생략되기도 해요(예: www).
example
도메인 이름
사이트의 고유한 이름. 사람이 외우는 핵심 부분이에요.
.com
최상위 도메인
사이트의 종류. .com(회사) .org(단체) .app(앱) 등이 있어요.
/today
경로
그 사이트 안의 특정 페이지를 가리켜요.
📌 우리가 만들 앱 주소도 똑같은 구조예요 → my-app.streamlit.appmy-app(내 앱 이름) · streamlit(서비스) · .app(종류). 도메인 이름만 알면 전 세계 누구나 같은 페이지를 찾아올 수 있어요.
🏠 집 주소에 비유하면
인터넷 주소는 집 주소와 비슷해요. ‘서울시(종류) → ○○구(구역) → ○○동 123번지(고유 위치)’처럼, 큰 범위에서 점점 좁혀 들어가 하나의 집을 정확히 찾아내죠. 도메인도 똑같이 ‘종류 → 이름 → 세부 구역’으로 한 페이지를 정확히 가리켜요.
개념

지금까지의 프로그램 vs 웹앱

지금까지 만든 파이썬 프로그램은 터미널(검은 화면)에서 글자로만 돌아갔어요. 그리고 그 프로그램은 내 컴퓨터에서만 실행됐죠. 웹앱은 두 가지가 결정적으로 다릅니다.

1
화면(UI)이 생긴다
버튼, 입력창, 제목처럼 사람이 눈으로 보고 클릭하는 화면이 있어요. 우리는 이걸 Streamlit이라는 도구로 코드 몇 줄로 만듭니다.
2
인터넷 주소가 생긴다
내 컴퓨터를 꺼도 누구나 접속할 수 있게, 프로그램을 인터넷에 배포합니다. 그러면 https://... 주소가 생기고 폰에서도 열려요.
📌 비유: 터미널 프로그램 = 일기장, 웹앱 = 블로그
터미널 프로그램은 나만 보는 일기장이에요. 웹앱은 주소만 알면 누구나 보는 블로그예요. 오늘 우리는 일기장을 블로그로 바꾸는 셈입니다.
💡 Streamlit이 특별한 이유

보통 웹사이트를 만들려면 HTML·CSS·자바스크립트를 따로 배워야 해요. Streamlit은 파이썬 코드만으로 화면을 만들 수 있게 해줍니다. 우리가 이미 아는 파이썬으로 바로 웹앱을 만들 수 있다는 뜻이에요.

미션 1

'오늘의 운세' 웹앱 띄우기

🎯 목표: 버튼을 누르면 AI가 오늘의 운세를 한 줄 만들어주는 웹앱을, 내 컴퓨터 브라우저에 띄운다.

① Streamlit 설치하기

먼저 도구를 설치합니다. 터미널에 (venv) 표시가 있는지 확인하고 입력하세요. (설치는 한 번만 하면 돼요.)

터미널
# (venv) 표시 확인 후 설치
pip install streamlit

② AI를 부르는 준비 — API 키와 ask_ai 함수

🔑 .env 파일 만드는 법 (처음 한 번만)

1단계 — VS Code 터미널에서 수업 폴더 안에 파일 만들기

터미널
# Windows
New-Item .env

# Mac
touch .env

2단계 — .env 파일을 열고 아래 한 줄 입력 (선생님이 알려준 키 사용)

.env
OPENAI_API_KEY=여기에_선생님이_알려준_키_붙여넣기

⚠️ 키 앞뒤에 공백이나 따옴표 없이 딱 붙여서 저장하세요. .env 파일은 코드와 같은 폴더에 있어야 해요.

우리 앱은 AI에게 운세를 부탁할 거예요. 그러려면 두 가지가 필요해요.

🔑 API 키란?
AI 서비스에 "이 요청은 우리 학원에서 보낸 거예요"라고 알려주는 비밀번호 같은 출입증이에요. 이게 있어야 코드에서 AI를 부를 수 있어요. 선생님이 나눠준 키 파일 안에 들어 있고, 코드는 그 키를 .env(또는 배포 시 st.secrets)에서 자동으로 꺼내 씁니다. 키 내용을 화면·채팅·코드에 직접 적지 않아요.

그리고 AI를 부르는 짧은 함수 하나를 만들어 두면, 앞으로 계속 편하게 쓸 수 있어요. 이 함수는 한 번 만들어 두고 재사용합니다.

app.py — AI 호출 함수 (한 번만 작성)
from openai import OpenAI
client = OpenAI()   # 키는 .env / secrets에서 자동으로 불러옴

def ask_ai(prompt):
    res = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}]
    )
    return res.choices[0].message.content
💡 ask_ai가 하는 일

ask_ai("질문")이라고 쓰면, AI에게 질문을 보내고 답을 글자로 돌려줘요. 'AI 호출 3단계(준비 → 보내기 → 답 꺼내기)'를 이 함수 하나에 담아 둔 거예요. 다음부터는 ask_ai(...)만 부르면 됩니다.

③ 운세 웹앱 코드 만들기

이제 화면을 만들어요. AI 도구에 아래 프롬프트를 직접 입력해 기본 코드를 받아 보세요. 프롬프트는 ① 무엇을 만들지 ② 어떻게 동작할지 ③ 키 처리 방법 세 가지를 분명히 적는 게 핵심이에요.

💬 이렇게 입력해 보세요
Streamlit으로 '오늘의 운세' 웹앱을 만들어줘. 버튼을 누르면 운세를 한 문장 만들어서 화면에 보여줘. AI 호출은 내가 만든 ask_ai(prompt) 함수를 쓰고, API 키는 코드에 직접 쓰지 말고 .env / st.secrets에서 불러오게 해줘.

④ 핵심 구조 이해하기

코드에는 보통 이런 핵심 줄이 들어 있어요. 이 세 부분만 찾을 수 있으면 충분합니다.

app.py
import streamlit as st

# ── ① 화면 만들기 ──
st.title("🔮 오늘의 운세")

# ── ② 버튼을 누르면 실행 ──
if st.button("운세 뽑기"):
    result = ask_ai("오늘의 운세를 한 문장으로 말해줘")  # 위에서 만든 함수
    # ── ③ 결과 보여주기 ──
    st.write(result)

⑤ 앱 실행하기

코드를 app.py로 저장했다면, 이제 터미널에서 실행합니다. 실행하면 브라우저가 저절로 열려요.

터미널
streamlit run app.py

버튼을 누르면 브라우저에 이런 식으로 나와요.

▸ 브라우저 화면
🔮 오늘의 운세
[ 운세 뽑기 ]

오늘은 작은 행운이 당신을 따라다니는 날이에요.
망설이던 일에 용기를 내보세요!
📸 스크린샷 자리
터미널에서 streamlit run app.py를 실행한 직후, 브라우저에 운세 앱 화면이 처음 뜬 모습
📝 버튼을 누르기 전/누른 후 화면을 나란히 보여주면 학생이 동작을 이해하기 쉬움
⚠️ 자주 하는 실수
  • ModuleNotFoundError: streamlit이 설치 안 된 상태. 터미널 (venv) 표시 확인 후 다시 설치.
  • streamlit run이 아니라 python app.py로 실행하면 화면이 안 떠요. 꼭 streamlit run app.py.
  • 버튼을 눌러도 반응이 없으면, AI 호출 부분이 if st.button(...) 안에 들어 있는지 확인.
🔒 힌트 — 화면에 빨간 에러가 떠요 (전체 참고 코드)

에러가 계속 나면 아래 전체 구조와 비교해 보세요. (그대로 베끼기보다, 내 코드에서 빠진 부분을 찾는 용도예요.)

app.py (전체 참고)
import streamlit as st
from openai import OpenAI

client = OpenAI()   # 키는 .env / secrets에서 자동으로

def ask_ai(prompt):
    res = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}]
    )
    return res.choices[0].message.content

st.title("🔮 오늘의 운세")
if st.button("운세 뽑기"):
    st.write(ask_ai("오늘의 운세를 한 문장으로 말해줘"))

키 관련 에러: 키 설정 파일이 제대로 들어갔는지 선생님께 확인을 요청하세요. 학생이 키를 직접 입력하지 않습니다.

미션 2

나만의 앱으로 꾸미기

🎯 목표: 기본 앱에 이름 입력·이모지·색을 더해, 내 앱처럼 느껴지게 만든다.

기본 앱이 돌아간다면, 이제 내 취향을 더할 차례예요. 그런데 바로 정답을 보지 말고, 먼저 스스로 생각해 보는 것부터 시작해요.

✏️ 먼저 스스로 해보기
운세에 '이름'을 넣으려면 어떻게 할까?
지금 앱은 누구에게나 똑같은 운세를 보여줘요. 이걸 "○○님의 오늘의 운세"처럼 바꾸고 싶어요.
① 사용자에게 이름을 어떻게 입력받을지 생각해 보세요. ② 그 이름을 AI에게 보내는 요청에 어떻게 끼워 넣을지 생각해 보세요.
떠올랐다면, 바로 코드를 받지 말고 내가 직접 AI에게 요청할 프롬프트를 한 문장으로 적어 보세요.

스스로 프롬프트를 적어봤다면, 아래 예시와 비교해 보세요. 똑같지 않아도 괜찮아요 — 내 방식대로 요청해도 됩니다.

🔒 내가 적은 프롬프트와 비교해보기 (예시)
💬 이렇게 입력해 보세요
운세 앱에 이름 입력창을 추가해줘. 입력한 이름을 넣어서 "○○님의 오늘의 운세"처럼 보여줘.

이 정도로 요청하면 충분해요. 핵심은 "이름을 입력받아 → 운세 요청에 넣는다"는 흐름을 내가 먼저 떠올리는 거예요.

더 꾸미고 싶다면 — Streamlit 위젯

화면에 넣을 수 있는 요소를 위젯(widget)이라고 불러요. 아래 위젯들을 AI에게 "추가해줘"라고 요청하면 화면이 풍성해져요. 어떤 위젯이 있는지 알아두면, 무엇을 요청할지 스스로 정할 수 있어요.

st.text_input글자를 입력받는 입력창
st.selectbox여러 개 중 하나를 고르는 선택 메뉴
st.success결과를 초록 강조 박스로 보여주기
st.balloons축하 풍선 효과 🎈
▸ 브라우저 화면(예시)
이름을 입력하세요: [ 지민 ]
운세 주제: [ 공부 ▾ ]
[ 운세 뽑기 ]

✅ 지민님의 공부 운세
오늘 집중력이 평소보다 좋아요. 어려운 문제부터 도전!
⚠️ 자주 하는 실수
  • 입력한 이름이 운세에 안 들어가요 → 입력창 값을 변수에 담아 AI 요청 문장 안에 넣어야 해요.
  • 기능을 추가했더니 기존 게 사라졌어요 → "기존 기능은 그대로 두고 ~를 추가해줘"라고 요청하세요.
  • st.balloons()if 밖에 두면 버튼을 안 눌러도 풍선이 떠요.
🔒 힌트 — 이름이 운세에 안 들어가요 (참고 코드)

입력창의 값을 변수에 담아, AI에게 보내는 요청 문장 안에 그 변수를 끼워 넣어야 해요.

app.py (참고)
name = st.text_input("이름을 입력하세요")
if st.button("운세 뽑기"):
    # 이름을 프롬프트에 직접 끼워 넣기
    st.write(ask_ai(f"{name}님을 위한 오늘의 운세를 한 문장으로"))
미션 3

배포해서 폰으로 접속하기

🎯 목표: 내 앱을 인터넷에 올려, 폰 브라우저로 접속되는 주소(URL)를 만든다.

이제 마지막 단계예요. 내 컴퓨터에서만 돌던 앱을 Streamlit Community Cloud라는 무료 서비스에 올리면, 전 세계 어디서나 열리는 주소가 생깁니다.

배포 3단계

1
GitHub에 코드 올리기
앱 코드를 GitHub 저장소에 올립니다. (지난 과정에서 만든 GitHub 계정 사용)
2
Streamlit Cloud에 연결
Streamlit Community Cloud에서 그 저장소를 선택하면 자동으로 앱이 만들어져요.
3
키는 Secrets 칸에
배포 화면의 'Secrets' 칸에 선생님이 알려준 형식대로 키를 넣습니다. 코드에는 절대 키를 적지 않아요.
📸 스크린샷 자리
Streamlit Community Cloud의 'New app' 화면에서 GitHub 저장소를 선택하고 배포(Deploy) 버튼을 누르는 단계
📝 Repository / Branch / Main file path 입력란이 보이도록 캡처
📸 스크린샷 자리
배포 설정의 Secrets 입력 칸에 키를 넣는 화면
📝 실제 키 값은 가린 채로(●●●●) 위치와 형식만 보이게 — 키 노출 주의

배포에 꼭 필요한 파일

배포하려면 "이 앱은 어떤 라이브러리가 필요해요"를 알려주는 목록 파일이 있어야 해요. AI에게 "이 앱의 requirements.txt를 만들어줘"라고 요청하면 됩니다.

requirements.txt
streamlit
openai
📱 완성!

배포가 끝나면 https://...streamlit.app 주소가 생겨요. 이 주소를 폰으로 나에게 보내서 폰 브라우저로 직접 열어 보세요. 내가 만든 앱이 인터넷에 올라가 있는 거예요.

📸 스크린샷 자리
완성된 앱을 폰 브라우저로 접속한 화면
📝 PC 화면과 폰 화면을 나란히 두면 '같은 앱이 어디서나 열린다'는 점이 잘 전달됨

🃏 선택지 카드 — 배포 전에 무엇을 더할까?

배포하기 전, 앱에 하나만 더 추가해 봅시다. 하나를 골라 AI에게 요청해 보세요.

A
운세 점수 표시
오늘의 운세를 100점 만점 점수로도 보여주기
난이도 ★☆☆
→ "운세에 0~100 사이 행운 점수를 같이 보여줘"
B
테마 색 바꾸기
앱 전체 배경/글자 색을 내 취향으로
난이도 ★★☆
→ "앱 배경색을 파스텔 톤으로 바꿔줘"
C
럭키 아이템 추천
운세와 함께 오늘의 행운 아이템·색깔 추천
난이도 ★★☆
→ "운세에 오늘의 행운 아이템과 색을 같이 추천해줘"
D
운세 이미지 카드
결과를 캡처해서 공유할 수 있는 카드 형태로
난이도 ★★★
→ "운세 결과를 예쁜 카드 형태로 보여줘"
E
나만의 아이디어!
위에 없는 기능을 직접 떠올려 AI에게 요청해 보기
⚠️ 자주 하는 실수
  • 배포한 앱이 에러 → 대부분 requirements.txt가 빠졌거나 Secrets에 키를 안 넣어서예요.
  • GitHub에 .env 파일(키)을 올리면 절대 안 돼요 → 키는 배포 화면의 Secrets에만 넣습니다.
  • 코드를 GitHub에 다시 올렸는데 앱이 그대로면 → 잠시 기다리거나 'Reboot'을 눌러요.
🔒 힌트 — 배포한 앱에서 에러가 떠요

가장 흔한 원인 두 가지예요.

requirements.txt 누락 — AI에게 "이 앱의 requirements.txt를 만들어줘"라고 요청해 저장소에 추가.

Secrets 미설정 — 배포 설정의 Secrets 칸에 키를 넣었는지 확인. 형식은 선생님 안내를 따르세요.

보너스 미션

더 해보고 싶다면

미션 3까지 끝내고 시간이 남는다면 도전해 보세요. 끝내지 못해도 괜찮습니다.

보너스 ① 방문자 카운터 달기

앱에 접속한 사람 수를 세서 화면에 보여줍니다. "몇 명이나 내 운세를 봤을까?"를 확인할 수 있어요.

💬 이렇게 입력해 보세요
내 운세 앱에 방문자 수 카운터를 추가해줘. 버튼을 누를 때마다 숫자가 1씩 올라가게 해줘.
app.py (방문자 카운터 예시)
# 세션 안에서 숫자를 기억하기
if "count" not in st.session_state:
    st.session_state.count = 0

if st.button("운세 뽑기"):
    st.session_state.count += 1
    st.write(result)

st.caption(f"오늘 {st.session_state.count}번 뽑았어요!")

보너스 ② 친구에게 공유하고 후기 받기

완성된 주소를 친구 3명에게 보내고, 써 본 느낌을 물어보세요. "뭐가 제일 재밌었어? 뭘 더하면 좋을까?"를 물어 다음 주 개선 아이디어로 모읍니다.

🎯 성공 기준
방문자 카운터 숫자가 버튼을 누를 때마다 올라가고, 친구 1명 이상에게서 후기를 받으면 성공이에요.
정리

오늘의 핵심 정리

1️⃣
화면
Streamlit으로 파이썬만 써서 버튼·입력창이 있는 웹앱 화면을 만들었다
2️⃣
배포
코드를 인터넷에 올려, 폰으로 접속되는 진짜 주소를 만들었다
3️⃣
보안
API 키는 코드가 아니라 Secrets에 따로 보관한다는 원칙을 익혔다

🔧 막혔을 때 — 자가 디버깅 4단계

에러가 떠도 당황하지 마세요. 선생님께 묻기 전에 이 순서대로 스스로 해결해 봅니다.

1
에러 메시지 읽기
빨간 글자에서 '몇 번째 줄'과 '무슨 에러'인지 찾아본다.
2
AI에게 보여주기
에러 메시지를 복사해서 "이 에러를 수정해줘"라고 AI에게 요청한다.
3
고쳐서 다시 실행
AI가 준 수정 코드를 적용하고 다시 실행해 본다.
4
선생님께 질문
그래도 안 되면 '에러 메시지 + 내가 시도한 것'을 함께 설명한다.