Django 블로그를 끝까지 연결하려면 프로젝트를 만든 뒤 앱 등록, 모델 migration, 관리자 등록, 배포 서버의 WSGI 경로 설정을 순서대로 맞춰야 합니다. 로컬 서버, 관리자 데이터, 정적 파일, 운영 WSGI는 각각 다른 산출물을 확인해야 합니다. 기능이 어느 단계까지 작동하는지 먼저 적으면 설정을 무작정 바꾸지 않고 원인을 좁힐 수 있습니다.
Django 블로그가 로컬에서는 되는데 배포에서 막힐 때: 프로젝트부터 WSGI까지
프로젝트와 앱을 먼저 구분하기
프로젝트는 사이트 전체 설정을 담고, 앱은 blog처럼 하나의 기능을 담습니다. 원문의 개발 환경은 Anaconda의 Python 3.5와 당시 Django 명령을 사용합니다. 아래 순서는 그 환경에서 mysite 프로젝트와 blog 앱을 만드는 명령입니다.
1
2
3
4
conda create -n name python=3.5
pip install django
django-admin.py startproject mysite .
python manage.py startapp blog
명령을 실행했다고 앱이 사이트에 자동 연결되는 것은 아닙니다. mysite/settings.py의 INSTALLED_APPS에 blog를 추가해야 Django가 모델과 관리 대상을 읽습니다. 같은 파일에서 LANGUAGE_CODE, TIME_ZONE, STATIC_URL, STATIC_ROOT도 프로젝트 환경에 맞춥니다.
로컬 확인에 필요한 순서는 다음과 같습니다.
1
2
python manage.py migrate
python manage.py runserver
서버가 실행되면 브라우저에서 127.0.0.1:8000으로 확인합니다. 여기까지 성공했다면 프레임워크 설치와 기본 프로젝트는 동작하는 것이고, 이후 오류는 앱, 모델, URL 연결을 나눠 살펴볼 수 있습니다.
Post 모델을 데이터베이스와 관리자에 연결하기
원문은 SQLite를 사용하고 Post에 작성자, 제목, 본문, 작성일, 발행일을 둡니다. 발행 동작은 현재 시각을 published_date에 넣고 저장합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from django.db import models
from django.utils import timezone
class Post(models.Model):
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
모델 파일을 고친 뒤에는 변경 내역을 만들고 데이터베이스에 반영해야 합니다.
1
2
python manage.py makemigrations blog
python manage.py migrate blog
관리자에서 Post를 보려면 blog/admin.py에도 등록합니다.
1
2
3
4
from django.contrib import admin
from .models import Post
admin.site.register(Post)
그다음 python manage.py createsuperuser로 관리자 계정을 만들 수 있습니다. 모델을 작성했는데 관리자에 보이지 않는다면 INSTALLED_APPS, migration 실행 여부, admin.py 등록을 각각 확인하는 것이 빠릅니다.
PythonAnywhere 배포에서 맞춰야 할 경로
배포 흐름은 GitHub 저장소의 코드를 PythonAnywhere 콘솔에서 clone하고, virtualenv를 만든 뒤 Django 설치와 migration을 다시 수행하는 구조입니다. 로컬의 가상환경과 데이터베이스가 서버로 자동 복제되는 과정이 아니므로 서버 환경을 별도로 준비해야 합니다.
PythonAnywhere 웹 메뉴에서는 원문 기준으로 Manual configuration과 Python 3.6을 선택하고 virtualenv 경로를 지정합니다. WSGI 파일의 핵심은 프로젝트 경로와 settings 모듈입니다.
1
2
3
4
5
6
7
8
9
10
11
12
import os
import sys
path = '/home/<your-PythonAnywhere-username>/my-first-blog'
if path not in sys.path:
sys.path.append(path)
os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
from django.core.wsgi import get_wsgi_application
from django.contrib.staticfiles.handlers import StaticFilesHandler
application = StaticFilesHandler(get_wsgi_application())
이 코드는 <your-PythonAnywhere-username>을 실제 계정명으로 바꾸고, clone한 디렉터리가 정말 my-first-blog일 때만 맞습니다. 프로젝트 이름이 다르면 mysite.settings도 함께 바꿔야 합니다. ALLOWED_HOSTS에는 로컬 주소와 .pythonanywhere.com을 허용하도록 원문이 설정합니다.
작동하지 않을 때 순서대로 볼 체크리스트
문제를 한 번에 “Django 오류”로 묶지 말고 단계별 산출물을 확인합니다.
runserver가 뜨지 않으면 가상환경, Django 설치, settings 문법을 봅니다.- 앱 모델을 못 찾으면
INSTALLED_APPS와 import 경로를 봅니다. - 테이블이 없으면
makemigrations와migrate실행 순서를 봅니다. /admin/에 Post가 없으면admin.py등록과 superuser를 봅니다.- PythonAnywhere만 실패하면 WSGI의 절대경로,
DJANGO_SETTINGS_MODULE, virtualenv,ALLOWED_HOSTS를 봅니다. - 정적 파일이 빠지면
STATIC_URL과STATIC_ROOT가 같은 설정 파일에 반영됐는지 확인합니다.
이 글의 Python 3.5, 3.6과 배포 화면은 당시 환경을 기준으로 합니다. 명령을 최신 범용 배포법으로 간주하기보다, 프로젝트, 앱, 데이터베이스, WSGI가 어떤 순서로 연결되는지를 점검하는 기록으로 사용하는 편이 안전합니다.
로컬 성공을 배포 성공으로 어떻게 이어 가나
먼저 로컬에서 확인할 범위를 작게 나눕니다. 서버가 켜지는지, /admin/에 로그인되는지, Post를 저장하고 다시 읽을 수 있는지, 정적 파일이 보이는지를 차례로 확인합니다. 모델 코드를 바꾼 뒤 migration 파일만 만들고 실제 데이터베이스에 적용하지 않으면 관리자 등록 여부와 무관하게 테이블 오류가 납니다.
운영 환경에서는 코드 위치와 Python 환경이 달라집니다. WSGI가 import할 프로젝트 경로가 실제 배포 폴더와 일치해야 하고, 그 프로세스가 사용하는 가상환경에 Django가 설치돼 있어야 합니다. ALLOWED_HOSTS는 요청 도메인과 맞아야 하며, 개발용 runserver가 작동한다는 사실만으로 운영 WSGI 설정이 검증되지는 않습니다.
정적 파일은 애플리케이션 데이터와도 분리합니다. 게시글을 데이터베이스에서 읽는데 CSS만 없다면 모델이나 migration을 다시 만들 이유가 없습니다. 반대로 관리자에서 저장 자체가 실패하면 정적 파일 경로를 고쳐도 해결되지 않습니다. 이처럼 화면의 일부 성공 여부를 단서로 삼아 settings, database, WSGI, static 중 한 층씩 검사하는 것이 가장 빠릅니다.
함께 읽으면 이해가 이어지는 글
- Django 북마크 앱이 Admin에는 보이는데 화면에 안 뜰 때: 파일 연결 순서 — Django의 settings.py, models.py, admin.py, urls.py, views.py, templates가 어떤 순서로 연결되는지 북마크 앱으로 설명합니다. 앱 등록과 migration, URL include…
- ZeroClaw는 RAM 5MB로 무엇을 실행하나: Rust 런타임 검증 기준 — Node.js 기반의 무거운 AI 에이전트는 이제 그만. 3.4MB 단일 바이너리, 10ms 부팅 속도, 5MB 미만의 메모리 사용량을 자랑하는 Rust 기반 초경량 AI 런타임 ‘ZeroClaw’를 소개합니다. 설치부터 아키텍처…
- ADK-Go를 Python 에이전트 대신 고를 때: 동시성보다 먼저 볼 것 — Google ADK-Go의 에이전트 유형과 세션, 실행 구조를 살펴보고, Go 백엔드에 도입하기 전 생태계, 운영, 버전 조건을 판단합니다.
자주 묻는 질문
Django 프로젝트와 앱은 어떻게 다른가요?
프로젝트는 사이트 전체 설정과 URL, WSGI 진입점을 묶고, 앱은 게시글처럼 하나의 기능 영역을 담당합니다. 앱을 만들기만 해서는 활성화되지 않으므로 INSTALLED_APPS 등록이 필요합니다.
모델을 만들었는데 관리자 화면에 보이지 않는 이유는 무엇인가요?
앱 등록, migration 적용, admin.py의 모델 등록을 각각 확인해야 합니다. 데이터베이스 테이블 생성과 관리자 화면 노출은 서로 다른 단계입니다.
로컬에서는 되는데 PythonAnywhere에서만 실패하면 어디를 보나요?
WSGI의 프로젝트 절대경로, DJANGO_SETTINGS_MODULE, 가상환경, ALLOWED_HOSTS를 먼저 대조합니다. 정적 파일만 빠진다면 STATIC_URL과 STATIC_ROOT 및 수집 경로를 별도로 확인합니다.
게시글 하나로 전체 연결을 검증하는 방법
테스트용 Post 하나를 Admin에서 만들고 제목에 구분하기 쉬운 값을 넣습니다. 관리자 목록에서 다시 보이면 모델 등록과 데이터베이스 저장까지 확인한 것입니다. 같은 객체를 Django shell에서 조회하면 관리자 화면과 모델 query 사이도 분리해 볼 수 있습니다. 이 단계가 실패하면 URL이나 template을 고치지 않습니다.
그다음 가장 단순한 view에서 Post 개수나 제목 하나를 문자열로 반환합니다. 브라우저에서 값이 보이면 project URL, app URL, view, ORM까지 연결된 것입니다. 이후에 template 렌더링과 목록 context를 추가하면 TemplateDoesNotExist와 빈 queryset을 서로 다른 문제로 확인할 수 있습니다.
운영 배포에서는 같은 테스트 Post가 보이는지 확인하되 데이터베이스 위치를 주의합니다. 로컬 SQLite 파일과 서버의 파일이 다르면 코드는 같아도 데이터가 비어 보일 수 있습니다. WSGI 프로세스가 읽는 settings와 database 경로를 확인하고, 배포 과정에서 어느 파일이 복사됐는지 명시해야 합니다.
마지막으로 관리자, 게시글 화면, CSS 파일을 따로 요청합니다. 모두 실패하면 WSGI와 host를, 데이터만 실패하면 database와 migration을, CSS만 실패하면 static 경로를 봅니다. 하나의 화면 캡처보다 URL별 상태와 서버 로그의 첫 오류를 기록하는 편이 다음 수정 대상을 더 정확히 알려 줍니다.
설정을 바꿀 때는 한 번에 한 항목만 수정하고 서버 프로세스를 다시 불러온 뒤 같은 URL을 확인합니다. 여러 경로와 host를 동시에 고치면 우연히 작동해도 원인을 남길 수 없습니다. 운영 settings에 비밀값이나 debug 정보가 노출되지 않는지도 배포 전 별도 점검 대상으로 둡니다.
←→ 키와 좌우 스와이프를 지원합니다. 읽던 페이지는 이 기기에 저장됩니다.