Django Rest Framework와 React에서 이를 이용해 Shopping mall 만들기
https://www.youtube.com/watch?v=JD-age0BPVo&list=PLzMcBGfZo4-kCLWnGmK0jUBmGLaJxvi4j&index=2
위 유튜브 Django & React Tutorial #1 ~ #3을 참고하였다.
기본 흐름은 다음과 같다.
DRF 세팅
1. 프로젝트 폴더 만들기 및 visual studio code로 해당 폴더 열기
2. 확장 프로그램 설치(장고, 코드에디터, 아래 snippets들)
3. django 프로젝트 폴더 생성
django-admin startproject shop_controller
- 이렇게 하면 shop_controller 폴더가 생성되고, 그 안에 설정파일을 모아 놓은 shop_controller 폴더가 또 생성됨.
shop_controller/shop_controller 는 프로젝트의 설정 담당하는 것들이라고 보면 됨.
4. 프로젝트 폴더 안에 api로 사용할 app 만들기 (이름 api로 했음)
cd shop_controller
django-admin startapp api
5. api 앱의 apps.ApiConfig, rest_framework shop_controller/settings.py에 추가해주기
INSTALLED_APPS = [
...
'api.apps.ApiConfig',
'rest_framework',
]
6. api 앱에 urls.py 생성 (앱별 url 관리하고, 나중에 통합 urls.py(프로젝트 폴더의 urls)에서 관리하기 위해)
# api.urls.py
from django.urls import path
from .views import main
urlpatterns = [
path('', main),
]
7. shop_controller/urls.py에 위 urls including. 'api/' 경로로 온 것은 다 api.urls로 보내는 것. 그리고 위 api.urls에서 처리해서 page 보여주는 것
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('api.urls')),
]
8. 테스트용 view 작성
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def main(request):
return HttpResponse("Hello")
9. migrate하여 db 변경사항 저장
python manage.py migrate
10. model에 Item class 작성 후 migrate
from django.db import models
# Create your models here.
class Item(models.Model):
writer = models.CharField(max_length=50, unique=True)
image = models.ImageField(verbose_name='image', null=True, blank=True)
listing_or_not = models.BooleanField(null=False, default=False)
like_count = models.IntegerField(null=False, default=0)
created_at = models.DateTimeField(auto_now_add=True)
11. serializers.py 생성 >> 위 모델에서 Item 클래스(필드)를 json으로 변환하여 응답해주기 위한 기능
from rest_framework import serializers
from .models import Item
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = ('id', 'writer', 'image',
'listing_or_not', 'like_count', 'created_at')
12. views.py 변경. 위에서 만든 models와 serializers 적용한 json 값 보여주도록. 우선 CreateAPIView로 보여주기.(글 작성 및 확인 가능한 View)
from django.shortcuts import render
from rest_framework import generics
from .models import Item
from .serializers import ItemSerializer
class ItemView(generics.CreateAPIView):
queryset = Item.objects.all()
serializer_class = ItemSerializer
13. api/urls.py 에 새로 만든 view class 추가
from django.urls import path
from .views import ItemView
urlpatterns = [
path('', ItemView.as_view()),
]
리액트(React) 세팅
1. 프로젝트 폴더에 frontend app 만들고, 해당 앱 안에 static(+ /images, css, frontend(js 번들 저장할 곳)), templates 폴더 추가
django-admin startapp frontend
2. packge.json 만들기 ( frontend 프로젝트를 위해 다운, 사용한 node module, packg json 등 기록되는 것)
npm init -y
3. webpack 및 babel 설치
* webpack : js 파일을 하나로 합쳐주는 것. 여러개 파일로 로딩하는 것은 네트워크 비용이 많이 들고, 또 변수 충돌의 위험이 있음.
* babel : 브라우저가 최신 js 코드를 인식 못하는 경우가 있을 수 있음. babel js를 compile 해주어 해당 에러 방지할 수 있음
npm i webpack webpack-cli --save-dev
npm i @babel/core babel-loader @babel/preset-env @babel/preset-react --save-dev
>> --save-dev로 저장하면, package.json에 그냥 dependencies가 아닌, devDependencies에 저장된다. 개발환경과 분리해주는 것.
4. react-dom 설치
UI를 브라우저에 렌더링 할때 사용하는 라이브러리.
근데 react(18 이상)부터는 지원하지 않고, ReactDOM.createRoot() API가 대체한다고 한다. 바꿀 필요가 있어보임.
npm i react react-dom --save-dev
5. Material-UI 설치. 웹 디자인 css 작성을 위한 프레임워크. 부트스트랩 같은 역할. icons는 1000여개 이상의 아이콘 제공해줌.
* 혹시 다운이 안되면 --save ... 붙여서 실행하면 됨
npm install @material-ui/core --save --legacy-peer-deps
npm install @material-ui/icons --save --legacy-peer-deps
6. plugin-proposal-class-properties >> class 내에서 instance 변수 선언 및 arrow function을 멤버 메소드로 사용할 수 있게 해줌.
npm install @babel/plugin-proposal-class-properties
7. react-router-dom 설치. react에는 router(url 처리하여 페이지 보여주는 것.)가 기능 내장된게 없어서 library 써야 한다 함.
>npm install react-router-dom
8. frontend 앱에 babel.config.json 생성.
- 설치한 라이브러리들을 presets 및 plugins으로 사용
- node에 현재 사용중인 node js 버젼 넣으면 됨
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "16"
}
}
],
"@babel/preset-react"
],
"plugins": ["@babel/plugin-proposal-class-properties"]
}
9. webpack.config.js 생성
- 우리의 entry js 파일 있는 위치, output할 위치 등 설정.
- lodaer로 babel-loader 사용한다는 의미,
- optimization에서 minimize하여 공백 다 없애서 로딩시간 줄이기.
const path = require("path");
const webpack = require("webpack");
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "./static/frontend"),
filename: "[name].js",
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
],
},
optimization: {
minimize: true,
},
plugins: [
new webpack.DefinePlugin({
"process.env": {
// This has effect on the react lib size
NODE_ENV: JSON.stringify("production"),
},
}),
],
};
10. package.json scripts 부분 수정
- dev일 때는 webpack을 development, watch 모드로 실행.
>> js 파일이 변경되거나 하면 서버 재시작해서 변경사항 적용 확인되도록
- build일 때는 production 모드로 실행
"scripts": {
"dev" : "webpack watch --mode development",
"build" : "webpack --mode production"
},
11. frontend urls 추가 및 settings.py urls에에 해당 url 추가
# frontend/urls
from django.urls import path
from .views import index
urlpatterns = [
path('', index),
]
# settings/urls
...
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('api.urls')),
path('', include('frontend.urls')),
]
12. index.html, index.js, App.js 작성
index.js 가 Entry file이고 이게 App.js를 importing 해서,
App.js에서 rendering될 부분에 rendering할 내용 날려주고(여기선 index.html에 App 클래스 날려줌)
index.html은 해당 페이지를 보여주는 것.
// index.js
import App from './components/App';
// App.js
import React, { Component } from "react";
import { render } from "react-dom";
// 현재 파일의 default 앱
export default class App extends Component {
constructor(props){
super(props);
}
render(){
return (<h1>Testing React Code</h1>);
}
}
const appDiv = document.getElementById("app");
render(<App />, appDiv);
// index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Item Controller</title>
{% load static %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
/>
<link rel="stylesheet" type="text/css" href="{% static "css/index.css" %}"
/>
</head>
<body>
<div id="main">
<div id="app"></div>
</div>
<script src="{% static "frontend/main.js" %}"></script>
</body>
</html>
13. frontend/views 작성
그리고 django views가 url에 맞춰서 html 날려주는 건 똑같고. 약간 이 views 부분이 react랑 django 다리 역할 느낌?
from django.shortcuts import render
# Create your views here.
def index(request, *args, **kwargs):
return render(request, 'frontend/index.html')
14. settings.py에 생성한 앱 추가
INSTALLED_APPS = [
...
'frontend.apps.FrontendConfig',
]
15. python 서버와 npm 서버 실행
python manage.py runserver
npm run dev
** 그런데 WARNING in DefinePlugin Conflicting values for 'process.env.NODE_ENV' 에러가 발생해서 아래 webpack.config.js 부분을 바꿨음. 근데 이렇게 하면 번들이 무거워질 수 있다고, production으로 바꾸는 거 추천한다고 하는데.. 왜 생긴 에러인지를 아직 모르겠네.
plugins: [
new webpack.DefinePlugin({
"process.env": {
// This has effect on the react lib size
NODE_ENV: JSON.stringify("development"),
},
}),
],
};
webpack warning - WARNING in DefinePlugin Conflicting values for 'process.env.NODE_ENV'
I'm getting the warning in the title when I try to run development mode. This script used to work fine for an earlier website but now I always get this warning. This is my package.json: { "n...
stackoverflow.com
* 정상적으로 react와 django 연결 완료