* 프로그래머스, 타입스크립트로 함께하는 웹 풀 사이클 개발(React, Node.js) 5기 강의 수강 내용을 정리하는 포스팅.
* 원활한 내용 이해를 위해 수업에서 제시된 자료 이외에, 개인적으로 조사한 자료 등을 덧붙이고 있음.
백엔드라고 종합해서 말은 하지만, 세부적으로 백엔드의 진입점 / 정적 파일 / 데이터베이스 연결 / 설정 / 미들웨어 / 템플릿 등등.. 백엔드 구성에 필요한 폴더와 파일들이 많기 때문.
따라서 적절한 구조가 설계되지 않는다면, 백엔드 전체의 유지보수성과 가독성 그리고 확장성 측면에서 문제를 유발할 위험성이 커지게 된다.
대강 이렇게 하면 된다는 예시.
상황이나 필요에 따라서 세부적인 부분 혹은 전체 구조 자체가 달라질 수 있다.
프론트엔드 예시이긴 하지만, 컴포넌트 / 라우터 / 모델 등의 기존 구조를 벗어난 기능 분할 설계(FSD)라는 아키텍처라는 개념도 존재한다.
project-name/
├── bin/
│ └── www # 서버 실행 파일
├── node_modules/ # 의존성 모듈
├── public/ # 정적 파일 (CSS, 이미지 등)
│ ├── images/
│ ├── javascripts/
│ └── stylesheets/
├── routes/ # 라우트 정의
│ ├── index.js
│ └── users.js
├── controllers/ # 컨트롤러 (비즈니스 로직)
├── models/ # 데이터베이스 모델 정의
├── middlewares/ # 공통 미들웨어
├── views/ # 템플릿 파일 (ejs, pug 등)
├── app.js # 앱 초기화 및 설정
├── package.json # 프로젝트 메타데이터 및 의존성
└── README.md # 프로젝트 설명
예: controllers/usersController.js에서 사용자 데이터 처리 로직 작성.
예: 인증 미들웨어, 로깅 미들웨어 등.
굳이 이렇게 나누는 까닭은 결국 모든 파일들은 목적이나 기능별로 나누어져야 하기 때문.
공통적으로 사용하는 로직(예: 인증, 로깅)은 미들웨어로 분리하여 가독성과 유지보수성을 향상시킬 수 있고..
controllers와 services를 분리하면 컨트롤러는 요청-응답 핸들링만, 서비스는 비즈니스 로직만 담당하게 되면서 마찬가지로 효율성이 향상되게 된다.
이전 포스팅 - 프론트엔드 아키텍처의 그것과 비슷한 개념.
현존하는 아키텍처들을 몇 개 들어보자면..
project/
├── models/ # 데이터베이스와 관련된 로직
├── views/ # 템플릿 엔진(예: EJS, Pug)으로 사용자 인터페이스를 렌더링
├── controllers/ # 요청과 응답을 처리하는 로직
├── routes/ # 경로 설정
├── public/ # 정적 파일
├── app.js # 앱 초기화
project/
├── routes/ # 경로 설정
├── controllers/ # 요청과 응답 핸들링
├── services/ # 비즈니스 로직
├── models/ # 데이터베이스와 관련된 로직
├── middlewares/ # 공통 미들웨어
├── app.js # 앱 초기화
const userService = require('../services/userService');
exports.getUser = async (req, res) => {
const userId = req.params.id;
const user = await userService.getUserById(userId);
res.json(user);
};
const UserModel = require('../models/userModel');
exports.getUserById = async (userId) => {
return await UserModel.findById(userId);
};
project/
├── src/
│ ├── entities/ # 핵심 비즈니스 로직 (순수 JS)
│ ├── usecases/ # 애플리케이션 비즈니스 규칙
│ ├── interfaces/ # 컨트롤러 및 외부 통신
│ ├── frameworks/ # Express, DB 등 외부 프레임워크 의존성
│ └── config/ # 설정 파일
├── app.js # 앱 초기화
Entities: 도메인 로직만 포함.
Usecases: 비즈니스 규칙.
Interfaces: HTTP 요청 처리.
project/
├── routes/ # 프리젠테이션 계층
├── controllers/ # 프리젠테이션 계층
├── services/ # 도메인 계층
├── models/ # 데이터 계층
├── app.js # 앱 초기화
비즈니스 로직 분리: 컨트롤러와 서비스/모델을 분리해야 한다.
미들웨어 활용: 인증, 로깅과 같은 공통 로직은 미들웨어로 구현해야한다.
코드 재사용성: 공통 로직과 유틸리티 함수는 별도 디렉터리로 관리해야한다.
위 3개 원칙은 항상 준수할 것.
평문(Plain Text, 사람이 읽을 수 있는 데이터)을 읽을 수 없는 암호문(Cipher Text)으로 변환하는 과정.
데이터를 보호하여 허가되지 않은 접근으로부터 정보를 안전하게 유지하기 위함.
쉽게 말하자면, 회원가입 기능을 통해 회원 정보를 DB에 저장했다고 가정해보자.
그런데 비밀번호를 입력한 값 그대로 저장해버리면? 혹여나 DB가 유출되거나 하는 문제가 생겼을 때 돌이킬 수 없는 사태가 벌어질 수도 있다.
외부에 노출되었을 때 보안 문제를 일으키는 민감한 정보라고 하면, 값 자체를 암호화하는게 안전한 방법.
암호문(Cipher Text)을 평문(Plain Text)으로 되돌리는 과정.
암호화된 데이터를 원래의 형태로 변환하여 올바른 사용자만 읽을 수 있게 한다.
위 예시를 계속해보자면.. 로그인 기능을 구현했을 때 DB에는 암호화된 비밀번호만 저장된다. 사용자가 입력한 비밀번호는 원본이기 때문에 DB의 암호화 비밀번호를 다시 풀어서 사용자가 입력한 비밀번호와 대조해주어야 한다.
암호화 알고리즘.
데이터를 안전하게 보호하기 위해 사용되는 수학적 규칙과 절차.
일개 개인이 알고리즘을 만들어서 사용한다는건 현실적으로 불가능하다.
외부 공격에 안전한 알고리즘을 만드는 것부터 난관이고, 혼자 만들어봐야 다른 사람들이 널리 사용해주지 않으면 존재 가치가 없다.
결국 더 똑똑하고 부지런한 사람들이 만들어둔 훌륭한 방법을 가져다가 사용하면 된다.
아래는 암호화 알고리즘 예시. 어디서 한번 정도 들어본 방법들이 하나 정도는 보일 것이다.
현재 가장 널리 사용되는 대칭 암호화 알고리즘.
128, 192, 256비트 키 길이를 지원.
오래된 알고리즘으로, 현재는 보안 취약점 때문에 비추천.
DES를 3번 적용한 방식으로 보안을 강화했지만, 속도가 느림.
속도가 빠르고 유연한 키 길이를 제공하지만, AES에 밀려 사용이 줄어듦.
비대칭 암호화의 대표적인 알고리즘.
긴 키 길이를 통해 강력한 보안 제공.
RSA보다 더 짧은 키로 동등한 보안을 제공.
모바일 환경 등 리소스 제약이 있는 곳에서 사용 증가.
안전한 키 교환을 위한 알고리즘.