✨ Web page
- 정적 웹 페이지 (Static Web page)
- 있는 그대로를 제공하는 것(served as-is)을 의미
- 한 번 작성된 HTML 파일의 내용이 변하지 않고 모든 사용자에게 동일한 모습으로 전달되는 것
- 서버에 미리 저장된 HTML 파일 그대로 전달된 웹 페이지
- 같은 상황에서 모든 사용자에게 동일한 정보를 표시
- 동적 웹 페이지 (Dynamic Web page)
- 사용자의 요청에 따라 웹 페이지에 추가적인 수정이 되어 클라이언트에게 전달되는 웹 페이지
- 웹 페이지의 내용을 바꿔주는 주체 : 서버
- 서버에서 동작하고 있는 프로그램이 웹 페이지를 변경해줌.
- 이렇게 사용자의 요청을 받아서 적절한 응답을 만들어주는 프로그램을 쉽게 만들 수 있게 도와주는 프레임워크가 Django
- 다양한 서버 사이드 프로그래밍 언어 (Python, Java 등) 사용 가능 (파일을 처리하고 데이터베이스와의 상호작용이 이루어짐.)
Software Design Pattern
✨- 다양한 응용 소프트웨어를 개발할 때 공통적인 설계 문제가 존재하고 그를 처리하는 공통된 해결책 또한 존재하는데, 그것을 패턴화시켜둔 것을 의미
- 특정 문맥에서 공통적으로 발생하는 문제에 대해 재사용 가능한 해결책을 제시함.
- 다수의 엔지니어들이 일반화된 패턴으로 소프트웨어 개발을 할 수 있도록 한 규칙이자 커뮤니케이션의 효율성을 높이는 기법
MVC Design Pattern
✨- Model - View - Controller의 준말으로, 데이터 및 논리 제어를 구현하는 데에 널리 사용되는 소프트웨어 디자인 패턴
- 하나의 큰 프로그램을 세 가지 역할로 구분한 개발 방법론
- Model : 데이터와 관련된 로직을 관리
- View : 레이아웃과 화면을 처리
- Controller : 명령을 model과 view 부분으로 연결
- MVC Design Pattern의 목적
- "관심사 분리"
- 더 나은 업무의 분리와 향상된 관리를 제공
- 각 부분을 독립적으로 개발할 수 있어, 하나를 수정하고 싶을 때 모두 건들지 않아도 됨.
- ➡️ 개발 효율성 및 유지 보수가 쉬워짐, 다수의 멤버로 개발하기 용이함.
MTV Design Pattern (Django)
✨- Django는 MVC 패턴을 기반으로 한 MTV 패턴을 사용
- Model
- MVC 패턴에서 Model의 역할에 해당
- 데이터와 관련된 로직을 관리
- 응용프로그램의 데이터 구조를 정의하고 데이터베이스의 기록을 관리
- Template
- MVC 패턴에서 View의 역할에 해당
- 레이아웃과 화면을 처리
- 화면상의 사용자 인터페이스 구조와 레이아웃을 정의
- View
- MVC 패턴에서 Controller의 역할에 해당
- Model & Template과 관련한 로직을 처리해서 응답을 반환
- 클라이언트의 요청에 대해 처리를 분기하는 역할
- 동작 예시 : 데이터가 필요하다면 model에 접근해서 데이터를 가져오고, 가져온 데이터를 template으로 보내 화면을 구성하고, 구성된 화면을 응답으로 만들어 클라이언트에게 반환
Django Quick Start
✨# 가상환경 생성
# 첫 번째 venv는 명령어, 두 번째 venv는 가상환경 이름
python -m venv venv
# 가상환경 활성화 (윈도우)
source venv/Scripts/activate
# Django 설치
pip install django==3.2.13
# 패키지 목록 생성
pip freeze > requirements.txt
# 프로젝트 생성
# 마지막에 '.' 안 붙이면 현재 디렉토리에 프로젝트 디렉토리 생성되니까 꼭 붙여주기
# 프로젝트 이름에는 Python이나 Django에서 사용중인 키워드 및 하이픈 사용 불가
django-admin startproject projectname .
# 서버 실행
python manage.py runserver
# 애플리케이션 생성
# 일반적으로 앱 이름은 복수형으로 작성하는 것을 권장
python manage.py startapp appnames
# 애플리케이션 등록 (반드시 애플리케이션 생성 후 등록하실 것!)
# 'Local apps - Third party apps - Django apps' 순서로 정렬하는 것을 권장
# settings.py
INSTALLED_APPS = [
'appnames',
...
]
Django 프로젝트 구조
✨- __init__.py
- Python에게 이 디렉토리를 하나의 Python 패키지로 다루도록 지시
- 별도로 추가 코드를 작성하지 않음.
- asgi.py
- Asynchronous Server Gateway Interface
- Django 애플리케이션이 비동기식 웹 서버와 연결 및 소통하는 것을 도움
- 배포 시 사용
- settings.py
- Django 프로젝트 설정을 관리
- urls.py
- 사이트의 url과 적절한 views의 연결을 지정
- wsgi.py
- Web Server Gateway Interface
- Django 애플리케이션이 웹서버와 연결 및 소통하는 것을 도움
- 배포 시 사용
- manage.py
- Django 프로젝트와 다양한 방법으로 상호작용 하는 커맨드라인 유틸리티
Django 애플리케이션 구조
✨- 애플리케이션은 실제 요청을 처리하고 페이지를 보여주는 등의 역할을 담당
- 일반적으로 앱은 하나의 역할 및 기능 단위로 작성하는 것을 권장함.
- admin.py
- 관리자용 페이지를 설정하는 곳
- apps.py
- 앱의 정보가 작성된 곳
- 별도로 추가 코드를 작성하지 않음.
- models.py
- 애플리케이션에서 사용하는 Model을 정의하는 곳
- MTV 패턴의 M에 해당
- test.py
- 프로젝트의 테스트 코드를 작성하는 곳
- views.py
- view 함수들이 정의되는 곳
- MTV 패턴의 V에 해당
요청과 응답
✨- URL ➡️ VIEW ➡️ TEMPLATE
- URL
- urls.py에서 path를 설정
- 경로가 있으면 views.py에서 해당 함수를 불러오고, 없으면 404 error 발생
# urls.py from django.contrib import admin from django.urls import path from appnames import views urlpatterns = [ path('admin/', admin.site.urls), path('index/', views.index), ]
- VIEW
- HTTP 요청을 수신하고 HTTP 응답을 반환하는 함수 작성
- Template에게 HTTP 응답 서식을 맡김.
- render(request, templatename, context)
- 주어진 템플릿을 주어진 컨텍스트 데이터와 결합하고, 렌더링 된 텍스트와 함께 HTTPResponse(응답) 객체를 반환하는 함수
- request : 응답을 생성하는 데에 사용되는 요청 객체
- template_name : 템플릿의 전체 이름 또는 템플릿 이름의 경로
- context : 템플릿에서 사용할 데이터 (딕셔너리 구조)
# appnames/views.py def index(request): return render(request, 'index.html')
- TEMPLATE
- 실제 내용을 보여주는 데에 사용되는 파일
- 파일의 구조나 레이아웃을 정의
- Template 파일의 기본 경로 : appnames/templates
- 템플릿 폴더 이름은 반드시 templates라고 지정해야 함!
<!-- appnames/templates/index.html --> <!DOCTYPE html> ... <body> <h1>만나서 반가워요!</h1> </body> ...
Django Template Language (DTL)
✨- Django template에서 사용하는 built-in template system
- 조건, 반복, 변수 치환, 필터 등의 기능을 제공
- Python처럼 일부 프로그래밍 구조(if, for 등)를 사용할 수 있지만 이것은 python 코드로 실행되는 것이 아님!
- Django 템플릿 시스템은 단순히 Python이 HTML에 포함된 것이 아니니 주의
- 프로그래밍적 로직이 아니라 프레젠테이션을 표현하기 위한 것임을 명심하실 것
- DTL Syntax
- Variable
- {{ variable }}
- 변수명은 영어, 숫자, 밑줄의 조합으로 구성될 수 있으나 밑줄로는 시작할 수 없음.
- '.'을 사용하여 변수 속성에 접근할 수 있음.
- render의 세 번째 인자로 {'key': value}와 같이 딕셔너리 형태로 넘겨주며, 여기서 정의한 key에 해당하는 문자열이 template에서 사용 가능한 변수명이 됨.
- context 데이터가 많아질 경우, context라는 딕셔너리 변수에 데이터를 저장하여 넘겨주는 것을 권장
- Filters
- {{ variable|filter }}
- 표시할 변수를 수정할 때 사용
- 60개의 built-in template filters 제공
- chained가 가능하며 일부 필터는 인자를 받기도 함. ex) {{ name|truncatewords:30 }}
- Tags
- {% tag %}
- 출력 텍스트를 만들거나, 반복 또는 논리를 수행하여 제어 흐름을 만드는 등 변수보다 복잡한 일들을 수행
- 약 24개의 built-in template tags 제공
- 일부 태그는 시작과 종료 태그가 필요 ex) {% if something %}{% endif %}
- Comments
- {# #}
- Django template에서 라인의 주석을 표현하기 위해 사용
- 한 줄 주석에만 사용할 수 있음.
- 여러 줄 주석은 {% comment %}와 {% endcomment %} 사이에 입력
- Variable
템플릿 상속
✨- 템플릿 상속은 기본적으로 코드의 재사용성에 초점을 맞춤.
- 템플릿 상속을 사용하면 사이트의 모든 공통 요소를 포함하고 하위 템플릿이 override 할 수 있는 블록을 정의하는 기본 skeleton 템플릿을 만들 수 있음.
- {% extends 'base.html' %}
- 자식 템플릿이 부모 템플릿을 확장한다는 것을 알림.
- 반드시 템플릿 최상단에 작성되어야 함.
- {% block content %}{% endblock content %}
- 하위 템플릿에서 override 할 수 있는 볼륵을 정의
- 즉, 하위 템플릿이 채울 수 있는 공간
- 가독성을 높이기 위해 선택적으로 endblock 태그에 이름을 지정할 수 있음.
- 추가 템플릿 경로 만들기
- base.html의 위치를 앱 안의 template 디렉토리가 아닌 프로젝트 최상단의 template 디렉토리 안에 위치시키려면 기본 template 경로가 아닌 다른 경로를 추가하기 위해 아래와 같은 코드를 작성해야 함.
- 코드 작성 후 프로젝트 최상단에 templates 폴더 생성 후 base.html 이동
# settings.py TEMPLATES = [ { ... 'DIRS': [BASE_DIR / 'templates'], ... } ]
Sending form data (Client)
✨- HTML form element
- 데이터가 전송되는 방법을 정의
- 웹에서 사용자 정보를 입력하는 여러 방식(text, button, submit 등)을 제공하고, 사용자로부터 할당된 데이터를 서버로 전송하는 역할을 담당
- "데이터를 어디(action)로 어떤 방식(method)으로 보낼지"
- 핵심 속성
- action
- 입력 데이터가 전송될 URL을 지정
- 데이터를 어디로 보낼 것인지 지정하는 것이며 이 값은 반드시 유효한 URL이어야 함.
- 만약 이 속성을 지정하지 않으면 데이터는 현재 form이 있는 페이지의 url로 보내짐.
- method
- 데이터를 어떻게 보낼 것인지 정의
- 입력 데이터의 HTTP request methods를 지정
- HTTP form 데이터는 오직 GET 또는 POST 2가지 방식으로만 전송 가능
- action
# urls.py urlpatterns = [ ... path('throw/', views.throw), ] # appnames/views.py def throw(request): return render(request, 'throw.html')
<!-- appnames/templates/throw.html --> {% extends 'base.html' %} {% block content %} <h1>Throw</h1> <form action='#' method='#'> </form> {% endblock content %}
- HTML input element
- 사용자로부터 데이터를 입력받기 위해 사용
- type 속성에 따라 동작 방식이 달라짐.
- 핵심 속성
- name
- form을 통해 데이터를 submit 했을 때 name 속성에 설정된 값을 서버로 전송하고, 서버는 name 속성에 설정된 값을 통해 사용자가 입력한 데이터 값에 접근할 수 있음.
- 주요 용도는 GET/POST 방식으로 서버에 전달하는 파라미터로 매핑하는 것 (name은 key, value는 value)
- GET 방식에서는 URL에서 ?key=value&key=value/
- name
<!-- appnames/templates/throw.html --> {% extends 'base.html' %} {% block content %} <h1>Throw</h1> <form action='/catch/' method='GET'> <label for="message">Throw</label> <input type="text" id="message" name="message"> <input type="submit"> </form> {% endblock content %}
- HTTP request methods
- 자원에 대한 행위(수행하고자 하는 동작)를 정의
- HTTP method 예시
- GET
- 서버로부터 정보를 조회하는 데 사용
- 즉, 서버에게 자원을 요청하기 위해 사용
- 데이터를 가져올 때만 사용해야 함.
- 데이터를 서버로 전송할 때 Query String Parameters를 통해 전송 (데이터는 URL에 포함되어 서버로 보내짐.)
- POST
- PUT
- DELETE
- GET
- Query String Parameters
- 사용자가 입력 데이터를 전달하는 방법 중 하나로, url 주소에 데이터를 파라미터를 통해 넘기는 것
- Query String이라고도 함.
- 정해진 주소 이후에 물음표를 쓰는 것으로 Query String이 시작함을 알림.
- "key=value"로 필요한 파라미터의 값을 적음.
- 파라미터가 여러 개일 경우 앰퍼샌드(&)를 붙여 여러 개의 파라미터를 넘길 수 있음.
- ex) http://host:port/path?key=value&key=value
Retrieving the data (Server)
✨# urls.py
urlpatterns = [
...
path('catch/', views.catch),
]
# appnames/views.py
def catch(request):
message = request.GET.get('message')
context = {
'message': message,
}
return render(request, 'catch.html', context)
<!-- appnames/templates/catch.html -->
{% extends 'base.html' %}
{% block content %}
<h1>Catch</h1>
<h2>여기서 {{ message }}를 받았어!!</h2>
<a href="throw/">다시 던지러</a>
{% endblock %}
- 요청과 응답 객체 흐름
- 페이지가 요청되면 Django는 요청에 대한 메타데이터를 포함하는 HttpRequest object를 생성
- 그리고 해당하는 적절한 view 함수를 로드하고 HttpRequest를 첫 번째 인자로 전달
- 마지막으로 view 함수는 HttpResponse object를 반환
Variable routing
✨# urls.py
urlpatterns = [
...
path('hello/<str:name>/', views.hello),
path('<int:pk>/', views.detail),
]
# appnames/views.py
def hello(request, name):
context = {
'name' = name,
}
return render(request, 'hello.html', context)
- URL 주소를 변수로 사용하는 것을 의미
- URL의 일부를 변수로 지정하여 view 함수의 인자로 넘길 수 있음.
- 즉, 변수 값에 따라 하나의 path()에 여러 페이지를 연결시킬 수 있음.
- 변수는 <>에 정의하며 view 함수의 인자로 할당됨.
- 기본 타입은 string이며, 5가지 타입으로 명시할 수 있음.
- str : /를 제외하고 비어 있지 않은 모든 문자열
- int : 0 또는 양의 정수와 매치
- slug
- uuid
- path
App URL mapping
✨- 앱의 view 함수가 많아지면서 사용하는 path() 또한 많아지고, 앱 또한 더 많이 생성되기 때문에 프로젝트의 urls.py에서 모두 관리하는 것은 프로젝트 유지보수에 좋지 않음.
- 하나의 프로젝트에 여러 앱이 존재한다면, 각각의 앱 안에 urls.py를 만들어 URL 매핑을 위탁할 수 있음.
- 각각의 app 폴더 안에 urls.py를 작성하고 다음과 같이 수정 진행
# appnames/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('index/', views.index),
...
]
# projectname/urls.py
from django.contrib import admin
from django.urls import path, include
# include 되는 앱의 urls.py에 urlpatterns가 작성되어 있지 않다면 에러가 발생하므로
# include 할 때는 빈 리스트라도 작성해두실 것!
urlpatterns = [
path('admin/', admin.site.urls),
path('appnames/', include('appnames.urls')),
]
- 메인 페이지의 주소가 http://127.0.0.1:8000/appnames/index/로 변경됨.
- include()
- 다른 URLconf들을 참조할 수 있도록 돕는 함수
- 함수 include()를 만나게 되면 URL의 그 시점까지 일치하는 부분을 잘라내고, 남은 문자열 부분을 후속 처리를 위해 include된 URLconf로 전달
Naming URL patterns
✨- 링크에 URL을 직접 작성하는 게 아니라 path() 함수의 name 인자를 정의해서 사용
- DTL의 tag 중 하나인 URL 태그를 사용해서 path() 함수에 작성한 name을 사용할 수 있음.
- 이를 통해 URL 설정에 정의된 특정한 경로들의 의존성을 제거할 수 있음.
- Django는 URL에 이름을 저장하는 방법을 제공함으로써 view 함수와 템플릿에서 특정 주소를 쉽게 참조할 수 있도록 도움.
# appnames/urls.py
urlpatterns = [
path('index/', views.index, name='index'),
]
- Built-in tag url
- {% url '' %}
- 주어진 URL 패턴 이름 및 선택적 매개 변수와 일치하는 절대 경로 주소를 반환
- 템플릿에 URL을 하드 코딩하지 않고도 DRY 원칙을 위반하지 않으면서 링크를 출력하는 방법
Django의 설계 철학 (Template System)
✨- 표현과 로직을 분리
- 템플릿 시스템은 표현을 제어하는 도구이자 표현에 관련된 로직일 뿐
- 즉, 템플릿 시스템은 이러한 기본 목표를 넘어서는 기능을 지원하지 말아야 함.
- 중복을 배제
- 대다수의 동적 웹사이트는 공동 header, footer, navbar 같은 사이트 공통 디자인을 가짐.
- Django 템플릿 시스템은 이러한 요소를 한 곳에 저장하기 쉽게 하여 중복 코드를 없애야 함.
- 템플릿 상속의 기초가 되는 철학
Framework의 성격
✨- 독선적
- 독선적인 프레임워크들은 어떤 특정작업을 다루는 '올바른 방법'에 대한 분명한 의견(규약)을 가지고 있음.
- 대체로 특정 문제 내에서 빠른 개발 방법을 제시
- 어떤 작업에 대한 올바른 방법이란 보통 잘 알려져 있고 문서화가 잘 되어있기 때문
- 하지만 주요 상황을 벗어난 문제에 대해서는 그리 유연하지 못한 해결책을 제시할 수 있음.
- 관용적
- 관용적인 프레임워크들은 구성요소를 한데 붙여서 해결해야 한다거나 심지어 어떤 도구를 써야 한다는 '올바른 방법'에 대한 제약이 거의 없음.
- 이는 개발자들이 특정 작업을 완수하는 데에 가장 적절한 도구들을 이용할 수 있는 자유도가 높다는 것을 의미
- 하지만 개발자 스스로가 그 도구들을 찾아야 한다는 수고가 필요