될때까지

Study :: '깔끔한 파이썬 탄탄한 백엔드' 본문

학습/살이되고 뼈가되어라

Study :: '깔끔한 파이썬 탄탄한 백엔드'

랖니 2022. 4. 25. 23:18
728x90

p.49)

백엔드 API 개발자의 역할은 프론트엔드 시스템(혹은 다른 클라이언트 시스템)과 데이터를 실시간으로 주고받을 수 있는 기능을 구현하는 역할을 담당한다. 특히 많은 수의 동시 요청을 장애 없이 실시간으로, 그리고 최대한 빠른 속도로 처리할 수 있는 시스템을 구현하는 것이 백엔드 개발자의 중요한 역할이 된다.

 

p.52)

개발팀의 구성원들

- 기획자(Product Manager) : 개발하고자 하는 서비스를 정의하고 기획하는 역할을 담당하는 직군

- 디자이너(Designer) : 웹 시스템 개발에서 UI(User Interface) 및 UX(User Experience)를 구현하는 역할을 담당하는 직군으로, 프론트엔드의 눈에 보이는 부분, 그리고 사용자가 직접 경험할 수 있는 부분들을 사용자가 좋아하고 편리해 할 수 있게 디자인하는 역할

- 프론트엔드 개발자(Frontend Developer) : 프론트엔드 시스템을 구현하는 역할을 맡는 개발자

- 백엔드 개발자(Backend Developer) : 백엔드 시스템을 개발하는 역할을 맡는 개발자로, 크게 2가지 분야로 나눌 수 있다. 백엔드 시스템에서 좀 더 앞쪽 부분을 담당하는 API 개발을 담당하는 개발자, 그리고 백엔드 시스템에서 더 뒤쪽부분인 데이터 수집, 분석, 관리 등의 데이터 관련 시스템을 개발하는 개발자들로 나눌 수 있다.

- 데브옵스(DevOps) : 데브옵스는 "Developmet"와 "Operation"의 합성어로, 개발자가 시스템 개발뿐만 아니라 시스템 운영까지 담당하는 것을 이야기한다. 시스템 운영뿐만 아니라 빌드, 테스트, 배포 등 개발에서 배포되기까지의 과정을 자동화하여 전체적인 개발 사이클을 효율적으로 더 빨리 진행될 수 있는 개발환경을 구축하는 역할도 담당한다. 

- 풀스택 개발자(Full Stack Developer) : 프론트엔드 개발과 백엔드 개발 둘 다 가능한 개발자.

- 시스옵스(SysOp - System Operations) : 시스템 인프라스트럭처의 구현과 관리 및 운영을 담당하는 직군. 데브옵스와 다르게 실제 하드웨어를 다룰 수 있는 직군이다. 서버를 직접 설치하고 운영시키며, 그 외 물리적인 네트워크 구축 및 운영 등 시스템 인프라스트럭처 운영에 필요한 모든 부분을 담당한다. AWS등의 클라우드 서비스가 널리 사용되며 데브옵스가 발전함에 따라 예전보다는 시스옵스 팀에 대한 수요가 많이 줄어들고 있는 추세다.

- 데이터 사이언티스트(Data Scientist) : 데이터 분석에 필요한 알고리즘과 모델링의 구현을 담당하는 직군.

- 데이터 엔지니어(Data Engineer) : 데이터 사이언티스트와 함께 일하는 직군. 주로 데이터 사이언티스트가 데이터를 분석할 수 있도록 데이터를 정리하고 정석화시키는 시스템을 구현하는 역할을 담당한다.

- 테스터(Tester) : 시스템을 테스트하여 검증하는 역할을 담당하는 직군. 크게 2가지 역할로 구분된다. 하나는 QA(Quality Assurance)라고 불리는 테스터인데, 일반적으로 직접 손으로 테스트하는 메뉴얼 테스팅을 담당한다. 다른 하나는 테스트 자동화 시스템을 구현하는 테스터들이다.

 - 스크럼 마스터(Scrum Master) : 스크럼 개발론이 널리 사용되면서 새로 생겨난 직군. 개발팀들이 스크럼을 제대로 사용할 수 있도록 코치해 주고 이끌어 주는 역할을 하는 직군

 

p.62)

Flask는 파이썬으로 웹 애플리케이션을 구현할 때 사용되는 프레임워크다. "micro web framework" 즉 군더더기가 없는, 아주 가벼운 웹 프레임워크라는 이야기다. 

프레임워크는 특정 시스템을 구현하기 위해서 공통적으로 요구되는 기능들과 구조를 재사용이 가능하도록 구현해 놓은 것이다. 모든 웹 시스템은 소켓을 통해서 네크워크와 연결하여 외부 시스템으로부터 통신을 주고받을 수 있어야 한다. 모든 웹 시스템은 이러한 기능을 필수로 구현해야하는데, 이러한 기능은 이미 규격화되어서 시스템마다 각각 따로 구현해야 할 필요가 없다. 이미 구현되어 있는 코드를 재사용함으로써 개발자는 웹 시스템을 통해 제공하고자 하는 비즈니스 로직에만 집중할 수 있는 것이다.

프레임워크가 비슷한 개념으로 라이브러리가 있다. 프레임워크와 라이브러리는 둘 다 공통적으로 필요한 기능을 재사용이 가능하도록 구현해 놓아서 다른 개발자들이 필요에 의해 사용할 수 있도록 해 놓았다는 점에서는 동일하다. 둘의 차이점은, 라이브러리는 개발자가 자신의 코드 안에서 실행한다면, 프레임워크는 프레임워크가 개발자의 코드를 실행하는 개념이다. 즉 라이브러리는 개발자의 코드 안에 일부분으로 포함되어 개발자가 원하는 대로 사용이 가능하지만, 프레임워크는 프레임워크가 제공하는 틀 안에서 개발자가 필요한 로직을 구현하는 차이가 있다.

 

p.66)

새로운 패키지를 설치하기 전에 항상 파이썬 가상 환경을 실행시킬 것. 파이썬 가상 환경이 실행되고 있지 않은 상태에서 패키지를 설치하면 해당 패키지는 시스템에 설치되어 있는 파이썬에 종속되어 설치된다.

pip은 파이썬의 패키지 매니저다. pip을 사용하여 터미널 등의 커맨드라인 환경에서 간단하게 원하는 파이썬 패키지들을 설치할 수 있다.

 

p.68)

엔드포인트란 단순하게 API 서버가 제공하는 통신 채널 혹은 접점이라고 할 수 있다. 프론트엔드 서버 등의 클라이언트가 백엔드 API 서버와 통신할 때 엔드포인트에 접속하는 형태로 통신하게 된다. 각 엔드포인트는 고유의 URL 주소를 가지게 되며, 고유의 URL 주소를 통해 해당 엔드포인트에 접속할 수 있다.

일반적으로 각 엔드포인트는 고유의 기능을 담당하고 있다. 그리고 이러한 엔드포인트들이 모여서 하나의 API를 구성하는 것이다. 

ping 엔드포인트는 단순히 "pong"이라는 텍스트를 리턴하는 엔드포인트다. ping 엔드포인트는 주로 API 서버가 현재 운행되고 있는지 아니면 정지된 상태인지를 간단하게 확인할 때 사용된다. 이러한 기능을 하는 엔드포인트를 헬스 체크 엔드포인트라고 한다. API 서버에 접속하지 않고 해당 API의 정상 운행 여부를 간단하게 체크하는 엔드포인트다. 

 

p.69)

mkdir -p ~/Projects/api

mkdir 명령어는 리눅스 기반의 운영체제에서 새로운 디렉터리를 생성해 주는 명령어로 "Make Directory"의 약자. 그 다음에 나오는 -p 옵션은 디렉터리의 중간 경로에 해당하는 디렉터리가 존재하지 않으면 자동으로 생성하라는 뜻이다.

리눅스 기반의 운영체제에서 경로를 지정할 때 사용되는  ~는 해당 사용자의 홈 디렉터리를 뜻한다.

 

cd ~/Projects/api

cd 명령어는 터미널 커맨드라인상에서 다른 디렉터리로 위치를 변경할 때 사용하는 리눅스 명령어. "Change Directory"의 약자다.

++ 입력 : 'i'

++ 저장 후 나오기 : esc후 ':wq'

 

p.73)

로컬 호스트는 시스템이 실행되고 있는 해당 컴퓨터를 이야기한다. 로컬 호스트의 IP 주소는 127.0.0.1이다. 컴퓨터 환경에서는 자기 자신을 접근하는 경우가 굉장히 자주 있어서 운영 시스템에서 항상 고정된 호스트 이름과 IP주소를 제공한다. 그러므로 127.0.0.1 IP 주소는 예약된 IP 주소이며 인터넷상에서 일반 IP로는 쓰일 수 없다.

 

p.80)

[HTTP]

   HTTP는 HyperText Transfer Protocool의 약자. 웹상에서 서로 다른 서버간에 HTML(하이퍼텍스트 문서)를 서로 주고받을 수 있도록 만들어진 통신 규약이다. 웹상에서 네트워크를 통해 서버 사이에 통신할 때 어떠한 형식으로 서로 통신하자고 규정해 놓은 "통신 구조"라고 보면 된다. HTTP는 팀 버너스 리가 인터넷상에서 문서를 전송하기 위한 목적으로 발명했다. HTTP 통신 방식에는 2가지 특징이 있는데 하나는 요청(request)과 응답(response)방식이고, 또 다른 특징은 stateless다.

 

[HTTP 요청과 응답]

   HTTP는 기본적으로 요청과 응답의 구조로 되어있다. HTTP를 기반으로 통신할 때 클라이언트가 먼저 HTTP 요청을 서버에 보내면 서버는 요청을 처리한 후 결과에 따른 HTTP 응답을 클라이언트에게 보냄으로써 하나의 HTTP 통신이 된다. 그러므로 백엔드 API 시스템의 엔드포인트 구현도 기본적으로 HTTP 요청을 인풋으로 받아서 HTTP 응답을 아웃풋으로 리턴하는 구조로 구현을 하게 된다.

 

[stateless]

   state가 없다는 뜻으로, HTTP 통신에서 상태라는 개념은 존재하지 않는다. 각각의 HTTP 통신은 독립적이며 그 전에 처리된 HTTP 통신에 대해서 전혀 알지 못한다. HTTP 프로토콜이 stateless이기 때문에 서버 디자인이 훨씬 간단해지고, HTTP 통신들의 상태를 서버에 서 저장할 필요가 없으므로 여러 다른 HTTP 통신간의 진행이나 연결 상태의 처리나 저장을 구현 및 관리하지 않아도 된다는 장점이 있다. 하지만 stateless이기 때문에 HTTP 요청을 보낼 때 해당 요청을 처리하기 위해 필요한 모든 데이터를 매번 포함시켜서 요청을 보내야한다는 단점이 있다. 예를 들어서, 어떠한 HTTP 요청을 처리하기 위해서 해당 사용자가 로그인이 되어야한다고 가정을 해보자. 이미 그전의 HTTP 통신을 통해서 로그인을 했더라도 stateless이기 때문에 새로운 HTTP 통신은 그 전에 로그인했다는 사실을 알지 못한다. 그러므로 새로운 HTTP 요청을 보내기 위해서는 클라이언트가 사용자의 로그인 사실 여부를 기억하고 있어야 한다. 이러한 점들을 해결하기 위해 쿠키나 세션등을 사용하여 HTTP 요청을 처리할 때 필요한 진행 과정이나 데이터를 저장한다. 쿠키(클라이언트에 저장)는 웹 브라우저가 웹사이트에서 보내온 정보를 저장할 수 있도록 하는 조그만 파일을 말한다. 세션(서버에 저장)은 쿠키와 마찬가지로 HTTP 통신상에서 필요한 데이터를 저장할 수 있게 하는 매커니즘이다. 

 

[HTTP 요청 구조]

HTTP 요청 메시지는 크게 Start Line, Headers, Body로 구성되어 있다.

POST /payment-sync HTTP/1.1.   # 1 : Start Line

Accept : application/json      # 2 : Headers
Accept-Encoding : gzip, deflate
Connection : keep-alive
Content-Length : 83
Content-Type : application/json
Host : intropython.com
User-Agent : HTTPie/0.9.3

{ 		        	  # 3 : Body
	"imp_uid" : "imp_1234567890:,
    "merchant_uid" : "order_id_8765432",
    "status" : "paid",
}

 

1. Start Line

: 이름 그대로 HTTP 요청의 시작줄이다. 예를 들어 "search" 엔드포인트에 GET HTTP 요청을 보낸다면 해당 HTTP 요청의 start line은 다음과 같다. start line은 세 부분으로 구성되어 있음(HTTP 메소드, Request target, HTTP version)

>   GET /search HTTP/1.1

1) HTTP 메소드 : 해당 HTTP 요청이 의도하는 액션을 정의하는 부분.

HTTP 메소드 중 가장 널리 쓰이는 GET - 서버로부터 데이터를 받고자 할 때 / POST -  서버에 새로운 데이터를 저장하고자 할 때

2) Request target : 해당 HTTP 요청이 전송되는 목표 주소. 

3)HTTP version : 해당 요청의 HTTP 버전을 나타냄. HTTP 버전에 따라 HTTP 요청 메시지의 구조나 데이터가 약간 다를 수 있기 때문에 서버가 받은 요청의 HTTP version에 맞추어서 응답을 보낼 수 있도록 버전을 명시한다.

 

2. 헤더

: 헤더 정보는 HTTP 요청 그 자체에 대한 정보를 담고 있다. 헤더는 파이썬의 딕셔너리처럼 key와 value로 되어 있고 :로 연결된다. 예를 들어 google.com에 보내는 HTTP 요청의 Host 헤더의 경우 다음과 같이 표현된다.

>  HOST : google.com

 

3. Body

: HTTP 요청 메시지에서 body 부분은 HTTP 요청이 전송하는 데이터를 담고 있는 부분이다. 전송하는 데이터가 없다면 body부분은 비어있게된다. 

 

[HTTP 응답 구조]

HTTP 응답 메시지의 구조도 요청 메시지와 마찬가지로 크게 세 부분으로 구성되어 있음

1. Status Line

: 이름 그대로 HTTP 응답 메시지의 상태를 간략하게 요약하여 알려 주는 부분. 세 부분으로 구성되어 있음(HTTP Version, Status Code, Status Text)

>  HTTP/1.1 404 Not Found

1) HTTP Version

2) status code : HTTP 응답 상태를 미리 지정되어 있는 숫자로 된 코드로 나타내줌

3) status text : HTTP 응답 상태를 간략하게 글로 설명해주는 부분.

2. 헤더

3. Body 

 

[자주 사용되는 HTTP 메소드]

GET

: GET 메소드는 어떠한 데이터를 서버로부터 요청할 때 주로 사용하는 메소드다. 데이터의 생성,수정,삭제 등의 변경사항 없이 단순하게 데이터를 받아오는 요청이 주로 GET 메소드 요청이다. 주로 데이터를 받아올 때 사용되므로 해당 HTTP 요청의 body가 비어있는 경우가 많다.

POST

: GET과 다르게 데이터를 생성하거나 수정, 삭제 요청을 할 때 주로 사용되는 HTTP 메소드.

PUT

: POST 메소드와 비슷하게 데이터를 새로 생성할 때 사용되는 HTTP 메소드. POST와 중복되는 의미이므로 데이터를 새로 생성하는 HTTP 요청을 보낼 때 모든 데이터 생성 및 수정 관련한 요청은 다 POST로 통일해서 주로 사용한다.

DELETE 

: 삭제요청을 보낼 때 사용되는 메소드. PUT과 마찬가지로 POST에 밀려서 잘 사용되지 않는 메소드다.

 

[자주 사용되는 HTTP Status Code와 Text]

- 200 OK

- 301 Moved Permanently (HTTP 요청을 보낸 엔드포인트의 URL 주소가 바뀌었다)

- 400 Bad Request (요청에 포함된 인풋값들이 잘못된 값들이 보내졌을 때)

- 401 Unauthorized (HTTP 요청을 처리하기 위해서는 해당 요청을 보내는 주체의 신분 확인이 요구되는데, 확인할 수 없었을 때 보내는 응답 코드)

- 403 Forbidden (HTTP 요청을 보내는 주체가 해당 요청에 대한 권한이 없음을 나타내는 코드)

- 404 Not Found (HTTP 요청을 보내고자 하는 URI가 존재하지 않을 때 보내는 응답 코드)

- 500 Internal Server Error (내부 서버 오류로, HTTP 요청을 받은 서버에서 해당 요청을 처리하는 과정에서 서버 오류가 발생해서 요청을 처리할 수 없다는 코드..)

 

[API 엔드포인트 아키텍처 패턴]

1. RESTful HTTP API : API에서 전송하는 리소스를 URI로 표현하고 해당 리소스에 해당하고자 하는 의도를 HTTP 메소드로 정의하는 방식. 작 설명력이 가장 강한 장점이다. 엔드포인트의 구조만 보더라도 해당 엔드포인트가 제공하는 리소스와 기능을 파악할 수 있다.

2. GraphQL : 페이스북이 개발한 기술. REST 방식으로 구현한 API에도 문제가 있음. API의 구조가 특정 클라이언트에 맞추어져서 다른 클라이언트에서 사용하기에 적합하지 않게 된다는 점. GraphQL은 엔드포인트가 오직 하나고, 엔드포인트에 클라이언트가 필요한 것을 정의해서 요청하는 방식이다. 기존 REST 방식의 API와 반대라고 보면 된다.(서버가 정의한 틀에서 클라이언트가 요청하는 것이 아니라, 클라이언트가 필요한 것을 서버에 요청하는 방식)

 

p.126)

데이터베이스 시스템은 데이터를 저장 및 보존하는 시스템으로, 크게 2가지 종류가 있다. 관계형 데이터베이스(RDBMS, Relational Database Management System)와 비관계형 데이터베이스(Non-relational)가 있다.

[관계형 데이터베이스]

관계형 데이터 모델에 기초를 둔 데이터베이스 시스템이다. 대표적인 관계형 데이터베이스 시스템에는 MySQL과 PostgreSQL등이 있다. 관계형 데이터베이스에서 모든 데이터들은 2차원 테이블로 표현되고, 각각의 테이블은 컬럼과 로우로 구성된다. 각 로우는 저만의 고유키가 있고, 이 고유키를 통해 해당 로우를 찾거나 인용하게 된다. 관계형 데이터베이스에서는 한 테이블에서 다른 테이블의 특정 컬럼값을 연결시키기 위해 일반적으로 외래키를 사용한다. 

[테이블들의 상호 관련성 종류]

- 1:1 : 테이블A의 로우와 테이블B의 로우가 정확히 일대일 매칭되는 관계

- 1:many : 테이블A의 로우가 테이블B의 여러 로우와 연결되는 관계

- many:many : 테이블A의 여러 로우가 테이블B의 여러 로우와 연결되는 관계

[정규화]

관계형 데이터베이스에서 외부키를 사용해서 테이블들을 연결할 수 있다. 이로 인해서 데이터 값의 중복을 최소화하게 데이터를 구조화하는 프로세스를 정규화라고 한다.

[트랜젝션]

관계형 데이터베이스에서 중요한 기능 중 하나로, 일련의 작업들이 마치 하나의 작업처럼 취급되어서 모두 다 성공하거나 아니면 모두 다 실패하는 것을 말한다. 관계형 데이터베이스 시스템은 트랜젝션 기능을 보장하기 위해 ACID라는 성질을 가지고 있다. 원장성, 일관성, 고립성, 지속성을 의미하고 이 성질을 통해 트랜젝션 기능을 보장한다.

 

[비관계형 데이터베이스]

관계형 데이터베이스와 다르게 비관계형이므로 데이터들을 저장하기 전에 정의할 필요가 없다. 대표적인 NoSQL데이터베이스 시스템에는 MongoDB, Redis, Cassandra등이 있다.

 

[관계형 데이터베이스 시스템 VS 비관계형 데이터베이스 시스템]

관계형 데이터베이스 시스템은 주로 정형화된 데이터들이나 데이터의 완전성이 중요한 데이터들을 저장하는 데 유리하다.(ex, 전자상거래 정보, 은행 계좌 정보, 거래 정보 등) 비관계형 데이터베이스 시스템은 로그 데이터와 같은 비정형화 데이터, 완전성이 상대적으로 덜 유리한 데이터를 저장하는데 유리하다.

 

p.154)

SQLAlchemy는 ORM(Object Relational Mapper)이다. ORM이란, 관계형 데이터베이스의 테이블들을 프로그래밍 언어의 클래스로 표현할 수 있게 해주는 것을 말한다. 즉 클래스를 사용해서 테이블들을 표현하고 데이터를 저장, 읽기, 업데이트 등을 할 수 있게 해준다.

 

p.174)

사용자의 비밀번호는 DB에 저장할 때 외부의 해킹이나 내부의 인력에 의해 데이터베이스가 노출되었을 경우를 대비해서 암호화해서 저장해야한다. 사용자의 비밀번호를 암호화할 때는 복호화를 할 수 없는 단방향 해시함수가 일반적으로 쓰인다. 파이썬에서는 hashlib 모듈을 사용하여 단방향 해시 함수를 사용할 수 있다.

단방향 해시 암호 알고리즘들도 해킹이 가능하다. 가장 널리 사용되는 단방향 해시 암호 알고리즘 해킹 방법은 rainbow attack이다. 미리 해시 값들을 계산해 놓은 테이블인 rainbow table이라는 테이블을 먼저 생성해 놓은 후 해시 함수 값을 역추적해서 본래 값을 찾아내는 해킹방법이다. 해시 값을 복호화 하는게 아니라 사전에 가능한 영문과 숫자 그리고 기호 조합들로 구성된 다양한 스트링값들을연산한 후 그 값들을 미리 해시 암호화 해 놓은 후, 해시 값 끼리 매칭하는 방식.

해킹이 될 수 있기 때문에 단방향 해시 함수의 취약점들을 보완하기 위해 salting과 key stretching이라는 보완점들이 사용된다. 실제 비밀번호 이외에 추가적으로 랜덤값을 더해서 해시 값을 계산하는 salting, 단방향 해시 값을 계산한 후 그 해시 값을 또 해시, 또 해시 여러번 반복하는 방법이 키 스트레칭.

salting과 키 스트레칭을 구현한 해시 함수 중 가장 널리 사용되는 것이 bcrypt. bcrypt는 처음부터 비밀번호를 단방향 암호화하기 위해 만들어진 해시 함수다.

 

[access token]

사용자가 로그인에 성공한 후에는 백엔드 API 서버는 access token이라는 데이터를 프론트에 전송한다. 프론트엔드에서는 해당 사용자의 access tokne을 HTTP 요청에 첨부해서 서버에 전송한다. access token이 무엇인가?

stateless인 HTTP통신은 stateless다. 이 특징때문에 이전에 어떠한 HTTP통신들이 실행됐는 지 알지 못한다. 당연히 인증도 못한다. 그렇기 때문에 HTTP 요청을 처리하기 위해서 필요한 모든 데이터를 첨부해서 요청을 보내야한다. 로그인 정보도 HTTP  요청에 첨부해서 보내야지 API서버에서 해당 사용자가 이미 로그인 된 상태인 것을 알 수 있다. access token이 바로 로그인 정보를 담고 있는 것이다. API서버에서 사용자의 로그인 정보를 access token의 형태로 생성하여 프론트엔드 서버에 전송하면 프론트엔드 서버는 백엔드 서버로부터 전송받은 access token을 그대로 다시 백엔드 서버에 HTTP요청을 보낼 때 첨부해서 보내는 것이다. 그러면 백엔드 API서버에서는 프론트엔드가 보내준 access token을 통해 해당 사용자의 로그인 여부를 알 수 있다.

 

[JWT]

access token을 생성하는 방법 중 하나. JSON Web Token은 JSON데이터를 token으로 변환하는 방식이다. JWT는 세 부분으로 구성되는데 1)헤더는 두 부분으로 되어 있으며, 토큰 타입(JWT) 그리고 사용되는 해시 알고리즘을 지정한다. 2)payload는 JWT를 통해 실제로 서버 간에 전송하고자 하는 데이터 부분이다. 3)signature는 JWT가 원본 그대로라는 것을 확인할 때 사용되는 부분이다. 파이썬에서 JWT를 생성하고 복호화할 수 있게 해주는 라이브러리는 PyJWT가 있다. 

 

p.191)

여러 함수에서 공통적인 기능을 필요로 하는 경우에 decorator를 사용한다. decorator는 어떠한 함수를 다른 함수가 실행되기 전에 자동으로 먼저 실행될 수 있도록 해주는 파이썬 문법이다. decorator 함수는 함수를 리턴하는 함수다. 

 

p.273)

load balancer는 백엔드 서버들에게 전송되는 HTTP나 다른 종류의 네트워크 트래픽을 여러 서버들에 동일하게 분배해주는 역할을 한다. 하나의 서버가 모든 트래픽을 감당하는 게 아니라, load balancer가 HTTP요청을 먼저 받고 그 후 2개의 EC2 instance들에게 균등히 분배해줌으로써 만약 하나의 서버에 문제가 있어도 복구되는 동안 다른 서버가 트래픽을 감당해 줄 수 있게 된다.

 

p.284)

코드의 구조를 더 체계적, 효율적으로 구현하는 것을 코드의 아키텍처라고 한다.(이제까지 책에서는 app.py라는 하나의 파일에 모든 코드를 작성했었다. 논리적, 기능적으로 영역을 구분해서 코드를 관리하는 게 좋다.) 어떤 코드 아키텍처가 체계적이고 효율적인 아키텍처일까?

1) 확장성이 높은 구조로 코드를 구현하는 것이 중요하다. 2) 재사용성이 높아야 코드의 양도 적어지고 개발의 속도도 높아지며 코드 또한 더 안전하고 견고한 코드를 구현하기 쉽다. 3) 보수 유지가 쉬운 코드를 구현하기 위해서는 구조적으로 로직이 잘 정리가 되고 나뉘어 있어야 한다. 4) 어려운 로직을 쉽게 간단하게 구현하는 것이 좋은 개발자다. 코드의 가독성이 높아야한다. 5) unit test를 하기 쉬운 코드는 추상화가 잘 되어 있고, 한 가지 역할만 하는 코드다. 테스트 하기 쉬운 구조로 짜야 한다.

백엔드 API 코드에 가장 널리 적용되는 패턴 중 가장 널리 사용되는 좋은 패턴 중 하나는 레이어드 아키텍처 패턴이다. 각 모듈이 서로의 의존도에 따라 층층히 쌓듯이 연결되어서 전체의 시스템을 구현하기 때문에 레이어드 아키텍처 패턴이라고 불린다. 

presentation layer : 해당 시스템을 사용하는 사용자 혹은 클라이언트 시스템과 직접적으로 연결되는 부분이다. 웹사이트에서는 UI부분에 해당하고 백엔드 API에서는 엔드포인트 부분에 해당한다.

business layer : 실제 시스템이 구현해야 하는 로직들을 이 레이어에서 구현한다.

persistence layer : 데이터베이스와 관련된 로직을 구현하는 부분이다.

레이어드 아키텍처의 핵심 요소는 바로 단방향 의존성이다. 각각의 레이어는 오직 자기보다 하위에 있는 레이어에만 의존한다. presentation layer는 business layer에게 의존, business layer는 persistence layer에게만 의존한다. 반대로 business layer는 presentation layer에 대해 완전히 독립적이라는 이야기. persistence layer도 마찬가지.

또 다른 핵심 요소는 separation of concerns다. 레이어의 역할이 명확하기 때문에 비즈니즈 로직을 처리하기 위해서는 presentation은 business layer의 코드를 호출해서 사용해야 한다. 

레이어드 아키텍처의 구조로 코드를 구현하면 각 레이어가 서로 독립적이고 역할이 분명하므로 서로에게 끼치는 영향을 최소화하면서 확장하거나 수정하기 쉽게 된다. 각 레이어드가 완벽하게 분리되고 역할이 명확하니 코드의 확장성, 가독성, 재사용 가능성, 테스트 코드를 구현하기 쉽고 보수 유지하기 수월해진다. 

728x90