Application/Python

[Python] 미니 프로젝트로 마무리 — 파이썬 날씨 앱 만들기

devsalix 2026. 6. 8. 09:08
728x90

미니 프로젝트로 마무리 — 파이썬 날씨 앱 만들기

매일 아침 휴대폰으로 날씨 한 번씩은 확인하시잖아요. 그거랑 똑같이 동작하는 걸, 오늘 직접 만들어볼 거예요.

도시 이름을 입력하면 현재 기온이랑 체감 온도, 날씨 상태를 보여주는 작은 앱이에요. 16편에서 계산기, 24편에서 학생 성적 관리를 만들어봤는데, 이번엔 인터넷에서 데이터를 받아오는 진짜 실전 프로젝트입니다.


만들 앱 미리보기

실행하면 이런 식으로 동작할 거예요.

$ python main.py
도시 이름을 영어로 입력하세요: Seoul

========================================
  Seoul 현재 날씨
========================================
  상태   : 맑음
  기온   : 18.3도
  체감   : 17.1도
  습도   : 45%
  풍속   : 2.4 m/s
========================================

 

별거 아닌 것 같지만, 이 안에 우리가 32편 동안 배운 게 거의 다 들어가요. 함수, 딕셔너리, 예외 처리, 모듈 분리, 환경변수, API 호출까지. 진짜 졸업 작품이에요.


파이썬 고급 프로젝트, 폴더 구조부터 잡고 시작합니다

31편에서 배운 구조 그대로 갑니다. 코드를 한 파일에 다 때려넣지 않고 역할별로 쪼개는 거예요.

weather_app/
├── .env
├── .gitignore
├── requirements.txt
├── main.py
└── src/
    ├── __init__.py
    ├── api.py
    └── display.py

 

"또 폴더야?" 싶으실 수 있는데요, 이게 실무에서 쓰는 모양이에요. 한 파일에 다 적어도 동작은 하지만, 나중에 코드가 길어지면 어디 뭐 있는지 본인도 못 찾거든요.


가상환경 만들고 패키지 설치하기

weather_app 폴더 안에서 터미널을 열고 이렇게 합니다.

python -m venv venv
# Windows: venv\Scripts\activate
# Mac/Linux: source venv/bin/activate
pip install requests python-dotenv
pip freeze > requirements.txt

 

requests는 29편에서 만나본 그 친구고, python-dotenv는 31편에서 배운 .env 파일을 읽어주는 도구예요.


python 날씨 API 고르기 — OpenWeatherMap 추천

이 글에서는 OpenWeatherMap을 씁니다. 무료 계정으로 분당 60회까지 호출할 수 있어서 연습용으로 차고 넘쳐요.

가입은 openweathermap.org에서 이메일로 하시고, 로그인 후 "API keys" 메뉴에서 키를 발급받으시면 돼요. 여기서 진짜 중요한 한 가지.

키 발급 직후엔 활성화까지 몇 분에서 최대 한두 시간 걸려요.

이거 모르면 "키 분명히 맞게 넣었는데 왜 401이 떠?" 하면서 한참 헤매십니다. 저도 처음에 그랬거든요. 발급받고 차 한 잔 마시고 오신다 생각하시면 편해요.

참고로 키 발급이 너무 귀찮으시면 wttr.in이라는 대안도 있어요. https://wttr.in/Seoul?format=j1로 키 없이 바로 호출됩니다. 다만 응답 구조가 좀 복잡해서, 학습용으로는 OpenWeatherMap이 깔끔해요.


.env에 키 저장하고 .gitignore 챙기기

.env 파일에 키를 적습니다.

OPENWEATHER_API_KEY=여기에_발급받은_키_붙여넣기

 

그리고 .gitignore에는 이렇게.

.env
venv/
__pycache__/

 

키를 코드에 그냥 적어놓고 깃허브에 올리는 거, 진짜 위험해요. 봇이 깃허브를 24시간 스캔하거든요. 키 올라간 지 몇 분 만에 누가 훔쳐가서 본인 한도 다 까먹는 사례, 흔합니다.


src/api.py — 날씨 데이터 가져오기

이 파일이 하는 일은 딱 하나예요. 도시 이름을 받아서 날씨 정보 딕셔너리를 돌려주는 거.

import os                                # 환경변수 읽기용
import requests                          # HTTP 요청 보내기

BASE_URL = "https://api.openweathermap.org/data/2.5/weather"

def get_weather(city: str) -> dict:
    """도시 이름을 받아 날씨 정보를 반환합니다."""
    api_key = os.getenv("OPENWEATHER_API_KEY")  # .env에서 읽은 키
    if not api_key:
        raise ValueError("API 키가 없어요. .env를 확인해주세요.")

    params = {
        "q": city,           # 도시명
        "appid": api_key,    # 인증 키
        "units": "metric",   # 섭씨로 받기 (안 넣으면 켈빈)
        "lang": "kr",        # 날씨 설명을 한국어로
    }
    response = requests.get(BASE_URL, params=params, timeout=5)
    response.raise_for_status()          # 4xx, 5xx면 예외 발생
    return response.json()               # JSON을 딕셔너리로 변환

 

units=metric을 빼먹으면 기온이 켈빈 단위로 와요. 18도가 291.45 이런 식으로 나옵니다. 처음 보면 진짜 당황스러워요.


src/display.py — 보기 좋게 출력하기

받은 데이터를 사람이 읽기 좋게 찍어주는 역할만 합니다.

def print_weather(data: dict) -> None:
    """API 응답을 화면에 보기 좋게 출력합니다."""
    city = data["name"]                          # 도시 이름
    weather = data["weather"][0]["description"]  # 날씨 설명
    temp = data["main"]["temp"]                  # 기온
    feels = data["main"]["feels_like"]           # 체감 온도
    humidity = data["main"]["humidity"]          # 습도
    wind = data["wind"]["speed"]                 # 풍속

    print()
    print("=" * 40)
    print(f"  {city} 현재 날씨")
    print("=" * 40)
    print(f"  상태   : {weather}")
    print(f"  기온   : {temp}도")
    print(f"  체감   : {feels}도")
    print(f"  습도   : {humidity}%")
    print(f"  풍속   : {wind} m/s")
    print("=" * 40)

 

data["main"]["temp"]처럼 대괄호가 두 번 들어가는 거, 처음엔 어지러우시죠. 딕셔너리 안에 또 딕셔너리가 들어 있는 구조예요. 10편에서 배운 그 딕셔너리 맞아요.

응답이 정확히 어떻게 생겼는지 궁금하면 print(data) 한 번 찍어보세요. 눈으로 봐야 머리에 들어옵니다.


main.py — 모든 걸 연결하는 진입점

from dotenv import load_dotenv
import requests

from src.api import get_weather
from src.display import print_weather

def main():
    load_dotenv()                                # .env를 환경변수로 등록
    city = input("도시 이름을 영어로 입력하세요: ").strip()

    if not city:
        print("도시 이름을 입력해주세요.")
        return

    try:
        data = get_weather(city)
        print_weather(data)
    except requests.exceptions.HTTPError as e:
        status = e.response.status_code
        if status == 401:
            print("API 키가 잘못됐어요. .env를 다시 확인해주세요.")
        elif status == 404:
            print(f"'{city}' 도시를 찾을 수 없어요. 철자를 확인해주세요.")
        else:
            print(f"서버 오류 발생: {status}")
    except requests.exceptions.ConnectionError:
        print("인터넷 연결을 확인해주세요.")
    except KeyError as e:
        print(f"응답에서 {e} 값을 찾을 수 없어요.")

if __name__ == "__main__":
    main()

 

load_dotenv()는 반드시 get_weather를 호출하기 전에, 그리고 함수 안에서 불러주세요. 위치 잘못 잡으면 키를 못 읽어서 또 401 떠요.

이제 weather_app 폴더에서 python main.py 실행하시면 끝입니다.


자주 만나는 에러 모음

비전공자분들이 이 프로젝트 하면서 진짜 자주 만나는 에러들이에요. 미리 알고 가시면 덜 당황하세요.

  • 401 Unauthorized: 키 오타거나, 아직 활성화 안 됐거나. 10분쯤 기다리고 다시 해보세요.
  • 404 Not Found: 도시명 철자 오타. "Seoul"이지 "Soul" 아니에요.
  • ConnectionError: 인터넷 안 됨. 와이파이부터 확인.
  • ModuleNotFoundError: src: 실행 위치 문제. 꼭 weather_app 폴더에서 실행하셔야 해요.
  • KeyError: 'main': 응답이 정상이 아닐 때 나타나요. 보통 401이나 404가 먼저 떠야 하는데, 그 예외처리를 빠뜨렸을 때 같이 나옵니다.

확장 아이디어

여기서 멈추지 마시고 본인 손으로 한 단계만 더 가보세요.

  • 5일 예보: 엔드포인트를 /forecast로 바꾸면 3시간 단위 예보가 옵니다. 응답 구조가 조금 더 복잡해요.
  • 여러 도시 비교: 도시 리스트를 받아서 반복 호출하고, 30편에서 배운 pandas로 표 만들기.
  • GUI로 업그레이드: tkinter로 입력창이랑 버튼 만들면 진짜 앱처럼 보여요.
  • 자동 알림: 매일 아침 비 예보가 있으면 슬랙으로 메시지 보내기.

뭐 하나라도 직접 만져보시면 이 프로젝트가 본인 것이 됩니다.


32편을 끝까지 따라오신 분께

솔직하게 말씀드릴게요.

블로그로 코딩 강의를 32편까지 완주하시는 분, 통계상 정말 드물어요. 10%도 안 됩니다. 그러니까 여기까지 오신 것만으로 이미 충분히 잘 해오신 거예요. 진심이에요.

이제 누가 "파이썬 할 줄 아세요?" 하고 물어보면, 자신 있게 "네" 하셔도 됩니다. 모든 걸 다 안다는 뜻이 아니라, 모르는 게 나와도 찾아서 해결할 수 있는 기본기가 생기셨다는 뜻이에요. 그게 진짜 실력이거든요.

이다음 방향이 막막하실 텐데, 관심 가는 쪽으로 가시면 됩니다.

  • 웹 만들고 싶으시면 FlaskFastAPI
  • 데이터 보는 게 재밌으셨다면 pandas, matplotlib을 더 깊게
  • 업무 자동화 쪽이면 크롤링, 셀레니움, 엑셀 자동화
  • 요즘 핫한 AI 쪽이면 OpenAI API, LangChain

어디로 가시든, 여기서 다진 기초가 든든하게 받쳐줄 거예요.


 


제 글이 도움이 되셨다면 댓글 & 공감 부탁드려요 😀

 

 
728x90