Skip to content

%%
주니어 백엔드 개발자에게 필요한 기초 지식이랄게 무엇이 존재할까?

  • 장고를 사용한 프로젝트를 진행하며 겪은 다양한 에피소드를 엮어보자.
    • 그래서 장고가 뭘 해주는데
    • 가상환경, 패키지, 프로젝트 시작
    • 장고로 만드는 App, Form, View, Model, Template
  • 데이터 모델링
    • 데이터 모델링이니까 개념, 논리 모델링 중점적으로 다루자.
    • 장고 CRUD 코드와 비교 가능?
  • REST 기본 개념
    • URI 설계
    • Request & Response
    • DRF
  • 인증과 권한 (Authentication & Authorization)
    • OAuth: allauth 활용예시 위주로 + 에러 트래킹
    • JWT
  • 보안
    • CSRF
    • SSL/TLS
    • Input Validation
    • CORS: 에러처리 챕터 참조
    • HTTPS
  • DevOps: 뭐가 뭔지 대충 아는 식으로
    • ec2
    • s3: S3 에러트래킹
    • rds
    • docker
    • nginx

이게 보니까 순서가 완전 뒤죽박죽이네. 이대로 두고 비선형 방식으로 책을 그때그때 찾아 읽기 위해 작성했다고 의도를 설명하자.

Top Down Approach
%%

Before start#

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


주백개그이?#

Pasted image 20230720224508.png

note:
- "주니어 백엔드 개발자, 그 이상으로" 라는 뜻 - 구체적으로 예상독자의 수준을 제목에서부터 함의 → 비전공자 X, 초보자 X


django#

django.png

  • 장고가 뭘 해주는데
  • Model Template View
  • App, Form, Routing

Data Modeling#

db|200

  • 개념, 논리, 물리 모델링 (ER 다이어그램)
  • Django CRUD 예제와 같이

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


REST API#

Pasted image 20230721023656.png + RESTful한 URI 설계 + Request & Response + DRF 리팩토링한 결과 함께 보기

note:
bookstore 깃허브 페이지 가서 DRF - users/serializers.py - users/view.py


Authentication & Authorization#

Pasted image 20230721023821.png + 인증? 인가? + Django의 인증, 인가 + OAuth: allauth 모듈 활용 중심 소셜 로그인 + JSON Web Token


Securities#

Pasted image 20230721023921.png + CSRF + SSL/TLS + Input Validation + CORS + HTTPS

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


DevOps#

jeff.jpg + EC2 + S3 + RDS + Docker + Nginx

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


잠깐! ✋#

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


Pasted image 20230721235931.png

Framework#

as a web server

note: - 장고는 웹 서버이고, 웹 애플리케이션임. 프레임워크로써 이미 설계가 된 대로 장고 백엔드 (서버 백엔드 X)와 통신을 해야함.


Pasted image 20230721235931.png

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


Pasted image 20230721235931.png

MVT#

Model, View, Template

note:
장고 백엔드와의 통신규약. - Model: DB관리, ORM 기능 지원 - View: 비즈니스 로직 구현, MVC 패턴의 View와 Controller를 모두 View가 담당함. - Template: HTML + Django Template Backend => 동적으로 HTML 생성


Pasted image 20230721235931.png

Application#

Pasted image 20230721235931.png

  • models.py
  • views.py
  • urls.py
  • ...

note: - MTV 패턴을 구현하는 하나의 단위인 APP, 장고는 다음과 같은 파일로 구성되어 있다.


Pasted image 20230721235931.png

class SignupForm(UserCreationForm):
    class Meta:
        model = User
        fields = ["email", "nickname", "password1", "password2"]

note: - 백엔드 개발자가 프론트도 겸해야 할 때 쓰는 Form,


Pasted image 20230721235931.png

routing.png

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

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

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


Pasted image 20230721235931.png

GET http://13.209.22.220/products/book/

core/urls.py

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

Pasted image 20230721235931.png

GET http://13.209.22.220/products/book/

products/urls.py

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

Pasted image 20230721235931.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

Database#

Relational Database#

Data Modeling #

Entity Relationships

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

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

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

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


db.png

Entity#

erDiagram
    User {
        id
        email
        nickname
        hash
    }

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


db.png

Attribute#


db.png

Relationship#


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

request header

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

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


REST

Pasted image 20230722092200.png

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

Authentication#

Authorization#

note:
인증과 인가.

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


Pasted image 20230721023821.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

django-allauth#

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

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

Pasted image 20230721023821.png

JWT#

JSON Web Token

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


Pasted image 20230721023821.png

{
    "alg": "SHA256",
    "typ": "JWT"
}

Pasted image 20230721023821.png

Payload#

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

Pasted image 20230721023821.png

Signature#

Pasted image 20230722095824.png

https://jwt.io


Pasted image 20230721023921.png

Security#

  • OAuth
  • SSL/TLS
  • Input Validation
  • HTTPS
  • CORS

jeff.jpg

EC2#


jeff.jpg

S3#


jeff.jpg

RDS#


Docker_Logo.jpg

Docker#

내 컴퓨터에서는 되는데?

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

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


NGINX-logo-rgb-large.png

Nginx#

web server, not web application

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


NGINX-logo-rgb-large.png

Gateway#

nginx/default.conf

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


NGINX-logo-rgb-large.png

entrypoint.sh

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