오리엔테이션: 우리가 만들 것 - 테크창
프로그래밍

오리엔테이션: 우리가 만들 것

AI 활용 테크창 연구팀이 인공지능을 활용해 작성하고, 사실 확인과 편집 심사를 거쳐 발행한 칼럼입니다. 제작 과정 보기

조회 92회
댓글 0개
0
📚 연재 시리즈 AI가 짜준 Django, 이제 알고 씁니다 1 / 8

Cursor에게 "게시판 만들어줘"라고 했더니 폴더와 파일이 우르르 생겼습니다. 화면에 글 목록도 뜨는데, 제목 옆에 날짜 하나 넣으려니 어느 파일을 열어야 할지 모르겠죠. 결국 AI에게 또 "날짜 넣어줘"라고 물어봅니다. "동작은 하는데 왜 동작하는지 모르겠다"는 이 막막함이 이 연재의 출발점입니다.

이 연재가 내놓는 해법부터 말씀드리면, AI에게 고칠 파일을 지정해서 시키는 것입니다. "날짜 넣어줘"가 아니라 "board/templates/board/list.html의 제목 옆에 작성일을 넣어줘. 다른 파일은 건드리지 마"라고 말하는 겁니다. 이 한 줄을 쓰려면 어느 파일이 어떤 역할인지 알아야 하고, 그걸 한 편씩 뜯어 보는 것이 이 연재입니다.

연재는 Django 게시판 하나를 예제로 삼습니다. 오늘 0편에서는 세 가지에 답합니다.

  • 제목 옆에 날짜를 넣으려면 어느 파일을 열까요?
  • 폴더는 왜 두 겹이고, urls.py는 왜 두 개일까요?
  • 이 연재를 끝까지 읽으면 뭐가 달라지나요?

🤖 AI가 짜준 코드

프롬프트: "Django로 간단한 게시판 만들어줘"

📦 이 글의 기준: 일반 예제 프로젝트
이 글의 구조도와 코드는 특정 저장소에서 발췌한 것이 아니라, 연재 설명용으로 구성한 일반 예제입니다. AI가 만드는 결과는 도구와 프롬프트에 따라 파일 이름이나 함수 이름이 조금씩 다릅니다. 그래서 글에 실린 코드만으로 처음부터 만들 수 있게 했고, 직접 해보기에서 그 순서를 안내합니다. 빈 폴더에서 시작하는 명령은 맨 끝 부록에 있습니다.

예제 프로젝트의 구조는 이렇습니다. 이 글에서는 이 그림을 계속 참조합니다.

myboard_project/          ← 프로젝트 루트 (건물 전체)
├── manage.py             ← runserver 같은 명령을 내리는 진입점
├── myboard/              ← 프로젝트 설정 패키지
│   ├── __init__.py
│   ├── settings.py       ← 전체 설정 (INSTALLED_APPS 등)
│   ├── urls.py           ← ① 건물 입구의 urls.py
│   ├── asgi.py           ← asgi/wsgi는 서버 연결용 (지금은 몰라도 됨)
│   └── wsgi.py
└── board/                ← 게시판 앱 (건물의 한 층)
    ├── models.py         ← 글 데이터 정의 (title, content, created_at)
    ├── views.py          ← 날짜 값을 템플릿에 넘겨야 할 때만 열기
    ├── urls.py           ← ② 층 안쪽의 urls.py (직접 추가하는 파일)
    └── templates/
        └── board/
            └── list.html ← ★ 날짜를 넣을 때 가장 먼저 열 파일 (직접 추가하는 파일)
# board/ 안의 __init__.py, admin.py, apps.py, migrations/ 등 나머지 기본 파일은 일부 생략
# db.sqlite3는 migrate를 실행하면 manage.py 옆에 생기는 DB 파일

첫 번째 질문의 답은 이 그림에 있습니다. 날짜를 넣을 때 열 파일은 list.html이고, 날짜 값이 화면으로 넘어오지 않을 때만 views.py를 함께 봅니다. 이걸 알면 AI에게 주는 프롬프트가 이렇게 달라집니다.

  • 막연한 프롬프트: "날짜 넣어줘" → AI가 어디를 고칠지 추측합니다. 템플릿만 고칠 수도, views.py나 models.py까지 건드릴 수도 있어서 무엇이 바뀌었는지 따라가기 어렵습니다.
  • 파일을 지정한 프롬프트: "board/templates/board/list.html의 제목 옆에 작성일을 넣어줘. 다른 파일은 건드리지 마" → 바뀐 곳이 한 파일로 좁혀지니 결과를 확인하기 쉽습니다.

서버는 프로젝트 루트(manage.py가 있는 폴더)에서 이렇게 켭니다.

python manage.py runserver

브라우저에서 http://127.0.0.1:8000/board/를 열면 글 제목이 <ul> 목록으로 한 줄씩 나옵니다. 글이 하나도 없으면 빈 화면이 나옵니다. 예제의 글 목록에는 아직 작성일이 없고, 오늘 미션에서 제목 옆에 작성일을 붙여 봅니다.

글을 저장할 DB 표는 migrate로 만들고, 이 과정은 직접 해보기 1단계에 들어 있습니다. 원리는 6편에서 다룹니다.

참고로 startapp이 만들어 주는 것은 models.py, views.py 등이고, urls.py와 templates/는 만들어 주지 않습니다. 이 둘은 따로 채워 넣는 파일입니다. AI가 게시판을 만들어 줄 때도 이 두 가지를 직접 추가합니다.

🔍 한 줄씩 통역

폴더가 두 겹인 이유: 건물과 층

폴더가 두 겹으로 보이는 이유는 역할이 다른 폴더가 둘 있기 때문입니다. manage.py가 있는 바깥 폴더(프로젝트 루트)와 settings.py가 있는 안쪽 myboard/(설정 패키지)가 따로 있습니다.

django-admin startproject myboard .처럼 명령 끝에 .을 붙이면, 바깥 폴더를 새로 만들지 않고 지금 있는 폴더를 루트로 씁니다. .을 빼고 startproject myboard만 실행하면 바깥 myboard/ 폴더가 하나 더 생겨서 myboard/myboard/ 구조가 됩니다. AI가 만든 프로젝트에서 폴더 이름이 겹쳐 보이는 것도 대개 이 때문입니다.

그 옆의 board/가 앱, 즉 게시판이라는 기능 하나를 담당하는 폴더입니다. 비유하면 프로젝트는 건물이고 앱은 층입니다. 나중에 회원 기능이 필요하면 층(앱)을 하나 더 올리면 됩니다. 새 앱은 settings.py의 INSTALLED_APPS에 등록해야 Django가 인식합니다. 이 목록은 아래 '자주 깨지는 지점'에서 다시 만납니다.

urls.py가 두 개인 이유: 입구와 층

urls.py가 두 개인 것은 건물 입구에서 한 번, 층 안에서 한 번 길을 나누기 때문입니다. 예제 코드를 보겠습니다.

① 건물 입구: myboard/urls.py

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('admin/', admin.site.urls),
    path('board/', include('board.urls')),   # 'board/'로 시작하면 board 앱으로 넘김
]

② 층 안쪽: board/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('', views.list),   # 'board/' 뒤에 남은 부분이 비어 있으면 views.list 실행
]

방문자가 /board/로 들어오면 요청은 이 순서로 움직입니다.

GET /board/
   │
   ▼
myboard/urls.py   path('board/', include('board.urls'))
   │              → 'board/'가 일치합니다. 남은 주소 ''를 board.urls로 넘깁니다.
   ▼
board/urls.py     path('', views.list)
   │              → '' 가 일치합니다. views.list 함수를 실행합니다.
   ▼
board/views.py    def list(request): ...
   │              → 데이터를 챙겨 템플릿에 넘깁니다.
   ▼
board/templates/board/list.html   → 완성된 HTML이 응답으로 나갑니다.

이렇게 나눠 두면 주소를 바꾸기 쉽습니다. board/를 community/로 바꾸고 싶다면 입구 urls.py의 한 줄만 고치면 됩니다.

# 고치기 전: myboard/urls.py
path('board/', include('board.urls')),

# 고친 후: myboard/urls.py
path('community/', include('board.urls')),

board/urls.py는 한 글자도 바꾸지 않습니다. 이제 글 목록은 /community/에서 열립니다. 템플릿에 /board/ 주소를 직접 적어 둔 링크가 있다면 그것만 같이 고치면 됩니다. 큰 길은 myboard/urls.py가, 층 안의 세부 길은 board/urls.py가 맡는 구조입니다. 이 요청이 오가는 길 전체가 이 연재의 지도입니다.

models.py, views.py와 템플릿: 데이터, 데이터를 모으는 곳, 화면을 그리는 곳

먼저 글 데이터의 모양을 정하는 board/models.py입니다. 날짜 미션에서 쓸 created_at 필드가 여기 있습니다.

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)   # 글이 저장되는 순간의 시각이 자동으로 들어감

board/views.py는 요청을 받아 필요한 데이터를 모아 템플릿에 넘깁니다.

from django.shortcuts import render
from .models import Post

def list(request):
    posts = Post.objects.all()
    return render(request, 'board/list.html', {'posts': posts})

board/templates/board/list.html은 넘겨받은 데이터를 HTML에 끼워 화면을 만듭니다.

<ul>
  {% for post in posts %}
    <li>{{ post.title }}</li>
  {% endfor %}
</ul>

여기서 list라는 함수 이름은 파이썬 내장 list와 겹칩니다. 동작은 하지만 실무에서는 post_list처럼 구분되는 이름을 권장합니다. 이 연재에서는 설명을 단순하게 하려고 list를 그대로 씁니다.

posts로 넘어가는 Post 객체에는 이미 created_at이 들어 있습니다. 데이터를 모으는 일(views.py)과 화면을 그리는 일(템플릿)이 나뉘어 있어서, 이미 넘어오는 값을 화면에 더 보여 주는 "날짜 추가" 같은 일은 list.html만 열면 됩니다. 처음 던진 "어느 파일을 열어야 하나"의 답이 바로 이 분업입니다.

⚠️ 자주 깨지는 지점

이 연재에서 가장 먼저 만나기 쉬운 에러는 앱 등록과 관련된 것입니다. 이 예제에서 INSTALLED_APPS의 'board',를 빼면 어떻게 되는지 코드 흐름으로 따라가 보겠습니다.

  1. /board/ 요청이 오거나 서버가 시작되면서 Django가 URLconf를 읽습니다.
  2. myboard/urls.py의 include('board.urls')가 board/urls.py를 import합니다.
  3. board/urls.py가 from . import views로 views.py를 import합니다.
  4. views.py가 from .models import Post를 실행하고, Post 클래스가 정의되는 순간 Django가 "이 모델이 속한 앱이 등록되어 있나?"를 확인합니다.

템플릿을 찾는 단계는 그 뒤라서, 이 예제에서는 템플릿 에러가 나오기 전에 3~4단계에서 먼저 멈춥니다. 따라서 이 예제의 기준 증상은 다음과 같습니다.

RuntimeError: Model class board.models.Post doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.

이 에러는 board 폴더와 파일은 그대로 있는데 Django가 board를 앱으로 인식하지 못한다는 뜻입니다. 에러 문구의 세부 표현은 Django 버전에 따라 조금 다를 수 있으니, 직접 해보실 때는 본인 화면의 첫 줄과 아래 명령으로 확인한 버전을 함께 메모해 두세요.

직접 확인하는 방법:

  1. python -m django --version으로 본인의 Django 버전을 확인해 적어 둡니다.
  2. myboard/settings.py의 INSTALLED_APPS에서 'board', 줄을 주석 처리하고 저장합니다.
  3. python manage.py runserver를 실행하거나 /board/를 새로고침해 첫 줄이 위 RuntimeError인지 확인합니다.

고치는 순서:

  1. settings.py를 열어 INSTALLED_APPS 리스트에 'board',를 다시 넣습니다.
INSTALLED_APPS = [
    # ... 기본 앱들 ...
    'board',
]
  1. 저장하고 /board/를 새로고침해 목록이 돌아오는지 확인합니다.

별도 증상: TemplateDoesNotExist

앱 등록과 상관없이 템플릿 파일을 못 찾을 때는 이런 에러가 따로 나옵니다.

TemplateDoesNotExist: board/list.html

모델과 뷰는 정상인데 템플릿 위치나 설정이 어긋났을 때 보이는 증상입니다. 앱의 templates/ 폴더는 INSTALLED_APPS 등록과 TEMPLATES 설정의 APP_DIRS가 True일 때 탐색 대상이 됩니다. 이 에러는 3~4편에서 자세히 다루고, 지금은 확인 목록만 챙겨 두세요.

  • INSTALLED_APPS에 'board'가 등록돼 있는지
  • settings.py의 TEMPLATES 항목에 'APP_DIRS': True가 있는지
  • templates/ 폴더가 board/ 앱 폴더 바로 아래에 있고, 그 안에 board/list.html처럼 한 겹 더 들어 있는지
  • 뷰에 적은 템플릿 경로에 오타가 없는지 (board/list.html인데 board/lists.html로 쓴 경우 등)

🗺️ 연재 지도와 완주 후 얻는 것

각 편이 위 구조도의 어느 부분을 뜯는지 표로 정리했습니다. 길을 잃으면 이 표로 돌아오세요.

편 주제 구조도에서 뜯는 곳
1편 Django는 대체 뭘 대신 해주나 전체 구조도: Django가 만든 파일과 직접 채운 파일 구분
2편 URL 한 줄의 정체 (라우팅) myboard/urls.py와 board/urls.py 두 파일
3편 뷰 = "요청 들어오면 뭐 할지" board/views.py
4편 템플릿 = HTML에 데이터 끼우기 board/templates/board/list.html
5편 모델 = AI가 만든 표(테이블)의 실체 board/models.py
6편 마이그레이션 = "DB야, 나 바뀌었어" models.py 변경을 DB에 반영하는 migrate
7편 폼과 CSRF = 글쓰기가 되는 원리 글쓰기 흐름: 템플릿의 폼 + views.py
8편 로그인은 어떻게 나를 "기억"하나 INSTALLED_APPS에 있던 auth·sessions 등 기본 앱
9편 정리 + 내 손으로 기능 하나 추가하기 구조도 전체: urls → views → 템플릿 흐름 복습

완주하면 에러가 났을 때 "urls.py 문제인지, views.py 문제인지, 템플릿 문제인지"부터 가릴 수 있습니다. 그리고 앞에서 본 파일 지정 프롬프트처럼 고칠 곳을 짚어 AI에게 정확히 시킬 수 있습니다. 코드를 복붙하는 단계에서 읽고, 고칠 곳을 짚고, AI에게 정확히 시키는 단계로 넘어가는 것이 목표입니다.

🎮 직접 해보기

미션입니다. 처음의 막막함을 3단계로 직접 풀어 봅니다. 준비 시간까지 합쳐 15분쯤 잡으세요.

  1. 예제 프로젝트를 준비합니다.
  2. 맨 끝 부록의 명령으로 manage.py, myboard/, board/를 만듭니다.
  3. 이 글의 myboard/urls.py, board/urls.py, board/models.py, board/views.py, board/templates/board/list.html을 해당 위치에 저장합니다. templates/board/ 폴더는 직접 만드세요.
  4. settings.py의 INSTALLED_APPS에 'board',를 추가합니다.
  5. DB 표를 만듭니다. 이 프로젝트에는 DB 파일이 들어 있지 않으므로 아래 두 줄을 실행해야 /board/에서 no such table 에러가 나지 않습니다. 원리는 6편에서 다룹니다.

bash python manage.py makemigrations board python manage.py migrate

  • 확인용 글을 하나 넣습니다.

bash python manage.py shell -c "from board.models import Post; Post.objects.create(title='첫 글', content='안녕하세요')"

  • python manage.py runserver를 실행하고 http://127.0.0.1:8000/board/를 엽니다. 목록에 '첫 글'이 보이면 성공입니다.
  • board/templates/board/list.html을 열어 글 제목을 보여 주는 줄({{ post.title }})을 찾습니다.
  • 그 파일을 프롬프트에 직접 지정해서 AI에게 시킵니다. 예: "board/templates/board/list.html의 제목 줄 옆에 작성일을 한 줄 넣어줘. 날짜 값은 post.created_at을 써줘. 다른 파일은 건드리지 마". 새로고침해서 날짜가 보이는지 확인하고, AI가 실제로 고친 파일과 줄이 어디인지 직접 확인해 보세요. list.html만 바뀌었다면 오늘 배운 분업이 그대로 맞은 것입니다.

막히면 어디까지 따라 했는지, 화면 또는 에러 메시지의 첫 줄, 그리고 python -m django --version 결과를 메모해 두세요. 이 세 가지만 있으면 원인을 훨씬 빨리 좁힐 수 있습니다.

⏭️ 다음 편 예고

1편 "Django는 대체 뭘 대신 해주나"에서는 이 모든 폴더와 파일 중 Django가 우리 대신 해주는 부분이 어디까지인지, 그리고 AI가 짠 코드 중 "내가 안 써도 되는 부분"이 정확히 어디인지 가려 보겠습니다.

📎 부록: 빈 폴더에서 직접 만들려면

직접 해보기 1단계에서 쓰는 준비 명령입니다. 이 명령만으로는 manage.py, myboard/, board/의 기본 파일까지만 생깁니다. urls.py(앱 안쪽), templates/, 그리고 본문의 모델·뷰·템플릿 코드는 본문을 보고 채웁니다. AI에게 시킨다면 "게시판 기능을 추가해줘"라고 요청하면 됩니다.

mkdir myboard_project          # 빈 폴더 만들기
cd myboard_project
python -m venv .venv           # 가상환경 만들기 (맥/리눅스는 python3일 수 있음)
source .venv/bin/activate      # 윈도우: .venv\Scripts\activate
pip install django             # Django 설치
django-admin startproject myboard .
python manage.py startapp board

이미 가상환경과 Django가 준비돼 있다면 venv, activate, pip install 줄은 건너뛰어도 됩니다.


📚 시리즈: AI가 짜준 Django, 이제 알고 씁니다 · 0편 · 오리엔테이션
테크창 연구팀
본 칼럼은 AI 보조로 작성되었으며, 코드·예시는 학습용입니다.


(수정 담당자 확인 사항, 게재 시 이 줄 아래는 포함하지 마세요) 이번 수정 환경에서는 Django를 실행할 수 없어 앱 미등록 실험을 실제로 돌리지 못했습니다. 그래서 버전과 출력 결과를 지어 넣지 않고, 코드의 import 순서에 근거해 RuntimeError를 기준 증상으로 설명했으며 "직접 재현해 보겠습니다" 문구는 삭제했습니다. 게재 전에 Django 버전을 정해 실험을 돌린 뒤, '자주 깨지는 지점'에 실제 버전과 첫 줄을 추가해 주세요. Q&A 게시판 문구는 근거가 없어 삭제했고, 링크가 확인되면 직접 해보기 끝에 다시 넣으면 됩니다.

오늘 글에서 하나 가져간다면?

다 읽고 남은 한 가지를 한 줄로 적어 주세요. 다른 독자에게도, 다음 글을 쓰는 연구팀에게도 가장 좋은 신호가 됩니다.

Making of · 이 칼럼이 만들어진 과정

AI 연구원 5명이 5번 심사하고 7번 고쳐 쓴 글입니다

  • 5편집 심사
  • 7재집필
  • 3평론
  • 4시간 46분제작 기간
심사 점수 51 → 59 → 68 → 62 → 80점점선은 프리미엄 기준 90점
제작 과정 전체 보기
T
techchang연구팀
시리즈 목차 전체 보기

아직 댓글이 없습니다. 첫 번째 댓글을 작성해보세요!

댓글을 작성하려면 로그인해주세요

로그인
모바일 버전