오늘 처음으로 파이썬으로 웹을 구현하는 방법에 대한 궁금증을 가졌다. 그것은 다름이 아닌 기말고사에 시험이 없고 뭘 한다는 거였는데 일단 뭐라도 익혀주면 좋겠지 싶어서 필자가 젤 관심있는 웹을 연관시켰다. 찾아보니 플라스크, 장고가 가장 많이 이용되는 듯 하다. 플라스크를 먼저 공부하고 장고를 해보려했지만 튜토리얼은 장고쪽이 더 잘 만들어져 있어서 먼저 장고를 택했다. 참고로 튜토리얼은 장고 걸스를 참고하여 개인적인 생각을 가미하였다.

장고

장고와 NodeJS 같은 프레임워크를 이해하기 어려웠던 이유는 필자 처음 시도한 웹 프로그래밍이 NginxPHP를 조합한 것이기 때문이다. 웹서버를 올리고 거기에 파일을 올리고 사용자가 그 파일을 요청하면 그 파일은 그 소스코드를 처리해서 사용자에게 보내주는 것. 그게 당연한 줄 알았다. 하지만 장고, NodeJS는 따로 Nginx같은 웹서버를 필요로 하지 않았다. 사용자가 url을 요청하면 서버에서는 모델과 뷰를 조합하여 사용자에게 전달한다.

적용된 페이지

우리가 이 포스트를 통해서 만들 페이지는 위와같다.


뼈대 만들기!

장고를 사용하기 앞서 대부분 가상환경을 이용하여 구현하는 것을 일반적으로 사용하고 있는 듯 하다. 각 서비스에 필요한 프레임워크의 버전이 다르기 때문에 각각의 가상 환경을 구축하여 각 서비스에 맞는 환경을 구성해준다. 그 환경은 다른 서비스에 영향을 주지 않는다. 파이썬은 기본적으로 설치가 되어 있을테니 venv를 설치하자. 필자는 ubutnu를 기준으로 설명한다.

1
sudo apt-get install python-venv

이후 가상 환경을 만들어서 사용하자.

1
2
3
mkdir test; cd test
python3 -m venv mvenv
source mvenv/bin/activate

그럼 이제부터 터미널에 (mvenv)라는 수식이 붙은 것을 확인할 수 있다. 이 상태에서 장고를 설치하자. 그전에 pip의 업데이트가 있으면 업데이트를 먼저 해줄것이다.

1
2
python3 -m pip install --upgrade pip
pip install django~=2.0.0

장고를 설치했다면 django-admin을 이용해서 프로젝트의 골격을 생성할 것이다.

1
django-admin startproject main

골격이 생성되었다면 main 디렉터리의 setting.py 에서 몇가지 내용을 변경할 것이다.

1
2
3
4
5
TIME_ZONE='Asia/Seoul'
LANGUAGE_CODE='ko'
...
STATIC_URL='/static/'
STAITC_ROOT=os.path.join(BASE_DIR,'static')

이후 내용을 변경하고 test 디렉터리로 돌아와 다음 명령어를 수행하면 초기 화면을 확인할 수 있다.

1
2
python manage.py migrate
python manage.py runserver

이해가 안되는 점

  • 스태틱 루트를 생성하는 이유는?
    • STATIC_URL은 웹상에서 표시되는 경로다.
    • STATIC_ROOT는 운영체제 상에서 실존하는 위치다.

시작앱!

이후 manage.pystartapp이라는 명령어를 이용하여 blog를 생성해 보도록 하자.

1
python manage.py startapp blog

이후 mainsetting.py에서 INSALLED_APPS 항목에 blog를 추가한다.

1
2
3
4
5
6
7
8
9
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',
]

그 다음 블로그의 모델(blog/model.py)을 생성해 주어야 한다. 장고에선 MVC 모델을 사용하는데 이것에 대한 개념이 없다면 위키피디아 - MVC 모델을 참고하자.

1
2
3
4
5
6
7
8
9
10
11
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)
	
	def __str__(self):
		return self.title

위와같이 데이터베이스 모델을 생성했는데, author에서 적혀진 CASCADE는 작성자가 삭제되면 작성자가 포함된 인스턴스를 삭제한다는 것 같다. 튜토리얼엔 published_date도 있지만 필자의 입장에선 필요없어서 지웠다.

이제 manage.py에 모델이 변경되었음을 알려주어야 한다.

1
2
python manage.py makemigrations blog
python manage.py migrate blog


관리자 만들기!

필자가 굉장히 감탄한 부분은 데이터베이스 모델을 작성한 뒤 어드민 페이지로 들어가면 그럴싸한 모델 작성란이 등장한다. 정말 블로그를 하나를 뚝딱 만들어 낸 것 같은 착각을 들게 해준다.

먼저 blog/admin.py를 열어서 다음과 같이 수정하자.

1
2
3
4
from django.contrib import admin
from.models import Post

admin.site.register(Post)

이제 어드민 페이지에서 포스트를 등록할 수 있게 되었다. 어드민 계정을 하나 생성하도록 하자.

1
2
python manage.py createsuperuser
python manage.py runserver

runserver를 한 다음 127.0.0.1/admin로 이동하면 로그인 페이지가 나타난다. 자신이 작성한 어드민의 아이디와 비밀번호로 로그인을 시도하자. 그리고 새로운 포스트를 작성해보자!


포스트 출력

블로그에 포스트를 추가했으나 우리가 추가한 포스트를 확인할 수가 없다. 메인 페이지에서 포스트를 확인할 수 있도록 해주자. 먼저 메인 페이지에 접근했을때 반응할 수 있도록 main/urls.py에서 수정해 주도록 하자.

1
2
3
4
5
6
7
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('blog.urls')),
]

외부 파일을 불러올 수 있도록 include를 추가해 주었고 루트 디렉토리로 접근시 blog.urls가 반응하도록 하였다. 그럼 blog/urls.py에서 나머지 내용을 수정하자.

1
2
3
4
5
6
from django.urls import path
from . import views

urlpatterns = [
    path('',views.post_list,name='post_list'),
]

사용자가 루트 디렉터리로 접근시 post_list라는 뷰를 보여주도록 하였다. 그럼 이번엔 blog/views.py에서 post_list가 실질적으로 무엇인지 위치는 어디인지 정의하자.

1
2
3
4
from django.shortcuts import render

def post_list(request):
    return render(request, 'blog/post_list.html', {})

이제 blog디렉터리 아래에 templates/blog/post_list.html을 만들도록 할 것이다. 사용자가 메인 페이지에 접근했을 때 가장먼저 이 파일이 보여지는 것이다.

1
2
<h1>Hello</h1>
<p>World!</p>

위와같이 만들고 서버를 실행해보자. 위 html 파일이 보여지는 것을 확인할 수 있다. 그럼 우리가 작성한 포스트는 어떻게 보여줄 수 있을까? 그전에 해주어야 할 일은 blog/views.py를 수정해야 하는 것이다.

1
2
3
4
5
6
7
from django.shortcuts import render
from django.utils import timezone
from .models import Post

def post_list(request):
    posts = Post.objects.filter(created_date__lte=timezone.now()).order_by('created_date')
    return render(request, 'blog/post_list.html',{ 'posts':posts })

먼저 Post 모델을 불러와서 posts라는 변수를 만들었다. posts에는 모든 포스트 모델이 들어가는데 생성된 날자순으로 정렬되어 들어가있다. 그리고 templates/blog/post_list.html에 posts라는 변수를 넘겨주었다. 이제 templates/blog/post_list.html로 이동하여 포스트를 출력해보자.


이해가 안되는 점

  • 난 DB를 연동한 적이 없는데??? 어떻게 되는거지???
    • Django에서는 기본적으로 ORM 방식을 사용하며 sqlite를 내장하고 있음. sqlite는 파일 데이터 형식으로 데이터 베이스를 관리함

꾸며보자!

1
2
3
4
5
{% for post in posts %}
	<span>{{ post.created_date }}</span>
	<h2>{{ post.title }}</h2>
	<p>{{ post.text | linebreaksbr }}</p>
{% endfor %}

위와같이 작성한 후 서버를 실행해보면 자신이 작성한 포스트가 시간순으로 정렬되어 표시되는 것을 확인할 수 있다. 이번엔 static파일, 가령 css, js와 같은 파일을 추가하여 좀 더 예쁘게 만들어 보자. 필자는 블루프린트 - 타임라인을 이용하여 꾸밀것이다. 해당 소스코드에 있는 css, js파일은 전부 blog 디렉터리 아래 static 디렉터리를 생성하여 넣었다. 가령 다운받은 소스코드에서 css 파일은 blog/static/css/default.css와 같이 들어가 있다.

스태틱 파일을 사용하기 위해서 templates/blog/post_list.html의 최상단에 아래와 같이 입력해주자.

1
{% load static %}

이로써 우리는 static 파일을 사용할 수 있게 되었다.

1
2
3
<link rel="stylesheet" type="text/css" href="{% static 'css/default.css' %}" />
<link rel="stylesheet" type="text/css" href="{% static 'css/component.css' %}" />
<script src="{% static 'js/modernizr.custom.js' %}"></script>

스타일시트와 스크립트 파일에 위와같이 입력하여 static 파일을 사용할 수 있다. 그리고 서버를 시작해보자.

1
python manage.py runserver

적용된 페이지

WRITTEN BY

배진오

소비적인 일보단 생산적인 일을 추구하며, 좋아하는 일을 잘하고 싶어합니다 :D
im@baejino.com