주백개그이 - 발표자료

Before start

note:
저 링크들을 오가면서 발표를 진행할 것임. 라운지에 링크 올리고 발표 시작하자.


주백개그이?

Pasted image 20230720224508.png|200x200

note:


django

django.png


Data Modeling

db|200

note:
CRUD 예제는 ER 다이어그램을 토대로 admin site에 가서 확인해 보는 것이 좋겠다.


REST API

Pasted image 20230721023656.png|200

note:
bookstore 깃허브 페이지 가서 DRF


Authentication & Authorization

Pasted image 20230721023821.png|200


Securities

Pasted image 20230721023921.png|200

note:
이런게 있다 정도만 가볍게


DevOps

jeff.jpg|200

note:
척 보면 척 하게 되는 과목이라 그렇게 심각하게 다룰 필요는 없음. 다만 내용이 너무 많으니까


잠깐! ✋

note:
책 순서와 발표 순서가 뒤죽박죽이라는 것을 눈치챘을거다. 괜찮다. 이 책은 비선형으로 진행이 되기 때문에 그때그때 찾아가며 읽으면 되는 책으로 만들었다. 따라서 이 책을 완독할 의무또한 없다.


![Pasted image 20230721235931.png](/img/user/docs/assets/Pasted%20image%2020230721235931.png)

Framework

as a web server

note:


![Pasted image 20230721235931.png](/img/user/docs/assets/Pasted%20image%2020230721235931.png)

image41 1.png
note:
장고는 주어진 설계대로 App을 제작하여야 하며, App 별로 MVT 패턴을 적용하여야 함.


![Pasted image 20230721235931.png](/img/user/docs/assets/Pasted%20image%2020230721235931.png)

MVT

Model, View, Template

note:
장고 백엔드와의 통신규약.


![Pasted image 20230721235931.png](/img/user/docs/assets/Pasted%20image%2020230721235931.png)

Application

![Pasted image 20230721235931.png](/img/user/docs/assets/Pasted%20image%2020230721235931.png)

note:


![Pasted image 20230721235931.png](/img/user/docs/assets/Pasted%20image%2020230721235931.png)
class SignupForm(UserCreationForm):
    class Meta:
        model = User
        fields = ["email", "nickname", "password1", "password2"]

note:


![Pasted image 20230721235931.png](/img/user/docs/assets/Pasted%20image%2020230721235931.png)

routing.png

note:
RESTful한 리소스 구분을 위한 Routing.

urlpatterns가 라우팅을 수행함. 프로젝트에도 있고, 각 앱에도 있어서 들어오는 요청에 따라 구체적인 App의 urlpatterns에게 요청을 전달하는 일종의 게이트웨이와 같은 기능을 하고 있음을 보여준다.

라우팅이 성공적으로 진행되면 view에서 로직을 처리하고 웹에 응답을 보낸다.


![Pasted image 20230721235931.png](/img/user/docs/assets/Pasted%20image%2020230721235931.png)
GET http://13.209.22.220/products/book/

core/urls.py

urlpatterns = [
    path("products/", include("products.urls")),
]

![Pasted image 20230721235931.png](/img/user/docs/assets/Pasted%20image%2020230721235931.png)
GET http://13.209.22.220/products/book/

products/urls.py

urlpatterns = [
    path('book/', book_list, name='book_list'),
]

![Pasted image 20230721235931.png](/img/user/docs/assets/Pasted%20image%2020230721235931.png)
GET http://13.209.22.220/products/book/

proejcts/views.py

def book_list(request):
    books = Product.objects.all()
    for book in books:
        url = str(book.image)
        url_without_query = url.split('?')[0]
        book.image = url_without_query
    return render(request, 'book_list.html', {'books': books})

![db.png](/img/user/docs/assets/db.png)

Database

Relational Database

Data Modeling

Entity Relationships

note:
Data Modeling 챕터는 바로 들어가기에 앞서 이 개념의 위치 파악에 힘을 써야 한다. 데이터베이스는 사실 윈도우 파일 시스템도 데이터베이스라고 불리울 수 있을 정도로 일반적인 개념.

Relational database(RDB)는 Key와 Value의 관계를 테이블화한 데이터베이스

Key 덕분에 서로 연관성 있는 테이블을 연결할 수 있게 되는데, 여기에서 데이터 모델링이 튀어나오는 것.

데이터 모델링에는 개념 / 논리 / 물리 모델링이 있는데, 우리가 흔히 "DB 다이어그램"이라고 부르는 단계는 개념 + 논리 모델링을 아우른다. 우리는 이 단계에만 집중한다.


![db.png](/img/user/docs/assets/db.png)

Entity

erDiagram
	User {
		id
		email
		nickname
		hash
	}

note:
엔티티는 고유하게 식별할 수 있고 독립적으로 존재 가능한 개체이다.


![db.png](/img/user/docs/assets/db.png)

Attribute


![db.png](/img/user/docs/assets/db.png)

Relationship


![db.png](/img/user/docs/assets/db.png)

Django Models

products/models.py


REST

RESTful?

note:
REST는 웹을 망가뜨리지 않으면서 설계를 변경하기 위해 고안된 규약. HTML 문서, 엔티티 등의 리소스를 접근하기 위해 계층적인 경로를 가짐.

메서드(동사)를 통해 리소스 명시와 이에 따른 동작을 분리할 수 있게 됐다. 덕분에 쌩판 처음 보는 요청을 접해도 직관적으로 유추할 수 있게 되었다.


REST

GET /books


REST

POST /books


REST

/deleteBooks

note:
책을 추가하는 동작(동사)가 URI에 정의


REST

/books/getAllBooks

note:
book 이라는 단어 중복사용


REST

Request & Response

note:
ch.10 요청과 응답 참고바람.

REST는 웹과 함께 성장했기에, HTTP는 REST이다.


REST

Pasted image 20230722091947.png|500

request header

note:
우리가 눈여겨 볼 것은 바로 헤더와 바디. 일단 헤더 먼저 보자.

위의 이미지는 요청의 헤더이다.


REST

Pasted image 20230722092200.png|600

response header

note:
다음은 응답 헤더를 의미.


REST

Pasted image 20230722092343.png
Pasted image 20230722092405.png
Pasted image 20230722092504.png

note:
바디는 Content-Type이 정의한 대로 간다. 이미지 왼쪽에서부터 각각 HTML, JS, JSON


REST

DRF

note:

모든 구성을 DRF으로 변경할 수는 없었다. 우리 프로젝트 중 user, cart 부분만 DRF으로 작업했다.


REST

serde.png
note:

DRF는 장고 앱 중의 하나로, Serialization, Deserialization을 지원한다.

DRF는 객체, dictionary, QuerySet 등등 장고에서 다룰 수 있는 모든 데이터를 직렬화, 역직렬화 할 수 있다. 직렬화의 결과로 JSON을 채택했으며 (JSON만 있는 건 절대로 아님) JSON은 데이터를 바이트 스트림으로 인코드, 디코드할 수 있다.

그러면 일반 오브젝트는 바이트 스트림으로 바로 변환이 안되냐? ㅇㅇ


REST

users/serializers.py

class UserSerializer(serializers.ModelSerializer):
    password1 = serializers.CharField(required=True, write_only=True)
    password2 = serializers.CharField(required=True, write_only=True)
    
    class Meta:
        model = User
        fields = ['email', 'nickname', 'password1', 'password2']
        extra_kwargs = {
            'password1': {'write_only': True},
            'password2': {'write_only': True}
        }

note:
다음은 UserSerializer의 코드 일부를 가져왔다. 모양이 상당히 Form과 닮았다. 맞다. Form처럼 사용할 수도 있다. 사용자가 <form> 태그에 이메일, 닉네임, 비밀번호를 적어 회원가입을 할 때 Form이 아니라 Serializer에 의한 JSON이 날아온다.


REST

users/serializers.py

class UserSerializer(serializers.ModelSerializer):
# continue
    def validate(self, attrs):
        attrs = super().validate(attrs)
        password1 = attrs.get('password1')
        try:
            password_validation.validate_password(password1)
        
        except DjangoValidationError as error:
            raise serializers.ValidationError({'password1': error})

        return attrs

users/views.py

def signup(request):
    if request.method == 'POST':
        serializer = UserSerializer(data=request.data)
        try:
            serializer.is_valid(raise_exception=True)
            serializer.save()
            return Response({'success': True, 'message': '회원가입이 완료되었습니다.', 'redirect': '/users/signin/'})
        except serializers.ValidationError as error:
            
            errors=''
            if 'email' in error.detail and 'password1' not in error.detail:
                errors = error.detail.get('email', [])
                errors = errors[0] if len(errors) > 0 else ''
                
            if 'password1' in error.detail and 'email' not in error.detail:
                errors = error.detail.get('password1', [])
                errors = errors[0] if len(errors) > 0 else ''
            return Response({'success': False, 'errors': errors}, status=status.HTTP_400_BAD_REQUEST)
    return render(request, 'signup.html')

note:
validate 라는 메서드는 우리 form.is_valid 할 때와 같은 API를 가지고 있다.


![Pasted image 20230721023821.png|200](/img/user/docs/assets/Pasted%20image%2020230721023821.png)

Authentication

Authorization

note:
인증과 인가.

인증은 사용자 신원을 확인하는 절차, 인가는 인증된 사용자에게 적절한 권한을 부여.


![Pasted image 20230721023821.png|200](/img/user/docs/assets/Pasted%20image%2020230721023821.png)
# 사용자 객체 반환
user = authenticate(request, username=username, password=password)

# 로그인 실패 시 HttpResponse 반환
login(request, user)

logout(request)

# Boolean 반환
if request.user.is_authenticated:

note:
사용자 모델을 AbstractUserAbstractBaseUser를 사용한 경우, 기본 내장 인증함수를 손쉽게 사용할 수 있다.


![Pasted image 20230721023821.png|200](/img/user/docs/assets/Pasted%20image%2020230721023821.png)

django-allauth

note:
구글 로그인 구현을 해보자. ch 9.4를 참조

  1. settings.py 설정
  2. 클라이언트 등록 및 발급
  3. admin-site에서 사이트 등록
    1. Sites
    2. Social applications

![Pasted image 20230721023821.png|200](/img/user/docs/assets/Pasted%20image%2020230721023821.png)

JWT

JSON Web Token

note:
JWT는 쿠키와 같이 인증인가를 할 수 있는 여러 방법 중 하나임. 각각의 장단점이 명확하게 있어 무엇이 더 좋은지 논의하는 건 의미가 없음.


![Pasted image 20230721023821.png|200](/img/user/docs/assets/Pasted%20image%2020230721023821.png)
{
	"alg": "SHA256",
	"typ": "JWT"
}

![Pasted image 20230721023821.png|200](/img/user/docs/assets/Pasted%20image%2020230721023821.png)

Payload

{
	"iss": true,
	"admin": true,
	"name": "Choi Wheatley"
}

![Pasted image 20230721023821.png|200](/img/user/docs/assets/Pasted%20image%2020230721023821.png)

Signature

Pasted image 20230722095824.png|700

https://jwt.io


![Pasted image 20230721023921.png|200](/img/user/docs/assets/Pasted%20image%2020230721023921.png)

Security


![jeff.jpg](/img/user/docs/assets/jeff.jpg)

EC2


![jeff.jpg](/img/user/docs/assets/jeff.jpg)

S3


![jeff.jpg](/img/user/docs/assets/jeff.jpg)

RDS


![Docker_Logo.jpg](/img/user/docs/assets/Docker_Logo.jpg)

Docker

내 컴퓨터에서는 되는데?

note:
컨테이너 기반의 오픈소스 가상화 플랫폼. 가상머신이 아니라 프로세스로 작동하기 때문에 가벼움.

컨테이너란, 파일 시스템, 시스템 자원, 가상 네트워크를 아우르는 독립된 공간을 의미함.


![NGINX-logo-rgb-large.png](/img/user/docs/assets/NGINX-logo-rgb-large.png)

Nginx

web server, not web application

note:
웹 서버로 사용되는 nginx는 정적 HTML 문서들을 매우 빠른 속도로 호스팅 하는 용도 외적으로도 리버스 프록시, 부하분산, 캐싱, SSL 오프로딩, HTTP/2 지원 등 다양한 역할을 수행할 수 있는 다재다능한 서버이다.


![NGINX-logo-rgb-large.png](/img/user/docs/assets/NGINX-logo-rgb-large.png)

Gateway

nginx/default.conf

note:
우리팀은 nginx를 게이트웨이로 사용하고 있다. default.conf 파일을 보면 http 프로토콜의 기본 리스닝 포트인 80을 받아다 장고 웹앱으로 보내는 작업을 하고 있다.


![NGINX-logo-rgb-large.png](/img/user/docs/assets/NGINX-logo-rgb-large.png)

entrypoint.sh

note:
배포단계의 장고앱은 runserver를 호출하지 않는다! nginx가 장고 앱을 호출한다고 했지만 그 사이에 gunicorn이라는 미들웨어가 runserver같은 역할을 수행하는 걸로 알고 있지만 책에는 넣지 않았다.