-
Notifications
You must be signed in to change notification settings - Fork 8
24.10.02 개발 지식 공유
식당에 딱 들어갔을 때 안내해주는 데스크 직원이라고 생각하시면 됩니다.
- 웹 개발에서의 Web server의 역할은 정적 페이지를 전달해주는 역할입니다.
- 예전 UPCY 구성한거 보면 백엔드에 Nginx 껴있습니다.
- 이 Nginx를 넣은 이유는 사용자와 서버가 웹으로 소통하기 위해 HTTP 프로토콜을 사용하는데, 이걸 받아서 전달해주려면 사용자의 요청을 안내해주는게 필요합니다. 그 역할을 Nginx가 수행합니다.
- 근데 지금은 제가 빼놓았습니다. 그 이유는...
- 정적파일 배포 필요 X -> 저희 서버는 현재로서는 오로지 JSON 상하차를 위한 서버입니다. 정적 파일은 앱에서 다 제공합니다.
- nginx는 리버스 프록시 기능(특정 경로로 들어오면 특정 포트로 이동시키는 것이라고 간단하게 이해하시면 됩니다), 로드밸런싱(부하분산)을 제공하는데, 이걸 AWS ALB가 똑같이 제공해줍니다.
- 제가 UPCY 말고 다른 프로젝트에서는 Nginx를 제가 구성해놓았는데, 그 프로젝트는 연구실 컴퓨터를 서버로 해서 하나의 컴퓨터에 react, django, ai모델이 다 들어가야합니다. 클라우드 서비스도 안쓰기로 했구요.. 그래서 nginx 사용해서 웹 서버를 만들어놓았습니다. << 이런 경우에 주로 사용한다! 정도로 생각하시면 될 것 같아요
오픈형 주방 보면, 홀 직원이 주문을 받아서 주방장에게 "이모 돈까스 하나요~~"라고 들어보셨을건데, WSGI가 딱 그 역할입니다. 웹 서버로부터 전달받은 요청을 웹 Application으로 전달해줍니다.
- Web server gateway interface
- UPCY에서 사용하고 있는 WSGI는 이전에는 uvicorn이었는데, 지금은 gunicorn으로 바꾸어놓은 상태이고,
- 나중에 gunicorn + uvicorn 합쳐서 제공할 생각입니다.
- 자세한 동작과정은 저도 몰라요.. 찾아봐야할것같네요
실제 음식을 만들어서 내놓는 곳입니다.
- Django, FastAPI, Flask, Spring Boot, Ruby on Rails같은 우리가 잘 아는 백엔드 프레임워크가 바로 Web application입니다.
- 실제 비즈니스 로직(요구사항을 구현하는 로직)을 처리하고, 데이터베이스와 직접적으로 상호작용하는 곳입니다. << 음식을 만드는 곳!
식당의 재료 창고라고 생각하시면 됩니다.
- 음식을 만들때도 재료가 없으면 아무것도 못하는것처럼, 백엔드도 데이터가 없으면 뭐 의미있는 데이터를 내놓기가 힘듭니다.
- PostgreSQL, MySQL, SQLite 같은 RDBMS도 있고,
- MongoDB같은 NoSQL같은것도 있습니다. << 이건 저도 안써봤는데 나중에 한번 써봤으면 좋겠네요!
Monolithic : 그냥 우리가 아는 식당 MSA : 휴게소 푸드코드
- 저희가 지금 개발하는 프로젝트는 Monolithic (모든 요구사항을 백엔드 하나의 어플리케이션에서 처리)입니다.
- 제가 지금 연구실에서 하는 프로젝트는 약간 MSA 방식인데, 웹 Application 역할을 하는 백엔드 Django가 하나 있고, 어떤 요청을 수행하기 위해서 AI Model들에 들렀다 와야합니다.
- 이 AI Model들에도 FastAPI라는 프레임워크를 달아서 Django의 요구사항을 처리하도록 구성했습니다.
인터넷 세계에서 사용자(Client)와 서버간 데이터를 주고받기 위해 고안된 프로토콜
진짜 간단하게 설명하자면,
- 클라이언트의 Request -> Server의 Response 방식으로 동작합니다 << 좀 익숙하시죠?
- HTTP는 Stateless 프로토콜인데, 요청간 Client의 상태를 서버에 저장을 안합니다. 다시 말해서 한번 요청할때마다 서버 입장에서는 너가 누구냐? 이러는겁니다.
- Stateless
- Connectionless -> 요청을 보내고 응답을 받으면 연결을 끊습니다.
- Flexible -> HTTP는 Hyper Text Transfer Protocol인데, 한국어로 바꿔보면 텍스트를 초월하는것을 전송하는 프로토콜입니다. 이게 뭐냐? 텍스트 뿐 아니라 다양한 형식의 데이터를 주고받을 수 있다는 겁니다 (이미지, json, HTML, ...) << 혹시나 해서 그런건데 HTML이랑 HTTP랑 다른겁니다!!!
- 1번과 2번에서 설명했듯이, HTTP는 Stateless입니다. 사용자가 누군지 요청마다 알지 못합니다.
- 그러면 어떻게 현대 웹 서버에서는 사용자를 기억해서 페이지 커스터마이징이라던지, 장바구니 기능이라던지,... 이런 기능을 제공할 수 있을까요??
- 이 의문은 아래 소개하는 방법을 통해 해결할 수 있습니다.
Client의 브라우저에 저장되는 데이터
- 서버가 쿠키를 Client에게 발급해주고, 사용자가 이 쿠키를 들고 HTTP 통신을 할때마다 보여주면, 서버 입장에서는 이게 누군지 알 수 있게 됩니다.
- 주로 사용자 Preference나 보안, 데이터 무결성을 보장하기 위해 사용한다고 합니다.
- 실제로 저는 이전 프로젝트에서 인증 기능을 Cookie + JWT 사용해서 했습니다.
Server에 이 사용자를 저장하는 방법
- Session을 사용하게 되면 Session ID라는 값이 Client에게 쿠키로 전달됩니다. 그리고 서버도 이정보를 어딘가에 저장합니다.
- 서버에 사용자 정보를 저장하기 때문에, Client측에서 만약 Session ID를 변경한다면 이걸 가지고 정상적으로 인증을 수행할 수 없게 됩니다.
- 이 방법의 단점이 있는데, 웹페이지 사용자가 늘어나면 늘어날수록 서버에서 이 사용자를 계속 찾아서 검증해야 하니까 부하가 더 걸린다는 점을 들 수 있습니다.
Json Web Token 이건 실제로 본인이 jwt.io 들어가서 까보면서 이해하는게 더 좋다고 생각합니다.
- 지금 저희 프로젝트에서 사용하는 방식입니다.
- 이게 세션 방식의 단점이 있다보니까 똑똑한 개발자들이 고안해낸 방법이라고 알고있습니다.
- 이 방식은 Token 형식으로, 서버측에 저장할 필요도 없고 Cookie처럼 사용자가 들고 있다가 서버에게 보여주는걸로 인증을 수행하는 방식입니다.
- 주로 RESTful API와 함께 가장 많이 쓰는 방식입니다.
- 일반적으로 JWT는 Base64Url 방식으로 인코딩됩니다.
- Header.Payload.Signature 형식으로 이루어져 있습니다.
- xxxxx.yyyyy.zzzzz
{
"alg": "HS256", # 어떤 알고리즘으로 서명했는지?
"typ": "JWT" # 이게 어떤 타입인지? << 일반적으로 Value로 "JWT"를 사용합니다.
}
Claims : 엔티티의 정보(사용자의 정보)및 추가적인 정보 데이터라고 생각하면 됩니다. claim에도 세가지 종류가 있는데, registred, public, private이 있습니다.
- 필수는 아닌데, 권장되는 사전 정의한 Claim 정보로, 유용한 정보가 담겨있습니다. iss : 발급자 exp : 만료시간 sub : 주제 aud : 청중
- JWT 사용하는 사람들이 자유롭게 정의하는 Claim인데, 저도 이건 잘 모르겠네요..
- 여기에 저희가 담아야 할 사용자 정보 데이터가 들어갑니다.
- 사용자 정보를 담을때도 진짜 최소한의 정보만 담는게 좋다고 합니다.
- 그래서 settings.py를 보면, claim에 user_id만 담겨있는걸 볼 수 있습니다.
- Django가 실제로 발급한 jwt 까서 확인해보시는게..?
이 서명 부분을 통해 이게 변조된 토큰인지 아닌지 서버에서 확인하게 됩니다.
- 주로 >> 인코딩된 Header + 인코딩된 Payload + SecretKey(아까 말했던 그겁니다) << 이 방식으로 수행하고,
- 여기에 마지막으로 Header에서 지정한 alg (위에서는 HS256)으로 암호화합니다.
- 이걸 signature 부분에 담게 됩니다.
어쨌든 이렇게 구성되어 있기 때문에, 사용자가 토큰을 들고 서버에 들어오면, 이 토큰을 내가 발급한건가? 체크를 수행하게 됩니다.
근데 이 토큰이 내가 발급한건지 어떻게 알까요? --> 주로 Secret key를 사용해서 확인합니다.
Django를 예로 들면, settings.py에 DJANGO_SECRET_KET가 있는걸 확인할 수 있는데, JWT 발급 시 이걸 사용합니다.
따라서 Django가 Header에 Authorization Bearer : token 형식으로 jwt가 들어오면, 이걸 내가 발급한건지 확인하고 맞으면 들여보내주고, 틀리면 401 Unauthorized라던지 400 Bad request 라던지 HTTP 상태 코드를 반환해줍니다.