본문 바로가기

캡스톤 설계 [건물별 소통 플랫폼 BBC]/기술 스택 및 아키텍처

백엔드 기술스택 및 아키텍쳐

백엔드

Language : TypeScript

Library & Framework : NestJS, Express.js

Test: Jest ,Supertest

Database : Mysql,erdcloud , DataGrip

ORM : TypeORM

Authentication: passport.js, JWT, 세션

Proxy Sever : Nginx

.

.

.

 

 

우선 이번 백엔드 파트에서 사용할 언어 및 프레임워크, 인프라들이다.

파트 별로 왜 해당 언어 와 프레임워크 인프라들을 사용했는지를 기록해보자.

.

.

.

.

.

Language : TypeScript

JavaScript에 타입을 추가한 언어

 

- 정적 타입 시스템

  변수, 매개변수 및 함수 반환 값에 대한 타입을 명시적으로 지정할 수 있어 코드의 가독성을 높이고 버그를 미리 예방.

- 코드 예측 및 자동 완성

   코드 작성을 돕는 개발 도구와 통합되어 있어, 코드 예측과 자동 완성 기능을 제공해서 빠르게 코드를 작성하고 실수를 줄인다.

- 타입 추론

변수의 타입을 자동으로 추론할 수 있어서 타입 지정의 번거로움을 줄여주고 필요한 경우 수동으로 타입을 명시할 수도 있다.

- 유지 보수 용이성

정적 타입 검사를 통해 코드 변경으로 인한 예기치 않은 오류를 방지하므로 유지 보수가 용이하다.

- 강력한 생태계

TypeScript는 JavaScript 생태계와 통합이 잘 되어 있으며, 수많은 라이브러리와 프레임워크에서 지원하고 있다.

.

.

.

.

+ TypeScript 이슈 체크

현재 TypeScript가 퇴출될 가능성에 대해 대두 되고 있다.

그 원인은  데이비드 하이네마이 한슨(루비온레일즈를 만듬 )이라는 사람이

터보에서 타입스크립트가 퇴출 된다는 블로그 포스팅을 올렸다.

이미 해당 깃허브 터보 레포지토리에는 타입스크립를 제거한 뒤 마지까지 시킨 상태이다.

또한 Svelte4(프론트엔드 프레임워크)에서도 타입스크립트를 버린다고 한다.

위 사진과 같이 이미 해당 레포지토리에는 좋아요 보다 싥어요가 압도적으로 많은것을 알수 있다.

즉, 이미 너무 많은 사람들이 거부를 하고 있다는 것이다.

 

또한 Svelte4에서는 Svelte를 사용하는 과정에서 타입스크립트를 사용하지 못하게 한다는게 아니라

Svelte 개발하는 개발자들이 타입스크립트가 아닌 자바스크립트로 개발을 한다는 것이 과하게 소문이 난것 이었다.

즉, Svelte를 사용하는 일반 프론트엔드 개발자에게는 아무런 영향이 없는 이야기 인 것이다.

 

결론 : TypeScript를 사용안할 이유가 없다.

 

위 통계 자료는 rollbar 에서 정리한 자바스크립트로 개발한 프로젝트에서 가장 많이 발생한 에러 TOP10이다.

 

결론적으로 타입에러가 가장 많이 나기 때문에 저 통계자료 하나로만 봐도

TypeScript의 사용은 필수불가결하다.

 

.

.

.

.

 

 

Library & Framework : NestJS, Express.js

TypeScript를 사용하여 서버 사이드 애플리케이션을 빌드하기 위한 프레임 워크

 

- 모듈 기반 아키텍처

모듈 기반의 구조를 채택하여 애플리케이션을 컴포넌트로 나눌 수 있어 코드의 모듈화와 재사용성을 높일 수 있다.

- 의존성 주입

의존성 주입(Dependency Injection)을 지원하므로 클래스 간의 의존성을 쉽게 관리할 수 있어 테스트 가능한 코드 작성 용이.

- 강력한 모듈 기능

 라우팅, 컨트롤러, 서비스, 프로바이더 및 미들웨어를 하나로 묶는 기능을 제공하여 코드를 체계화하고 유지 관리에 용이.

- 편리한 에러 처리

편리한 에러 처리 기능을 제공하여 애플리케이션에서 발생하는 예외를 처리하고 적절한 응답을 생성할 수 있도록 도와준다.

- GraphQL 및 WebSockets 지원

RESTful API 뿐만 아니라 GraphQL 및 WebSockets를 지원하여 다양한 통신 프로토콜에 대한 서비스를 구축할 수 있다.

- 설계 및 테스트 용이성

 모듈화된 구조와 의존성 주입을 통해 코드 설계와 테스트가 용이하며, 테스트 가능한 코드 작성이 쉽다.

- 확장성

NestJS는 강력한 확장성을 가지고 있어서 큰 규모의 애플리케이션을 구축하고 유지 관리할 수 있다.

아래와 같이 컨트롤러, 서비스, 레포지토리, 인터페이스 단으로 나누어 모둘별로 개발 하였다

 

 

깃허브 스타의 history을 보면  nest의 스타 상승률이 압도적으로 높은걸 확인할 수 있다.

현재 2023.09.19일 기준 이미 djandgo를 제외하고는 스타수가 가장 많은것 또한 확인할 수 있다. 

 

 

Django 장단점

(장점)

파이썬 라이브러리 사용 가능

기본적인 기능들을 미리 만들어 제공해 쉽고 빠르게 개발

FullStack 가능

 

(단점)

파이썬 기반이다보니 속도가 느리다

세세한 조정이 힘들다

Django ORM 사용할 있다는

Full System 지식이 필요하다는

 

NestJS /단점 

(장점)

Express, Fastify 호환된다는

TypeScript, OOP, FE 등이 지원된다는

좋은 아키텍쳐와 구조를 가지고 있어 처음부터 시작하지 않아도 된다는

 

(단점)

아키텍쳐로 인한 러닝커브

NodeJS 비해 strict 구성(NodeJS 철학 : 간결함과 실용주의)

출처 : https://velog.io/@sinichy7/Django-vs-NodeJS-vs-NestJS

 

현재 내가 NEST를 선택한 가장 큰 이유

1. 프론트엔드와 같은 언어(타입스크립트)로 개발

2. 이전 node(express)를 사용한 경험이 있다.

3. 국내 대기업에서 사용 압도적 1위인 spring과 비슷한 디자인 패턴

 

 

 

.

.

.

ORM : TypeORM

TypeScript와 JavaScript를 위한 객체 관계 매핑(ORM) 라이브러리로, 

데이터베이스와의 상호 작용을 추상화하고 객체 지향적으로 다룰 수 있게 해주는 도구

 

- 객체 지향적 접근

 데이터베이스 테이블과 데이터를TypeScript 클래스와 객체로 매핑해줌으로써 데이터베이스 작업을 객체 지향적으로 수행.

- 다양한 데이터베이스 지원

다양한 데이터베이스 시스템을 지원하며, MySQL, PostgreSQL, MongoDB, 등과 같은 데이터베이스와 통합이 가능하다.

- 타입 안전성

TypeScript와 함께 사용할 때 TypeORM은 타입 검사를 통해 런타임 오류를 사전에 방지해 줌으로써

코드의 안정성을 높이고 버그를 줄여준다.

- 강력한 쿼리 빌더

 SQL 쿼리를 생성하는 빌더를 제공하여 복잡한 쿼리를 쉽게 작성하고 실행할 수 있다.

- 데이터베이스 마이그레이션

데이터베이스 스키마를 버전 관리하고 마이그레이션하는 기능을 제공하여

데이터베이스 스키마를 업데이트하고 유지 관리하기 용이하다.

- 관계 지원

 다양한 유형의 관계(일대일, 일대다, 다대일 등)를 지원하며, 데이터 간의 복잡한 관계를 쉽게 모델링할 수 있다.

- 확장성

 확장 가능하며, 사용자 지정 리포지토리, 리스너, 플러그인 등을 통해 기능을 확장할 수 있다.

- 커뮤니티 및 문서:

활발한 개발 커뮤니티와 풍부한 문서를 가지고 있어서 개발자들이 도움을 받고 문제를 해결하기 쉽다.

아래 같이 총 15개의 엔티티를 구성하여 데이터 베이스를 ORM 으로 관리를 하였다.

 

 

위 장점들과 더불어 모든 쿼리를 sql로 짜면 코드량도 길어질 뿐더라 가독성도 좋지 않다고 느끼는 현재의 나에게는 

백엔드와 프론트엔드 두 파트 모두 같은 언어인 TypeScript를 사용하고 있어

쿼리 언어 또한 TypeScript문법을 그대로 사용하여 진행하면 개발 속도와 디버깅에 도움이 되어서 사용

.

.

.

.

 

Authentication: passport.js, JWT,

passport.js

Node.js 웹 애플리케이션에서 인증을 관리하기 위한 미들웨어. 

다양한 인증 전략(예: 로컬, 소셜 미디어, OAuth)을 제공하며,

개발자에게 인증 프로세스를 간소화하고 보안을 강화하는 도구를 제공.

 

 - 모듈러 및 확장 가능

Passport.js는 다양한 전략을 지원하므로 원하는 인증 방법을 선택하고 필요에 따라 쉽게 확장할 수 있다. 

- 보안

사용자 인증 및 세션 관리를 처리하여 보안을 강화하며, 민감한 사용자 데이터를 안전하게 보호한다. 

- 유연성

웹 애플리케이션에서 다양한 인증 및 인가 요구 사항을 처리할 수 있으므로 개발자가 원하는 방식으로 사용자를 관리할 수 있다

.

.

.

 

구글 로그인과 카카오 로그인등과 같이 소셜 로그인 두개 정도를 같이 연동할 계획이 있기에

다양한 인증 전략을 제공하며 가장 많은 사용량을 가지고 있는 passport 미들웨어를 사용하기로 하였다.

.

.

.

.

JWT

인증(Authentication). : 로그인

=> 사이트에 가입된 회원임을 즉, 특정 서비스에 일정 권한이 주어진 사용자임을 아이디랑 비밀번호를 통해서 인증을 받는것

 

인가(Authorization)

==> 한번 인증을 받은 사용자가 이후 서비스의 여러기능을 사용할 때 매번 로그인 되어있음을 알아보고 허가 해주는것.

예) sns에 로그인(인증)을 한뒤 내 계정의 사용자으로'만' 할 수 있는 활동을 할 때 sns 서비스가 내가 로그인됨을 인지하는것

.

.

 

우선 인가에는 2가지 세션 방식과 JWT 방식이 대부분의 서비스에서 활용이 되고 있다.

 

셰션

사용자가 로그인에 성공하면 서버는 '세션 표딱지'란걸 출력한다.

그리고 그것의 반은 브라우저에 보내고 반은 메모리에 넣어 놓는다. (상황에 따라 하드디스크에 넣거나 데이터베이스에 넣는다)

.

.

그러면 브라우저는 이 딱지를 Seesion ID란 이름의 쿠키(브라우저에 저장되는 정보)로 저장하고

브라우저는 앞으로 해당 사이트에 요청을 보낼때 마다 이 표를 실어서 요청을 보낸다.

그리고 브라우저에서 온 반쪽 세션을 서버에서 비교 대조 한뒤 맞으면 인가를 해주는것이다.

.

.

세션의 허점 : 메모리상에 저장할 경우 서버가 꺼지는 상황이나 에러가 발생하면 휘발성인 메모리는 세션이 모두 날아가서

모든 사용자들이 로그인을 다시 해야한다. 또한 사용자가 여려명이 동시 방문하면 메모리가 부족해 진다.

또한 하드디스크나 데이터베이스에 저장할 경우 속도도 너무 느려진다.

보통 레디스나 memcashed같은 메모리형 데이터베이스 서버에 두기도 하지만 첫 허점과 같이 에러나 서버가 꺼지면 모두 날아간다.

더군다나 서버여러대를 거쳐 진행되는 서비스일 경우 로직이 꼬이는불상사도 일어난다.

.

.

이 모든 허점을 보안하지 위해서 나온게 JWT이다.

참고로 브라우저가 아닌 ios나 안드로이드같은 어플리케이션에는 쿠키가 없어 jwt를 사용해야 한다.

.

.

.

.

JWT

jwt는 로그인을 하면 반쪽짜리 표를 주는것이 아니라 전체(토큰)를 다 보내준다.

즉, 서버가 무언가를 저장 하지 않는다.

토큰은 인코딩 또는 암호화된 3가지 데이터를 이어 붙인 형태이다.

빨간색(header), 보라색(payload), 파란색(verify signature)로 구분이 된다.

.

.

payload를 디코딩해보면 json 형식으로 여러 정보들이 있다.

이 토큰들이 누가 누구에게 발급을 했는지, 언제까지 유효한지,

서비스가 사용자에게 이 토큰을 통해 공개하기 원하는 내용( 사용자의 닉네임, 관리자 여부 등등)

하지만 간단히 bas64rul로 인코딩한 방식이기에 변조와 조작의 가능성이 높은 우려가 있다.

이를 위해 헤더와 시그니처가 있다.

.

.

header에는 타입과 알고리즘의 종류 2가지가 들어간다 타입은 늘 JWT가 들어며

알고리즘에는 3번 시그니처(서명값)을 만드는데 사용될

알고리즘이 지정된다.

그리고 '헤더'와 '페이로드' 그리고 '서버에서 감춰놓은 비밀키' 이 셋을 암호화 알고리즘에 넣고 돌리면 3번 시그니처(서명값)이 나온다.

또한 암호화 알고리즘은 한쪽 방향으로는 계산이 돼도 반대쪽으로는 안되서 서버만 알고있는 비밀값을 알 방법이 없어 안전하다.

.

.

즉, 요청이 오면 클라이언트에서 보낸 토큰에서 헤더와 페이로드를 뽑아 서버에서 가지고 있는 비밀키를 조합해서

클라이언트에서온 시그니처(서명값)과 같은지 확인해서 인가를 판단한다.

즉 stateless 하다. 반대로 세션은 stateful하다.

 

.

.

.

하지만 세션을 대체하기에 jwt도 결점이 있다.

세션처럼 stateful해서 모든 사용자들의 상태를 기억하고 있다는건 구현하기 부담되고 고려사항도 많지만,

이게 되기만 하면 기억하는 대상의 상태들을 언제든 제어할 수 있다는 의미다.

.

.

예를 들어

1. 한 기기에서만 로그인 가능한 서비스를 만들려는 경우 pc에서 로그인한 상태의 어떤 사용자가 핸드폰에서 또 로그인하면

pc에서 로그아웃 되도록 기존 세션을 종료할 수 있는 것이다.

2. 특정 유저 쫒아내기

3. 로그인된 모든 디바이스를 보여주는데 원치 않는 디바이스에서 강제로 로그아웃을 할 수 있다.

4. 계정 공유숫자를 체크할 수 있다.

.

.

.

.

 

위와 같은 세션과 JWT토큰의 특징과 장단점을 비교해 보았을 때

결론적으로 한 계정에서 여러 사용자들의 로그인에 대한 컨트롤이 필요 없으며

모바일 애플리케이션까지의 확장을 고려하면 JWT가 가장 적합한것 같아서 JWT를 사용해서 인가를 하기로 결정 !

 

.

.

.

.

Proxy Sever : Nginx

오픈 소스로 제공되는 웹 서버 및 리버스 프록시 서버 소프트웨어

 

- 성능

Nginx는 경량이면서 고성능 웹 서버로 알려져 있으며, 다수의 동시 연결 및 요청을 처리할 수 있어 정적 콘텐츠를 빠르게 제공하고 부하 분산을 위한 우수한 성능을 제공.

- 리버스 프록시

Nginx는 리버스 프록시로 사용되어 백엔드 서버로 요청을 전달하고 응답을 다시 클라이언트에게 보내는 역할을 할 수 있어 애플리케이션 서버의 로드 밸런싱과 보안을 강화할 수 있다.

- 정적 콘텐츠 서빙

정적 파일 (예: HTML, CSS, JavaScript, 이미지)을 빠르게 제공하는 데 특히 뛰어나서 높은 성능과 효율성을 유지하면서 대규모 트래픽을 다룰 수 있다.

- 가벼움

Nginx는 리소스 사용이 적으며 메모리 효율적으로 동작한다. 

따라서 서버 자원을 효율적으로 활용하면서도 빠른 응답 시간을 유지한다.

- 모듈 지원

Nginx는 다양한 모듈을 지원하여 사용자 정의 기능을 추가할 수 있다.

이러한 모듈을 통해 고급 웹 서버 및 애플리케이션 요구 사항을 충족시킬 수 있다.

- 보안

Nginx는 보안 기능을 내장하고 있어 DDoS 공격 및 웹 어플리케이션 보안을 강화할 수 있다. 

  • 방화벽: Nginx를 사용하여 요청을 필터링하고 악성 트래픽을 차단.
  • SSL/TLS: HTTPS를 지원하고 SSL/TLS 인증서를 관리하여 데이터 보안을 유지.
  • 접근 제어: 웹 리소스에 대한 접근 제어 및 인증을 구현할 수 있다.

.

.

.

Test: Jest ,Supertest

 

테스트 관련 기술 스택은 아직 공부해보지 못했지만 가장 많은 사용량과 레퍼런스가 있는

Jest ,Supertest를 선택.