본문 바로가기

Server Programming/JavaScript

Nest.js

반응형

클라이언트/서버 구조를 구현하기 위해 사용하는 프로토콜 혹은 아키텍쳐

  1. REST API
  2. 웹 소켓
  3. RPC
  4. GraphQL

REST API, 웹소켓, RPC, GraphQL은 모두 서버와 클라이언트 간의 통신을 위해 사용되는 프로토콜이나 아키텍처입니다. 각기 다른 장단점과 사용 사례가 있습니다. 아래에서 각각의 차이점을 설명하겠습니다.

REST API (Representational State Transfer)

  1. 아키텍처 스타일: 클라이언트와 서버 간의 상태 정보를 주고받는 구조. 자원(Resource)을 URI로 표현하며, HTTP 메서드(GET, POST, PUT, DELETE)를 사용하여 자원을 처리.
  2. 데이터 형식: 주로 JSON이나 XML을 사용.
  3. 장점:
    • 표준화된 HTTP 프로토콜 사용.
    • 캐시를 통해 성능 향상 가능.
    • stateless 특성으로 인해 확장성과 신뢰성 높음.
  4. 단점:
    • 자원 간의 복잡한 관계를 처리하기 어려움.
    • 다수의 요청이 필요한 경우 비효율적일 수 있음.
  5. 사용 사례: 웹 서비스, 모바일 애플리케이션 백엔드, 마이크로서비스 통신 등.

웹소켓 (WebSocket)

  1. 프로토콜: HTML5의 한 부분으로, 양방향 통신을 위한 프로토콜. 단일 TCP 연결을 통해 클라이언트와 서버 간의 실시간 통신 가능.
  2. 데이터 형식: 텍스트 또는 바이너리 데이터.
  3. 장점:
    • 실시간 통신이 가능하여 낮은 지연 시간.
    • 지속적인 연결로 인해 빠른 데이터 전송 가능.
  4. 단점:
    • HTTP 기반이 아니므로 프록시 및 방화벽 설정에 영향을 받을 수 있음.
    • 상태를 유지하기 때문에 서버 자원 소모가 클 수 있음.
  5. 사용 사례: 채팅 애플리케이션, 실시간 업데이트가 필요한 대시보드, 게임 등.

RPC (Remote Procedure Call)

  1. 개념: 원격 서버에서 함수나 절차를 호출할 수 있는 프로토콜. 클라이언트는 서버의 함수 호출을 로컬 함수 호출처럼 수행.
  2. 데이터 형식: 프로토콜에 따라 다름. 예: JSON-RPC는 JSON, XML-RPC는 XML, gRPC는 Protocol Buffers.
  3. 장점:
    • 함수 호출 방식이므로 직관적이고 사용하기 쉬움.
    • 높은 성능과 효율성.
  4. 단점:
    • API 계약이 강하게 결합되어 변경 시 영향이 클 수 있음.
    • HTTP와 같은 표준화된 프로토콜에 비해 덜 유연함.
  5. 사용 사례: 마이크로서비스 간 통신, 분산 시스템, gRPC를 사용한 고성능 서비스.

GraphQL

  1. 언어: 페이스북에서 개발한 쿼리 언어로, 클라이언트가 필요한 데이터의 형태를 정확히 요청할 수 있음.
  2. 데이터 형식: 주로 JSON.
  3. 장점:
    • 클라이언트가 정확히 필요한 데이터만 요청할 수 있어 과다 전송 방지.
    • 단일 요청으로 여러 자원에 대한 데이터를 가져올 수 있음.
    • 강력한 타입 시스템을 통한 명확한 API 정의.
  4. 단점:
    • 서버 구현 복잡도 증가.
    • 캐싱이 REST에 비해 어려울 수 있음.
  5. 사용 사례: 복잡한 데이터 요구사항이 있는 프론트엔드 애플리케이션, 여러 자원 간의 관계를 명확하게 정의해야 하는 경우.

요약

  • REST API: 단순하고 표준화된 HTTP 기반 통신.
  • 웹소켓: 실시간 양방향 통신.
  • RPC: 원격 함수 호출 방식의 통신.
  • GraphQL: 클라이언트가 필요한 데이터를 명확하게 정의하여 요청할 수 있는 쿼리 언어.

REST API

적합한 상황:

  1. 정적인 리소스 접근: 리소스를 CRUD(생성, 읽기, 업데이트, 삭제) 방식으로 접근할 때.
  2. 분산 시스템: 마이크로서비스 아키텍처에서 서로 독립적으로 동작하는 서비스 간의 통신.
  3. 모바일 애플리케이션 백엔드: 모바일 앱에서 서버와 데이터를 주고받을 때.
  4. 데이터 캐싱: HTTP 캐싱을 활용하여 성능을 향상시키고자 할 때.

예시:

  • 블로그 게시글 API
  • 사용자 인증 시스템
  • 상품 목록 조회 서비스

웹소켓 (WebSocket)

적합한 상황:

  1. 실시간 통신 필요: 채팅 애플리케이션, 게임, 주식 거래 시스템 등.
  2. 실시간 업데이트: 대시보드, 실시간 알림 시스템.
  3. 양방향 통신: 클라이언트와 서버 간의 즉각적인 상호작용이 필요한 경우.

예시:

  • 실시간 채팅 애플리케이션
  • 온라인 멀티플레이어 게임
  • 주식 가격 실시간 업데이트

RPC (Remote Procedure Call)

적합한 상황:

  1. 고성능 요구: 낮은 지연 시간과 높은 처리량이 필요한 시스템.
  2. 분산 시스템 내부 통신: 마이크로서비스 간의 고성능 통신.
  3. 함수 호출 방식이 적합한 경우: 클라이언트가 서버의 함수를 원격으로 호출해야 하는 경우.

예시:

  • gRPC를 사용한 마이크로서비스 간 통신
  • 분산 데이터베이스 시스템
  • 대규모 엔터프라이즈 애플리케이션

GraphQL

적합한 상황:

  1. 복잡한 데이터 요구: 클라이언트가 다양한 자원과 그 관계를 정확하게 요청해야 하는 경우.
  2. 프론트엔드 주도 개발: 프론트엔드 개발자가 필요한 데이터만 정확하게 요청하고자 할 때.
  3. 단일 요청으로 여러 자원 접근: 여러 자원에 걸쳐 데이터를 동시에 가져와야 하는 경우.

예시:

  • 복잡한 대시보드 애플리케이션
  • 다양한 데이터 소스에서 데이터를 가져와야 하는 모바일/웹 애플리케이션
  • 여러 자원 간의 관계를 명확히 정의해야 하는 시스템

요약

  1. REST API:
    • 정적인 리소스 접근
    • 분산 시스템
    • 모바일 백엔드
    • 데이터 캐싱이 중요한 경우
  2. 웹소켓:
    • 실시간 통신이 필요한 경우
    • 실시간 업데이트
    • 양방향 통신
  3. RPC:
    • 고성능이 요구되는 시스템
    • 분산 시스템 내부 통신
    • 함수 호출 방식이 적합한 경우
  4. GraphQL:
    • 복잡한 데이터 요구사항
    • 프론트엔드 주도 개발
    • 단일 요청으로 여러 자원 접근

이러한 기준을 바탕으로 각 기술을 사용해야 하는 상황을 명확히 구분할 수 있습니다. 프로젝트의 특성, 요구사항, 성능 및 유지보수 고려 사항에 따라 적절한 기술을 선택하는 것이 중요합니다.


단일 스레드에서 구동되는 논틀로킹 I/O 이벤트 기반 비동기 방식

-멀티 스레드 : 여러 작업 동시 처리하기 위해, 공유 자원 관리 비용 발생 및 동기화 로직 작성 어려움으로 락 발생 가능성 존재. 또한 메모리 관리 필요

- 단일 스레드 : 애플리케이션 단에서는 단일 스레드, 백그라운드에서는 스레드 풀로 작업 처리하므로 개발자가 코드 작성에 어려움이 없음

- Node.js는 앞의 작업이 끝날 때까지 기다리지 않고, 논블로킹 방식으로 비동기 처리 후, 먼저 처리된 결과를 이벤트로 반환

장점과 단점

- 이벤트 방식은 서버의 자원에 부하를 가하지 않는다는 장점

- 이벤트를 동시에 처리할 경우 '콜백 지옥' 발생 가능하다는 단점

- 프로미스, async/await의 추가로 비동기 코드를 동기식처럼 작성 가능하게 되었다.


이벤트 루프 [비동기 처리를 가능하게 하는 기능]

- 시스템 커널에서 가능한 작업을 커널에 이관해, 단일 스레드 기반임에도 논블로킹 I/O를 수행할 수 있는 이유

- 6단계

- 타이머 단계

- 대기 콜백 단계 [파일 입출력 혹은 에러 핸들러 콜백]

: pending_queue에는 현재 돌고 있는 루프 이전의 작업에서 큐에 들어온 콜백

- 유휴,준비 단계

:유휴 단계는 틱마다 실행

:준비 단계는 매 폴링 직전에 실행

- 폴 단계

: 새로운 I/O 이벤트를 가져와 수행 -> watch_queue에 있는 작업을 수행

- 체크 단계

: setImediate의 콜백을 수행

- 종료 콜백 단계 [close나 destroy 이벤트 타입 콜백 처리]


Node.js 이벤트 루프 관련 큐 종류

Node.js 이벤트 루프는 다양한 큐를 통해 비동기 작업을 처리합니다. 다음은 Node.js 이벤트 루프에서 사용되는 주요 큐들입니다:

  1. nextTickQueue
  2. microTaskQueue
  3. Timers Queue
  4. I/O Callbacks Queue
  5. Check Queue
  6. Close Callbacks Queue

1. nextTickQueue

  • 설명: process.nextTick으로 예약된 콜백을 저장하는 큐입니다.
  • 특징: 현재 실행 중인 작업이 완료된 직후, 이벤트 루프의 다른 단계보다 우선하여 실행됩니다.
  • 예시:출력:
  • Start End Next tick callback
  • console.log('Start'); process.nextTick(() => { console.log('Next tick callback'); }); console.log('End');

2. microTaskQueue

  • 설명: Promise와 같은 미세 작업(microtask)을 처리하는 큐입니다.
  • 특징: 현재 실행 중인 작업이 완료된 직후, nextTickQueue 다음으로 실행됩니다.
  • 예시:출력:
  • Start End Promise callback
  • console.log('Start'); Promise.resolve().then(() => { console.log('Promise callback'); }); console.log('End');

3. Timers Queue

  • 설명: setTimeoutsetInterval로 예약된 콜백을 저장하는 큐입니다.
  • 특징: 이벤트 루프의 Timers 단계에서 처리됩니다.
  • 예시:
  • setTimeout(() => { console.log('Timeout callback'); }, 0);

4. I/O Callbacks Queue

  • 설명: 대부분의 I/O 관련 콜백을 저장하는 큐입니다.
  • 특징: 이벤트 루프의 Pending Callbacks 단계에서 처리됩니다.
  • 예시:
  • const fs = require('fs'); fs.readFile('/path/to/file', (err, data) => { if (err) throw err; console.log(data); });

5. Check Queue

  • 설명: setImmediate로 예약된 콜백을 저장하는 큐입니다.
  • 특징: 이벤트 루프의 Check 단계에서 처리됩니다.
  • 예시:
  • setImmediate(() => { console.log('Immediate callback'); });

6. Close Callbacks Queue

  • 설명: 닫힌 close 이벤트가 발생한 콜백을 저장하는 큐입니다.
  • 특징: 이벤트 루프의 Close Callbacks 단계에서 처리됩니다.
  • 예시:
  • const net = require('net'); const server = net.createServer((socket) => { socket.on('close', () => { console.log('Socket closed'); }); }); server.listen(8080);

이벤트 루프의 처리 순서

이벤트 루프는 다음 순서로 큐를 처리합니다:

  1. current operation: 현재 실행 중인 작업이 완료됩니다.
  2. nextTickQueue: process.nextTick으로 예약된 콜백을 실행합니다.
  3. microTaskQueue: Promise와 같은 미세 작업 콜백을 실행합니다.
  4. event loop phases:
    • Timers: setTimeoutsetInterval 콜백을 처리합니다.
    • Pending Callbacks: 일부 시스템 작업에 의해 지연된 I/O 콜백을 처리합니다.
    • Idle, Prepare: Node.js 내부 용도로 사용됩니다.
    • Poll: 새로운 I/O 이벤트를 가져오고, 적절한 경우 콜백을 실행하며, 이 단계에서 이벤트 루프는 새로운 이벤트가 발생할 때까지 대기할 수 있습니다.
    • Check: setImmediate 콜백을 처리합니다.
    • Close Callbacks: 닫힌 close 이벤트가 발생한 콜백을 처리합니다.

패키지 관리

package.json

- 필요한 패키지를 관리

- 시맨틱 버저닝 규칙 [메이저.마이너.패치]

- 같은 개발 환경 구성할 수 있도록 도와줌

package-lock.json

- 프로젝트가 필요로하는 패키지를 관리하는 node_modules를 직접 공유하지 않아도 되는 이유

- 서로 간의 패키지들 사이의 의존성을 표현해 이 파일을 기준으로 설치하도록 한다.


타입 스크립트

- 자바스크립트에 타입 시스템을 도입해 런타입에 에러를 체크함으로 타입 안정성을 높임 [정적 프로그램 분석]

- 변수 선언 방식

[선언 키워드] [변수명] : [타입]

- 지원 타입

(1) 원시 값 타입

(2) 객체 타입

(3) 함수 타입

- 일급 함수

(4) 특수 타입

- any

- unknown

- never

-타입 정의 방법

(1) 변수에 객체를 바로 할당

(2) 인터페이스로 선언해 객체 할당

(3) 인터페이스를 클래스로 선언 후, 생성자로 객체 할당

(4) 타입 키워드로 새로운 타입 생성해 객체 할당

- 타입 구성 방식인 덕 타이핑

(1) 유니언 타입 [열거형 사용 권장]

  • 여러 타입을 조합한 타입으로, 변수가 가질 수 있는 값을 제한할 수도 있음
  • (obj: string | string[])
  • "Ready | "Waiting"

(2) 제네릭 타입

  • 어떠한 타입이든 정의될 수 있지만, 호출 시점에 타입 결정

데커레이터

-횡단 관심사를 분리해 관점 지향 프로그래밍 구현

-관심사의 분리 (SoC)

Separation of Concerns (SoC, 관심사의 분리)는 소프트웨어 공학에서 중요한 설계 원칙 중 하나입니다. 이 원칙은 소프트웨어 시스템을 여러 개의 독립적인 부분으로 나누어 각 부분이 특정한 관심 영역에 집중하도록 하는 것을 목표로 합니다. 각각의 부분은 다른 부분과 최대한 독립적으로 개발, 유지보수할 수 있어야 합니다.

주요 개념

  1. 관심사(Concern):
    • 소프트웨어에서의 관심사란 특정 기능이나 책임을 가리킵니다. 예를 들어, 데이터베이스 접근, 비즈니스 로직 처리, 사용자 인터페이스 제어 등이 관심사의 예입니다.
  2. 분리(Separation):
    • SoC는 프로그램을 여러 개의 모듈이나 계층으로 나누어 각 모듈이나 계층이 특정 관심사에 집중하도록 합니다. 이는 코드의 가독성과 유지보수성을 높이고, 재사용성을 개선하는 데 기여합니다.
  3. 이점(Benefits):
    • 유지보수성 향상: 각 모듈이나 계층이 특정 관심사에 집중하므로 코드 수정이 필요할 때 해당 영역만 수정할 수 있습니다.
    • 재사용성 증가: 독립적인 모듈은 다른 프로젝트나 다른 부분에서 재사용될 수 있습니다.
    • 테스트 용이성: 각 모듈이 독립적이므로 단위 테스트가 용이합니다.
    • 확장성: 새로운 기능을 추가할 때 기존 코드를 수정하지 않고 새로운 모듈을 추가함으로써 시스템을 확장할 수 있습니다.

구현 방법

관심사의 분리를 구현하는 방법은 다음과 같습니다:

  • 계층적 구조(Hierarchical Structure): 각 계층이 특정한 관심사를 담당하도록 설계합니다. 예를 들어, MVC(Model-View-Controller) 패턴에서는 데이터, 표현, 제어 로직을 각각 분리합니다.
  • 모듈화(Modularization): 각 기능이나 서비스를 독립적인 모듈로 나누어 개발하고, 인터페이스를 통해 상호작용하도록 합니다.
  • 디자인 패턴 활용: 디자인 패턴을 적용하여 특정 관심사에 맞는 솔루션을 제공하는 방법을 사용할 수 있습니다. 예를 들어, Observer, Factory, Singleton 등의 패턴을 활용할 수 있습니다.

예시

예를 들어, 웹 애플리케이션에서는 데이터베이스 접근, 비즈니스 로직 처리, 사용자 인터페이스 제어 등의 다양한 관심사를 가집니다. 각각의 관심사를 분리하여 데이터베이스 접근을 위한 DAO(Data Access Object), 비즈니스 로직을 처리하는 서비스 클래스, UI를 담당하는 컨트롤러 등으로 나누는 것이 관심사의 분리를 실현하는 예시입니다.

관심사의 분리는 소프트웨어 설계에서 중요한 원칙으로, 코드의 가독성, 유지보수성, 확장성을 크게 향상시키고, 프로젝트의 성공에 기여하는 요소로 작용합니다.


-관점 지향 프로그래밍(AOP)

: 소스 코드 단에서 횡단 관심사를 분리하지 않을 때, 모듈로서 응집도가 떨어져 유지보수에 문제

 -> 횡단 관심사를 비즈니스 로직과 쉽게 분리할 수 있도록 인터셉터라는 컴포넌트가 존재.

 

인터셉터는 서버로 들어오는 요청과 나가는 응답을 가로채 일괄적으로 변경하는 역할을 수행 [전역적]

-> 로깅, 코드 표준화, 예외 핸들링

 

데코레이터

-> AOP 구현시 전역으로 적용하지 않고 특정 컴포넌트에서만 적용할 때 [부분적]


관점지향 프로그래밍(Aspect-Oriented Programming, AOP)은 소프트웨어 개발에서 횡단 관심사(cross-cutting concern)를 처리하기 위한 프로그래밍 패러다임입니다. AOP는 기본적으로 모듈성을 향상시키고 코드의 재사용성을 높이며, 유지보수성을 개선하는 데 중점을 둡니다. 여기에서 AOP의 주요 개념과 원리에 대해 더 자세히 설명하겠습니다.

AOP의 주요 개념

  1. 관심사(Concern):
    • 핵심 관심사(Core Concerns): 소프트웨어의 핵심 비즈니스 로직을 구현하는 부분입니다. 예를 들어, 계좌 이체, 주문 처리 등이 핵심 관심사에 해당합니다.
    • 횡단 관심사(Cross-cutting Concerns): 여러 모듈이나 계층에 걸쳐 분포되어 있는 부가적인 기능을 말합니다. 예를 들어, 로깅, 트랜잭션 관리, 보안 검사, 예외 처리 등이 횡단 관심사에 해당합니다.
  2. 관점(Aspect):
    • AOP에서 관점은 특정한 횡단 관심사를 나타냅니다. 즉, 여러 모듈에 걸쳐 있는 반복적인 코드나 동작을 하나의 관점으로 추상화하여 관리합니다.
  3. 어드바이스(Advice):
    • 어드바이스는 관점에서 특정 지점에 삽입되어 실행되는 코드 블록입니다. 주요 종류로는 다음과 같습니다:
      • Before advice: 대상 메소드 실행 전에 실행됩니다.
      • After returning advice: 대상 메소드가 정상적으로 반환된 후에 실행됩니다.
      • After throwing advice: 대상 메소드에서 예외가 발생한 후에 실행됩니다.
      • After (finally) advice: 대상 메소드가 실행된 후 무조건 실행됩니다.
      • Around advice: 대상 메소드 실행을 감싸서 전/후 처리를 수행합니다.
  4. 포인트컷(Pointcut):
    • 포인트컷은 어드바이스가 적용될 메소드나 지점을 선별하는 규칙을 정의합니다. 즉, 어떤 메소드에 어떤 어드바이스를 적용할지 결정하는 역할을 합니다.
  5. 위빙(Weaving):
    • 위빙은 관점에 정의된 어드바이스를 실제 코드에 삽입하는 프로세스를 말합니다. 이는 컴파일 타임에 바이트 코드를 조작하거나 런타임 중에 프록시 객체를 생성하여 이루어질 수 있습니다.

AOP의 장점

  • 모듈성 향상: 횡단 관심사를 별도의 모듈로 분리하여 각 모듈이 자신의 주요 역할에 집중할 수 있습니다.
  • 재사용성 증가: 관점을 다른 프로젝트나 다른 모듈에서 재사용할 수 있습니다.
  • 유지보수성 향상: 횡단 관심사를 한 곳에서 관리하기 때문에 코드의 중복이 줄어들고, 변경이 필요할 때 한 곳에서 수정할 수 있습니다.
  • 가독성 및 유지보수성: 핵심 비즈니스 로직과 횡단 관심사가 분리되므로 코드의 가독성이 향상되고, 유지보수가 용이해집니다.

예시

예를 들어, 보안 관점에서 AOP를 적용해보겠습니다. 모든 메소드 호출이 보안 검사를 거쳐야 하는 상황에서 AOP를 사용하여 모든 메소드 호출에 대해 보안 검사를 적용할 수 있습니다. 이를 통해 개발자는 각 메소드마다 보안 검사 코드를 중복해서 추가할 필요 없이, 한 번의 설정으로 모든 메소드에 보안 검사를 적용할 수 있습니다.

관점지향 프로그래밍은 특히 횡단 관심사를 효과적으로 처리하고 코드의 모듈성을 향상시키는 데 매우 유용한 패러다임입니다.


타입스크립트의 데커레이터

- 파이썬의 데커레이터

- 자바의 에너테이션

각 요소의 선언부 앞에 @로 시작하는 데커레이터를 선언하면, 데커레이터로 구현된 코드를 함께 실행한다.

-데커레이터 합성

(1) 위에서 아래로 표현을 평가

(2) 아래에서 위로 함수 호출

- 5가지 데커레이터

(1) 클래스 데커레이터

  • 생성자를 전달해 클래스의 정의를 읽거나 수정한다.
  • (2) 메서드 데커레이터
  • 타겟, 프로퍼티키, 프로퍼티설명자를 전달해 메서드 정의를 읽거나 수정
  • (3) 접근자 데커레이터
  • 타겟, 프로퍼티키, 프로퍼티설명자를 전달해 접근자 정의를 읽거나 수정
  • (4) 속성 데커레이터
  • 타겟, 프로퍼티키를 전달해 메서드 정의를 읽거나 수정
    • 타겟, 프로퍼티키를 , 파라미터인덱스를 전달해 메서드 정의를 읽거나 수정
  • (5) 매개변수 데커레이터

타입스크립트에서의 인터페이스와 클래스

타입스크립트(TypeScript)에서 인터페이스(interface)와 클래스(class)는 둘 다 객체의 형태를 정의하는 데 사용되지만, 각기 다른 목적과 기능을 가지고 있습니다. 다음은 인터페이스와 클래스의 주요 차이점들입니다:

1. 정의와 목적

인터페이스 (Interface):

  • 정의: 인터페이스는 객체의 구조(타입)를 정의하는 데 사용됩니다. 인터페이스는 객체가 어떤 프로퍼티와 메소드를 가져야 하는지 명시합니다.
  • 목적: 코드의 계약(Contract)을 정의하고, 객체가 특정 구조를 따르도록 강제합니다. 인터페이스는 구현 세부 사항을 가지지 않으며, 순수하게 타입을 정의하는 역할만 합니다.
interface Person {
  name: string;
  age: number;
  greet(): void;
}

클래스 (Class):

  • 정의: 클래스는 객체를 생성하기 위한 청사진(blueprint)입니다. 클래스는 필드(프로퍼티)와 메소드(동작)를 정의할 수 있으며, 이를 통해 객체를 인스턴스화할 수 있습니다.
  • 목적: 객체지향 프로그래밍(OOP)의 중심 개념으로, 상태와 행동을 함께 정의하고, 상속, 캡슐화 등의 OOP 원칙을 구현합니다.
class Person {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  greet(): void {
    console.log(`Hello, my name is ${this.name}`);
  }
}

2. 구현과 인스턴스화

인터페이스:

  • 구현: 인터페이스는 구현 세부 사항을 가지지 않습니다. 따라서 인터페이스 자체를 인스턴스화할 수 없습니다.
  • 사용: 다른 클래스나 객체가 인터페이스를 구현(implement)하여 그 구조를 따르게 합니다.
class Student implements Person {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  greet(): void {
    console.log(`Hello, my name is ${this.name} and I am a student.`);
  }
}

클래스:

  • 구현: 클래스는 필드와 메소드를 모두 정의하고, 실제 구현을 포함합니다.
  • 사용: 클래스를 사용하여 객체를 인스턴스화할 수 있습니다.
const student = new Student('John Doe', 20);
student.greet();  // Output: Hello, my name is John Doe and I am a student.

3. 타입 정의와 확장성

인터페이스:

  • 타입 정의: 인터페이스는 타입을 정의하는 데 집중하며, 이를 통해 다양한 객체들이 특정 구조를 따르도록 강제할 수 있습니다.
  • 확장성: 인터페이스는 다른 인터페이스를 상속받을 수 있으며, 여러 인터페이스를 확장하여 복합적인 구조를 정의할 수 있습니다.
interface Employee extends Person {
  employeeId: number;
  department: string;
}

클래스:

  • 타입 정의: 클래스는 타입을 정의할 수 있지만, 주로 객체를 생성하고 그 객체의 상태와 동작을 구현하는 데 사용됩니다.
  • 확장성: 클래스는 다른 클래스를 상속받을 수 있으며, 이를 통해 상속 계층 구조를 만들 수 있습니다. 또한, 인터페이스를 구현하여 인터페이스에서 정의한 계약을 따를 수 있습니다.
class Manager extends Person implements Employee {
  employeeId: number;
  department: string;

  constructor(name: string, age: number, employeeId: number, department: string) {
    super(name, age);
    this.employeeId = employeeId;
    this.department = department;
  }
}

4. 멤버 가시성(Visibility)

인터페이스:

  • 가시성 제어: 인터페이스에서는 멤버의 가시성(예: public, private)을 제어할 수 없습니다. 모든 멤버는 public으로 간주됩니다.

클래스:

  • 가시성 제어: 클래스에서는 멤버의 가시성을 제어할 수 있습니다. public, private, protected 등의 접근 제어자를 사용할 수 있습니다.
class SecretPerson {
  public name: string;
  private age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  public greet(): void {
    console.log(`Hello, my name is ${this.name}`);
  }

  private getAge(): number {
    return this.age;
  }
}

요약

  • 인터페이스는 객체의 구조(타입)를 정의하는 데 사용되며, 구현 세부 사항을 포함하지 않습니다.
  • 클래스는 객체를 생성하기 위한 청사진이며, 상태와 행동을 함께 정의하고 구현합니다.
  • 인터페이스는 타입 체크와 코드 계약을 강제하는 데 중점을 두고, 클래스는 객체 생성과 상속을 통한 코드 재사용에 중점을 둡니다.

컨트롤러 인터페이스

- 엔드포인트 라우팅 메커니즘을 통해 구조적이고 모듈화된 소프트웨어

- API 작성시 요청 객체를 직접 다룰 수도 있지만, @Query(), @Param(key? : string), @Body() 데커레이터로 전달

-> 쿼리 매개변수, 패스 매개변수, 본문

 

(1) 응답

-> @HttpCode()로 상태코드 변경

(2) 헤더

-> @Header로 커스템 헤더 추가

(3) 리디렉션

-> @Redirect 데커레이터로, 정해진 응답 코드로 이동 [결과에 따라 동적으로 리디렉트도 가능]

(4) 라우트 매개변수

-> @Param으로 전달받은 매개변수를 주입할 수 있지만, 타입이 any가 되므로 권장하지 않는다.

-> 타입이 항상 string이므로 명시적으로 { [key: string]: string} 처럼 타입 지정 가능

-> 하지만, 라우팅 매개변수를 따로 받아서 처리하도록 한다.

 

@Param('userId') userId: string,

@Param('memoId') memoId: string,

 

(5) 하위 도메인 라우팅

-> @Controller 데커레이터는 ControllerOptions 객체를 인수로 받으므로, host 속성에 하위 도메인 기술

 

(6) 페이로드

-> 처리에 필요한 데이터를 실어 보내는 HTTP 메서드 : POST, PUT, PATCH

-> 이 때 데이터 덩어리가 페이로드 혹은 본문

-> 구현되어있는 DTO를 이용


서비스 인터페이스

-> DTO에 JSON 형식임을 나타내도록 Content-Type 헤더에 추가 : application/json


프로바이더

: 핵심 기능. 즉 비즈니스 로직을 수행하는 역할

-> 단일 책임 원칙 (SRP)를 지키기 위해, 컨트롤러에서 분리해 서비스단에서 구현

-> 서비스, 저장소, 팩토리, 헬퍼와 같은 형태로 구현

 

 

-> 의존성 주입이 가능한 프로바이더 [DI]

-> 객체 생성, 사용시 관심사의 분리를 보장해주는 기능


서비스

: @Injectable

 

-> 컨트롤러에 연결된 서비스 클래스에서 수행할 수 있도록 서비스 클래스에 해당 데커레이터를 선언

-> UserController 생성자에서 주입받아 UserService라는 객체 멤버 변수에 할당해 사용

: 어떤 컴포넌트에서도 주입할 수 있는 프로바이더가 됨 [스코프 지정하지 않으면 기본적으로 싱글턴]

 


(1) 생성자 프로바이더

-> 프로바이더를 직접 주입받아 사용

 

(2) 속성 프로바이더

-> 상속관계의 자식 클래스를 주입받아 사용 [레거시에서 새로운 클래스로 프로바이더를 변경하고자 할 때]

-> super()를 이용해 부모 클래스에서 필요한 프로바이더를 전달

 

-> 자식 클래스의 생성자에서 super()를 이용해 부모 클래스의 생성자를 호출하는 것

 

-속성 기반 프로바이더는 사용할 부모 클래스 속성에 @Inject 데커레이터를 지정 [인수는 타입, 문자열, 심벌]

-> 상속 관계가 아닌 경우엔 생성자 기반 주입을 권장

 


기능

(1) 회원가입

(2) 이메일 인증

(3) 로그인

(4) 회원정보 조회


모듈

- 기본모듈인 루트 모듈과 각각의 기능을 하는 모듈로 구성

- 모듈은 기본적으로 컨트롤러와 프로바이더로 구성

 

- 프로바이더는 주로 클래스에 @Injectable() 데코레이터를 사용하여 정의됩니다.

- 이 @Injectable() 데코레이터는 해당 클래스가 의존성 주입 시스템에서 관리되는 프로바이더임을 나타냅니다.

- 이 데코레이터는 클래스에 메타데이터를 추가하고, 컨테이너에서 프로바이더를 생성하고 관리하는 방법을 결정한다.

- 서비스가 필요한 시점에 자동으로 객체를 생성

 

 

반응형

'Server Programming > JavaScript' 카테고리의 다른 글

59일차 -TIL  (0) 2023.02.09
3일차. TIL  (0) 2022.12.14