✅백엔드 웹 개발 : API = 클라이언트가 필요하는 데이터 반환
(웹) 클라이언트가 원하는 다양한 (웹) 데이터 (혹은 웹 페이지)를 1. 어떻게 2. 잘 반환할까?
- 어떻게 = 방법론(요청-응답을 처리하는 방법): Rest API, GraphQL, Queue, WebSocket, SSE등
- 잘 = 속도 + 가용성(요청-응답의 속도 및 대량 트래픽 커버
- 데이터 조회를 위한 데이터베이스 내 쿼리 수행 시 쿼리 효율에 따른 소요시간 축소
- 대량 트래픽에 기인한 데이터베이스 조회 시, 부담 축소 및 속도 향상을 위한 로컬 / 글로벌 캐시 도입
- 대량 트래픽에 따른 다중 데이터베이스 접속 시 동시성 처리
- 트랜잭션 도입: 직렬화가 가장 높은 수준 but 느림
- 동시성과 격리성은 trad off 관계
- MSA도 가용성을 높일 수 있음
✅백엔드 = 데이터 관리: 데이터에 대한 모든것(데이터에 대한 CRUD)
결제하기 버튼을 누르면 결제를 위한 정보를 조회하고, 실제 결제가 되었다는 사실을 저장
-> 어제 구매한 상품에 대한 배송지를 변경하고 싶다 -> 어떤 구매건이고, 어떤걸로 바꿀것인가요?
어떤 구매건 (URL): https://aaron.com/payments/13/update (구매한 결제 정보에 대한 ID)
어떤걸로 (변수): Path Variable, Query Parameter 혹은 JSON 형태의 Request Body
바꿀것인가요 (Method): POST
🔷직렬화 / 역직렬화: (웹 서버 기준) 외부 데이터 형태와 내부 데이터 형태 사이의 변환
백엔드 언어로만 직접 웹 서버를 만들면 얻게 되는 고통
- 어떤 요청이 들어왔는지 일일이 확인: 요청 매핑
- JSON 형태로 오는 Request 요청 데이터를 객체로 받기 위해 역직렬화 필요 = MessageConverter
- 객체인 Response 반환 데이터를 JSON으로 반환하기 위해 직렬화 필요 = MessageConverter
REST API를 통해 주고 받는 데이터
내부, 외부를 서버를 기준으로 구분한다면 ...
외부: 문자열(JSON)으로 전송
내부: 백엔드 프로그래밍 언어로 개발한 웹 서버에선 모든 데이터는 객체(Object)로 다뤄진다.
🔹직렬화(Serialization)
응답: 객체(2차원) -> HTTP Response Body JSON(1차원, String)
🔹역직렬화(Deserialization)
요청: HTTP Response Body JSON(1차원, String) -> 객체(2차원)
✅ 웹 어플리케이션 프레임워크 등장: 웹 서버 개발의 모든걸 제공
매우 간편하게 웹 어플리케이션 서버 개발을 할 수 있도록 돕는 프레임워크
🔷프레임워크 등장 배경
Java, C, C#, Ruby, Python 이런 언어는 근본이 어플리케이션 개발을 위한 언어로 , 웹과 전혀 상관없다.
웹 생태계가 커지면서 웹 서버로는 정적인 리소스만 반환이 가능하다보니 동적 웹 페이지 반환을 위해 어플리케이션이 필요하게 된다. -> WAS 등장 (웹 서버 + 어플리케이션)
이와 동시에 각 언어마다 웹 어플리케이션 개발을 위한 웹 개발 표준 기술들이 생겨나게 된다
🔹java같은 경우 웹 어플리케이션 개발을 위한 표준으로는 가장 유명한 Servlet이나 JSP
각 언어마다 웹 어플리케이션 개발을 위한 프레임워크를 가지고 있음. 아래는 예시
🔹Python: Django
🔹Java: Spring
🔹JS: Express.js
🔷웹 어플리케이션 프레임워크가 제공하는 기능
- RequestMapping: 어떤 요청에 다라 어떤 메서드(함수 혹은 로직)을 수행할 것인지
- Thread 관리: 요청을 처리하기 위한 Thread할당 및 관리, 데이터베이스 접속을 위한 Thread할당 및 관리
- 데이터베이스 동시성 제어: 대량 트래픽 발생 시 데이터베이스 조작에 대한 각 요청들 간의 동시성 제어 -> 요청에 대해서 줄 줄세우는 것
- Serialization / Desrerialization: 요청, 응답 시 어플리케이션의 객체와 클라이언트의 JSON 사이 변환
- Security: CORS 규칙 등에 대한 보안 관련 정의 및 처리
- Authentication / Authorization: 매 요청마다 해당 요청이 권한에 맞게 요청한건지 보안처리
💡라이브러리 VS 프레임워크 (개발의 제어권이 누구에게 있는가)
[라이브러리]
단일 문제 해결을 위한 단일 도구
- 상세 구현체를 제공하고, 개발자는 필요한 기능 사용을 위해 라이브러리를 가져와 코드와 합친다. -> 개발자는 자신의 코드와 라이브러리가 합쳐지도록 개별 설정 및 코딩 필요
- 라이브러리 사용법이나, 작동법을 알아야하고 라이브러리 연결하는 책임이 개발자에게 있다
- 즉, 개발자는 라이브러리 사용에 대한 책임과 모든 제어권을 갖는다 : 흐름 제어권 = 개발자 몫
[프레임워크(라이브러리 집합)]
다수 문제 해결을 위한 도구 집합
- 다수의 라이브러리 제공: 개발에 필요한 라입러리들을 한데 묶어, 개발 편의성 제공
- 다수의 인터페이스 제공: 개발을 위한 껍데기를 제공할 뿐 필요한 것은 직접 구현 혹은 라이브러리 교체
- 프레임워크는 껍데기만 주어지고 상세 구현체는 개발자가 직접 개발하거나, 다른 라이브러리들을 가져와 꽂는다. -> 프레임워크는 라이브러리를 편하게 바꿔쓸 수 있도록 공통 인터페이스 제공 -> 설정 파일에서 DB설정, 동기/비동기 선택, messageConverter(JSON, XML) 선택 등등
- 즉, 프레임워크는 라이브러리 사용에 대한 책임과 모든 제어권을 갖는다 : 흐름 제어권 = 프레임워크 몫
- IoC (Inversion of Control, 제어권의 역전) : 개발, 흐름 제어권이 개발자에서 프레임워크로 이동
프레임워크 무한한 자유도
스프링을 공부해본 입장에서 스프링을 공부할수록 스프링의 방대함에 놀랐다. 프레임워크는 아래 두가지를 제공하기에 공부할게 엄청 많아진다
🔹다수의 라이브러리 제공: 설정이 너무 다양한데, 뭘 만져야하나, 잘못 만지면 망가지지않을까
🔹다수의 인터페이스 제공: 어떻게 사용해야하지? 어떻게 동작하는거지? -> 공부할게 너무 많다
🔷웹 어플리케이션 프레임워크 동작 원리
1. pacage Manager
2. dababase
3. transaction
1. Pacage Manager: 라이브러리 버전 관리
- 스프링부트를 예로 들어보자 gradle.build파일에 수 많은 라이브러리를 정의하고 사용하고 있다. -> 프레임워크는 많은 라이브러리를 사용한다.
웹 어플리케이션이 제공하는 2가지
- 다수의 라이브러리: 개발의 편의성을 위한 다양한 라이브러리 제공
- 다수의 인터페이스: 개발을 위한 껍데기를 제공할 뿐 필요한 것은 직접 구현 혹은 라이브러리 교체
즉, 많은 수의 라이브러리가 필요하기에 아래 2가지 관리가 필요하다
- 어떤 라이브러리를 사용할지
- 어떤 버전을 사용할지
위 2가지 관리를 해주는게 Pacagke Manager이다.
각 언어에서 사용하는 Pacakge Manager
🔹JS: npm (semver 형식 버전표시를 한다)
🔹Python: pip
🔹Ruby: bundler
🔹Java: Maven or Gradle
2. Database: 데이터 조회 및 조작
CRUD: 데이터 조회 및 조작
동적 데이터를 저장하는 저장소이기에 데이터를 식별할때는 무조건 ID를 사용
🔹동적 데이터는 뭐다? 매번 바뀐다. 따라서 데이터가 바뀌더라도 고유의 ID로 일관적인 조회 가능하도록 해야함
[심화] 고유 식별자 설정에 관한 내용
[고유 식별자: UUID, CUID]
AutoIncrement ID: 2가지 문제 존재
1. 개수 제한: 최대 Long을 넘어서는 개수 표현 불가
2. 추적 가능: 해커와 같은 악의적인 유저가 ID 숫자를 기반으로 다른 자원들에 대한 추론 / 접근 가능
🔹성능: 작은 앱에서는 충분한 성능으로 채택할만한 ID채번 방식
UUID(Universally/Globally Unique Identifier)
- 개수 제한: 128bit로 사실상 무한 개수 표현 가능
- 순서 비보장: 키 그 자체로 의미(Semantic)을 갖기 못함 (이게 크니까 저거보다 나중에 생성됐네.. 이런 의미를 갖지않는다는 얘기)
- 길이: 너무 길고, 순서 보장이 되어 있지 않아 해당 키 값 기반으로 인덱싱을 할 때 어려움
- 충돌(Collision Resistance): 유사난수(Pseudo-Random)로 키 생성 시 충돌 가능성 매우 낮다
CUID (Collision-Resistant Unique Identifier) : 분산 시스템에서 적당한 옵션
- 순서 보장(Monotonically Increasing) -> UUID의 순서 비보장으로 인한 인덱싱 문제 해결
- 길이: UUID보다 짧아 졌다.
NanoID
- 순서 보장이 굳이 필요없지만, CUID보다 짧은 아이디를 원하는 경우 사용
ID Generator 중 Snowflake
- 트위터와 같은 대량의 코멘트, 라인과 같은 대량 메세지에 적합
- 라인 세미나: 메신저의 액티브 유저는 2억명이고, 하루 40억개의 메시지가 발행된다
- 글로벌 유니크 + 선형으로 커지는 ID(순서, Monotonically Increasing) + 개별 백엔드에서 ID 생성
- 단 시스템 간에 의존하는 위험이 있다
- 분산 시스템 내 모든 인스턴스가 같은 시스템 시간이 보장되어야한다. -> 같은 시간이 보장이 안되면? ID가 꼬이겠지?
- 메시지가 발생될땐 ID가 없고, 서버에서 메시지를 받았을 때 ID 채번, 그 ID를 다시 클라이언트에게 전송
3. Transaction
대량 트래픽이나, 다수 요청이 데이터베이스에 접근 -> 동시성 제어
- 다수의 웹 서버에서(대량 트래픽) -> 단일 데이터베이스에 접속 시, 충돌(서로 데이터베이스 쓰겠다고 싸움)
- 이중화(로드밸런싱) 하기도함
- 이중화 데이터베이스: 읽기만을 위한 데이터베이스, 쓰기만을 위한 데이터베이스를 나눠서 로드밸런싱
- 읽기 전용 데이터베이스는 데이터 변경이 일어나지 않으므로 여러개 생성 가능
- 쓰기 전용 데이터베이스는 데이터 변경이 일어나면 동기화를 진행해야하므로 비용, 시간 등등 자원이 나가므로하나만 생성
- 이중화(로드밸런싱) 하기도함
- 하나의 웹 서버에서 다수의 요청이 -> 단일 데이터베이스에 접속 시, 충돌(서로 데이터베이스 쓰겠다고 싸움)
✅API
API: Application Programming Interface 어플리케이션 사용을 위한 인터페이스
프로그램(어플리케이션) 혹은 웹 서버에서 어떤 요청을 보내면 어떤 응답을 받을 수 있는지에 대한 스펙
🔹추상 = 사용 스펙: 프로그램(어플리케이션) 혹은 웹 서버 사용법(어떤 요청 시 -> 어떤 응답 반환 합니다)
🔹구체 = 상세 로직 : 어떤 요청 시 -> 어떤 응답을 반환하기 위한 방법은 수없이 많고, 유저는 신경 쓸 필요 없다
'ASAC 웹 풀스택' 카테고리의 다른 글
[ASAC 6기] 웹 개발이란 무엇이며, 어떻게 동작하나? BE(3) - Infrastructure, 물리서버 vs 클라우드 서버 (3) | 2024.08.27 |
---|---|
[ASAC 6기] 웹 개발이란 무엇이며, 어떻게 동작하나? BE(2) - OS개요 및 프로그램 동작 원리 (0) | 2024.08.27 |
[ASAC 6기] 웹 개발이란 무엇이며, 어떻게 동작하나? FE(4) - Rendering Pattern (1) | 2024.08.24 |
[ASAC 6기] 웹 개발이란 무엇이며, 어떻게 동작하나? FE(3) - Javascript 프레임워크 동작 원리 (0) | 2024.08.21 |
[ASAC 6기] 웹 개발이란 무엇이며, 어떻게 동작하나? FE(2) - JS엔진, JS엔진 비동기 처리 (0) | 2024.08.20 |