둘의 작업의 단위가 다르다. Oracle로 사용하려면, User까지 확인해야 한다.
설정 정보
- 별도의 txt 파일이나, DB에 작성하는 경우가 많다.
- 1. properties : 속성 : 값, 여러번 사용가능
- 2. xml
- 3. json
- 4. yaml(yml) : email 표현 형식
- yaml은 똑같은 속성 여러번 작성 x, 트리처럼 작성해야 함.(정리)
소스코드
- Compile Build EXE
- 코드가 한 글자라도 바뀐다면 위의 과정을 전부 다시 해야한다.
개발 환경에서는 운영환경의 데이터를 쓰는 것이 아닌, 자체 리소스로 개발해야 한다.
- 이후, 이것을 운영환경으로 옮긴다. (migration)
- 리소스 관련 코드가 소스코드에 있다면, Compile, Build를 하는데 여기서 오류가 정말 많이 발생한다.(환경이 바뀌면 문제가 생길 가능성이 존재함)
- 그래서 환경을 하나로 묶은 DevOps
- 그리고 등장한 개념이 일반파일 or DB
이름을 dp.properties라고 하자. 그러면 소스코드에서 db.properties를 읽음. 하지만 파일을 바꿨다고 해서 소스코드가 바뀌는 것은 아니다.
일반 리소스의 변화는 소스코드에 아무 변화를 주지 못한다.
from django.db import models class Todo(models.Model) : # model 클래스로부터 상속 받도록 id=models.AutoField(primary_key=True) # Auto_increment userID=models.CharField(max_length=100) title=models.CharField(max_length=100) done=models.BooleanField() regdate=models.DateTimeField(auto_now_add=True)# 작성 날짜 자동 moddate=models.DateTimeField() #계정을 delete = 1 이렇게 해서 휴면계정을 설정할 수 있다.
python manage.py makemigrations python manage.py migrate
show tables; desc todoapplication_todo; (권장) select * from todoapplication_todo;
가져오기 - GET
삽입 - POST
수정하기 - (PUT : 전체 수정, 멱등성 O Update : 부분수정, 멱등성 x)
삭제하기 - DELETE
프로젝트 vs 앱
ulrs views
urls
Routing
요청 (Front)Controller 처리
읽기 앱 + 나머지 기능 앱
이후
읽기 앱은 mongodb나머지는 mysql
구독과 게시 kafka
"문서화" 해서 설명해두기
- 우선 원래 실무에서는 views.py는 controller의 역할로만 존재하게 한다.
from django.shortcuts import render from django.views import View #클래스의 get, post, put, delete 메서드가 각 요청 방식을 처리함 class TodoView(View):
from django.contrib import admin from django.urls import path from todoapplication import views # todo 요청은 views파일의 TodoView 클래스가 처리하도록 설정 urlpatterns = [ path("admin/", admin.site.urls), path("todo", views.TodoView.as_view()) ]
views.py에서
from django.views import View #클래스의 get, post, put, delete 메서드가 각 요청 방식을 처리함 from .models import Todo # JSON 응답을 만들기 위한 import from django.http import JsonResponse from rest_framework import status class TodoView(View): def get(self,request): # 파라미터 읽어오기 # userid가 없다면 none userID=request.GET.get("userID", None) if userID !=None: todos=Todo.objects.filter(userID=userID) else: todos=Todo.objects.all() # Json 응답, list라는 키로 검색된 데이터를 list로 전달 return JsonResponse({'list':list(todos.values())}, status=status.HTTP_200_OK)
- 이후 서버 재가동 하고 :8000/todo 해보면 데이터가 없어서
{"list": []}
만 보인다.
http://127.0.0.1:8000/todo?userID=mino
이렇게 하면 mino userID인 것 만 나온다. def post(self, request): # 파라미터 읽기 params=json.loads(request.body) userID=params["userID"] title=params["title"] #삽입할 객체 생성 todo=Todo() todo.userID=userID todo.title=title todo.done=False #regdate는 auto 현재 날짜이지만, moddate는 없으니 설정 todo.moddate=datetime.datetime.today() #데이터 저장 todo.save() #삽입하고 결과 처리 #일반 적으로 삽입한 데이터만 리턴하거나, 아니면 #전체 데이터 리턴 방식이 존재함 트래픽때문에 전체 다운로드는 #생각을 좀 해봐야 한다. #나는 삽입한 데이터 하나만 리턴할래 todos = Todo.objects.filter(userID=userID) # Json 응답, list라는 키로 검색된 데이터를 list로 전달 return JsonResponse({'list': list(todos.values())}, status=status.HTTP_200_OK)
- 제대로 동작하는지 확인해보고 싶은데?
post 확인해보기
http://127.0.0.1:8000/todo
파라미터{ "userID":"mino3" "title":"귀가하기" }
- Django에서는 Decorator로 해당 문제를 해결합니다.
- views.py 파일의 요청 처리 클래스 위에 설정을 추가
- python -> decorator 다른 곳 annotationfrom django.views.decorators.csrf import csrf_exempt from django.utils.decorators import method_decorator @method_decorator(csrf_exempt, name='dispatch')
- 이러면 get을 날려서 post가 잘 된 것을 확인할 수 있다.
# 클라이언트의 파라미터 읽기 # 서버에서의 처리 # 응답 만들기
- 이 세 가지 단계로 웹 프로그래밍은 처리한다.
def put(self, request): # 1단계 클라이언트의 파라미터 읽기 params=json.loads(request.body) id=params["id"] userID=params["userID"] done=params["done"] # 2단계 서버에서의 처리 # 여기서 데이터베이스 작업 이외의 작업을 한다면, # 별도의 클래스를 만들어서 처리하고 리턴받아서 다음 작업을 수행 # id에 해당하는 데이터를 찾아서 done의 값을 수정하는 것이다. # get은 하나만, filter는 여러개 return todo=Todo.objects.get(id=id) todo.done=done # 수정한 날짜를 기록하고 싶어. todo.moddate=datetime.datetime.today() todo.save() # 3단계 응답 만들기 # 1개 줄거야? 아니면 전체 다 줄거야? todos = Todo.objects.filter(userID=userID) # Json 응답, list라는 키로 검색된 데이터를 list로 전달 return JsonResponse({'list': list(todos.values())}, status=status.HTTP_200_OK)
- 테스트를 동일하게 해보자.
- 잘 바뀌었다.
- 하지만 시간 관련 method가 우리가 원하는 그대로가 아닌 것 같다. 뭔가 손을 봐줘야 할 것 같다.
def delete(self, request): # 파라미터 읽기 params = json.loads(request.body) id = params["id"] # 데이터 가져오기 todo = Todo.objects.get(id=id) # 데이터 삭제하기 todo.delete() # 응답 만들기 todos = Todo.objects.all() # Json 응답, list라는 키로 검색된 데이터를 list로 전달 return JsonResponse({'list': list(todos.values())}, status=status.HTTP_200_OK)
- 이번에는 id만 받아와서 해당 id를 가진 데이터를 삭제하고, Todo의 모든 리스트를 보여주는 코드를 작성하였다.
- "id":3을 delete 하였을 때, 전체 list에서 id는 1, 2만 보이는 것을 확인할 수 있다. 즉, 데이터가 잘 삭제되었다.
- URL에 해당하는 메서드 호출 방법을 알아야 합니다.
- URL과 전송방식에 해당 하는 방법을 알아야 합니다.- client가 전송한 파라미터를 어떻게 읽을 것인지 알아야 합니다.
- 유효성 검사를 해야 합니다. (일반 프로그래밍 언어 로직)
-if userID == None : , else:
이런것도 가능- 데이터베이스 작업을 어떻게 할 것인지 (CRUD)
- 결과를 JSON으로 어떻게 전송하는지 알아야 합니다.
- CSRF 해결책
- CORS 해결책
- 비밀번호 암호화해서 저장하는 방법(복호화를 못하도록 해서 저장해야 함)
- JWT Token을 사용하는 방법
- 로깅하는 방법
- 구독과 게시를 만드는 방법(Ops를 한다면 중요합니다.)
- 데이터 모델링, SQL 최적화
- 네트워크, 보안
- 트래픽 분석
- Cloud 배포
- SW 공학(디자인 패턴, 아키텍처 패턴, 개발 방법론)
react사용을 위한 사전 준비
npm install --location=global yarn
)npx create react-app 앱이름
yarn create react-app 앱이름
cd 프로젝트 앱 명
yarn start
or npm start
npm install --save --legacy-peer-deps @material-ui/core
npm install --save --legacy-peer-deps @material-ui/icons
- npm list에 있는지 확인을 하였다.
// <<<Todo.jsx>>> // react.js 파일에서 export한 객체를 React로 받아서 사용한다. // {이름} 의 경우는 export한 객체에서 이름에 해당하는 것만 받아서 사용 // 하나로 묶여있어야 하는 것을 잊지 말자. import React from "react"; class ToDo extends React.Component{ render(){ return( <div className="ToDo"> <input type="checkbox" id="todo0" nmae="todo0" value="todo0"/> <label for="todo0">ToDo 컴포넌트 만들기</label> </div> ) } } export default ToDo;
이후, App.js를 맞게 수정해주자.
entry point 는 index.js이다. App.js는 메인화면이라 부른다.// <<<App.js>>> import logo from './logo.svg'; import './App.css'; import React from "react"; import ToDo from "./ToDo"; function App() { return ( <div className="App"> <ToDo/> </div> ); } export default App;
- props
- 상위 컴포넌트에서 넘겨주는 데이터, 읽기 전용- state
- 자신의 컴포넌트에서 생성한 데이터, 읽고 쓰기 가능
- react는 props나 state(인스턴스 변수)의 원본 데이터를 수정하지 않습니다.
복사본을 만들어 수정한 뒤에 다시 대입하는 형태로 작업을 합니다.
- Data를 주고 받는 것은 react가 하는 것이 아닌, JS가 합니다.
- React는 화면 출력만 담당합니다.
// react.js 파일에서 export한 객체를 React로 받아서 사용한다. // {이름} 의 경우는 export한 객체에서 이름에 해당하는 것만 받아서 사용 // 하나로 묶여있어야 하는 것을 잊지 말자. import React from "react"; class ToDo extends React.Component{ constructor(props){ // 상위 컴포넌트로부터 넘겨받은 데이터를 나의 props에 저장 super(props) //안에서 쓴다면 this.state={이름: 초기값, 이름: 초기값...} // this 는 인스턴스 안에 숨겨진 첫 번째 매개변수 // 왜 생성자에서 만드는거야? render 안에 넣으면 안되나? // 둘이 this.state 해도 되는건데? // 왜냐하면, instance 호출은 constructor 이다. // 얘가 아니면 다른곳에서 한다면 있는지 없는지 알 수 없음 // python 은 def __init__(): super()겠지 // 생성자를 만드는 이유 : 시작하자마자 무엇인가를 해야 한다면 // props는 읽기 전용이라 수정을 한다면, // state에 복사해서 사용해야 합니다. this.state={item:props.item} } //밖에다가 쓴다면 // state={이름:초기값,...} render(){ // render는 메서드, //메서드 안에서 인스턴스를 쓴다면 this를 붙여야 한다. // 안붙으면 없으면 그냥 만든다. return( <div className="ToDo"> <input type="checkbox" id={this.state.item.id} name={this.state.item.id} value={this.state.item.done}/> <label id={this.state.item.done}> {this.state.item.title}</label> </div> ) } } export default ToDo;
import './App.css'; import React from "react"; import ToDo from "./ToDo"; class App extends React.Component { constructor(props){ super(props); // 하나의 객체를 생성해서 state에 item이라는 이름으로 저장 this.state={item:{id:0, title:"hello React", done:true}}; } render(){ return( <div className="App"> <ToDo item={this.state.item}/> {/*props*/} </div> ) } } export default App;