Post

챌린지 9일차 학습 정리

네이버 부스트캠프 9기 챌린지 9일차 학습 정리 페이지입니다.

챌린지 9일차 학습 정리

Tips
누군가 작성한 것을 그대로 쓰는 것이 아니라 나만의 언어로 재구조화하여 작성해야 합니다.
기술 키워드에 대한 상세 내용도 좋고, 미션 해결 과정에서 기능 구현을 성공한 사례도, 트러블 슈팅 경험도 좋습니다.

학습한 내용

Design Pattern

  • 소프트웨어 공학의 소프트웨어 설계에서 공통으로 발생하는 문제에 대해 자주 쓰이는 설계 방법을 정리한 패턴
  • 프로그램을 설계할 때 발생했던 문제점들을 객체 간의 상호 관계 등을 이용하여 해결할 수 있도록 하나의 ‘규약’ 형태로 만들어 놓은 것을 의미합니다.
  • 디자인 패턴 유형
    • 생성(Creational): 객체 인스턴스 생성에 관여, 클래스 정의와 객체 생성 방식을 구조화, 캡슐화를 수행하는 패턴 (Prototype, Factory Method, Singleton, …)
    • 구조(Structural): 더 큰 구조 형성 목적으로 클래스나 객체의 조합을 다루는 패턴 (Bridge, Decorator, Facade, …)
    • 행위(Behavioral): 클래스나 객체들이 상호 작용하는 방법과 역할 분담을 다루는 패턴 (Iterator, Template Method, Observer, Publisher-Subscriber, …)

Observer Pattern

  • 주체가 어떤 객체의 상태 변화를 관찰하다가 상태 변화가 있을 때마다 메서드 등을 통해 옵저버 목록에 있는 옵저버들에게 변화를 알려주는 디자인 패턴입니다.
  • 사용 시기
    • 낮은 결합도가 필요할 때
    • 상호 의존성을 느슨하게 해야 할 때
    • 한 객체에서 상태 변화가 일어날 때 다른 객체의 행동에 변화가 일어나야 할 때
  • 특징
    • ObserverObservable이 서로의 존재를 알고 있습니다.
    • 주로 동기적으로 동작합니다.
    • Observer 패턴은 주로 이벤트 기반 시스템에 사용하며 MVC(Model-View-Controller) 패턴에도 사용됩니다.

Publisher-Subscriber Pattern

  • 사용 시기
    • 상호 의존성을 느슨하게 해야 할 때
  • 특징
    • PublisherSubscriber에 직접 메세지를 보내지 않으며 이 둘은 서로의 존재를 알지 못합니다.
    • Observer 패턴과 달리 중간에 브로커(Event Broker 또는 Event Bus)가 존재합니다. 브로커는 Publisher와 Subscriber 사이에서 메시지를 필터링하여 다시 배포하는 역할을 수행합니다.
    • 비동기적으로 동작합니다.

Singleton Pattern

  • 클래스에 하나의 인스턴스만 생성하고 그 인스턴스를 어디에서든 참조할 수 있게 하는 패턴
  • 사용 시기
    • 시스템 내에 오직 단 하나의 인스턴스만 필요할 때 (구현 방식에 따라 존재할 수 있는 인스턴스의 수를 제한할 수 있음.)
    • 주로 데이터베이스 연결 모듈에 많이 사용합니다.
  • 특징
    • 클래스에서 만들 수 있는 인스턴스의 수를 하나로 제한합니다.
    • 해당 객체에 전역적으로 접근이 가능해 다른 클래스 간에 데이터 공유가 용이합니다.
    • 동일 클래스에 여러 객체를 생성하지 않기 때문에 메모리를 낭비하지 않습니다.
    • 싱글톤 패턴은 미리 생성된 하나의 인스턴스를 기반으로 구현하는 패턴이므로 테스트가 서로 독립적이어야 하는 단위 테스트를 하는 것이 어렵습니다. 즉, TDD(Test-Driven Development)를 진행하기 어렵습니다.

비동기 프로그래밍

  • 동기(Synchronous)
    • 현재 작업의 응답이 끝남과 동시에 다음 작업이 요청됨
    • 함수를 호출하는 곳에서 호출하는 함수와 결과가 반환될 때까지 기다림
    • 작업 완료 여부를 계속 확인함
  • 비동기(Asynchronous)
    • 현재 작업의 응답이 끝나지 않은 상태에서 다음 작업이 요청됨
    • 함수를 호출하는 곳에서 결과를 기다리지 않고, 다른 함수(Callback)에서 결과를 기다림
    • 작업 완료 여부를 확인하지 않음

프로세스 동기화

  • 프로세스의 실행 순서를 제어해 하나의 자원을 하나의 프로세스가 접근하게 하는 기법
  • 동시에 접근할 수 없는 자원에 하나의 프로세스만 접근하게 해 데이터의 일관성을 유지합니다.
  • Race Condition에 의해 자원의 일관성이 깨지는 상황을 방지합니다.

Race Condition(경쟁 상태)

  • 여러 프로세스가 공유자원에 동시에 접근할 때 공유자원에 대한 접근 순서에 따라 실행 결과가 달라질 수 있는 상황

Critical Section(임계 영역)

  • 여러 프로세스가 자원을 공유해 둔 상황에서 문제가 발생하지 않도록 독점을 보장해야 하는 영역
  • 임계 영역 문제
    • Mutual Exclustion(상호 배타, 상호 배제) : 임계 영역에는 하나의 프로세스만 진입해야 한다.
    • Progress(진행) : 임계 영역에 접근할 프로세스의 순서를 유한 시간 내에 결정해야 한다.
    • Bounded Waiting(유한 대기) : 프로세스는 유한한 시간 내에 임계 영역에 접근할 수 있어야 한다. 즉, 특정 프로세스가 영원히 임계 영역에 들어가지 못하면 안됩니다.
  • 임계 영역 문제 해결 방법
    • Mutex : 임계 영역을 하나의 프로세스만 접근할 수 있도록 하는 상호 배제 기법. 프로세스나 스레드가 공유 자원을 lock()을 통해 잠금 설정하고 사용한 후에는 unlock()을 통해 잠금 해제합니다.
    • Semaphore(세마포어) : 복수의 프로세스가 임계 영역을 접근할 수 있게 하는 상호 배제 기법. 간단한 정수 값과 두 가지 함수 wait(=P 함수) 및 signal(=V 함수)로 공유 자원에 대한 접근을 처리합니다.
      • wait(): 자신의 차례가 올 때까지 기다리는 함수
      • signal(): 다음 프로세스로 순서를 넘겨주는 함수

Dead-Lock(교착 상태)

  • 교착 상태는 두 개 이상의 프로세스들이 서로가 가진 자원을 기다리며 중단된 상태를 말합니다.
  • 교착 상태의 원인
    • 상호 배제: 한 프로세스가 자원을 독점하고 있으며 다른 프로세스들은 접근이 불가능합니다.
    • 점유 대기: 특정 프로세스가 점유한 자원을 다른 프로세스가 요청하는 상태입니다.
    • 비선점: 다른 프로세스의 자원을 강제적으로 가져올 수 없습니다.
    • 환형 대기: 프로세스 A는 프로세스 B의 자원을 요구하고, 프로세스 B는 프로세스 A의 자원을 요구하는 등 서로가 서로의 자원을 요구하는 상황을 말합니다.
  • 교착 상태의 해결 방법
    1. 자원을 할당할 때 애초에 조건이 성립되지 않도록 설계합니다.
    2. 교착 상태 가능성이 없을 때만 자원 할당되며, 프로세스당 요청할 자원들의 최대치를 통해 자원 할당 가능 여부를 파악하는 은행원 알고리즘 을 사용합니다.
    3. 교착 상태가 발생하면 사이클이 있는지 찾아보고 이에 관련된 프로세를 한 개씩 지웁니다.
    4. 교착 상태는 매우 드물게 일어나기 때문에 이를 처리하는 비용이 더 커서 교착 상태가 발생하면 사용자가 작업을 종료합니다.

Callback(콜백)

  • 콜백은 실행 가능한 함수를 인자로 전달하여, 특정 상황이 발생할 때 호출되게 하는 방식을 말합니다.
  • 콜백은 깊이가 깊어질 수록 코드의 가독성이 떨어지고, 에러 추적이 어려워집니다. (=콜백 지옥)

Promise 객체

  • 콜백 지옥(Callback Hell) 문제를 해결하기 위해 2015년 ES6 버전에 도입되었습니다.
  • 자바스크립트에서 콜백(callback) 대신 사용할 수 있는 방법으로 비동기 작업이 완료되면 결과를 반환하는 객체를 말합니다.
  • 프로미스 객체는 상태를 가지고 있으며 처음에는 대기 상태였다가 작업이 완료되면 성공 또는 실패 상태가 됩니다.
  • Promise 객체를 사용한 비동기 처리를 사용하는 방법은 다음과 같이 2가지 방식을 활용할 수 있습니다.
    • then() & catch()
      • 체이닝(chaining) 방식을 활용하여 로직을 처리하는 방식
      • 복잡한 로직과 예외 처리를 해야 하는 상황에서 사용하기 어려습니다.
    • async/await
      • 자바스크립트에서 도입한 비동기 처리 방식 중 하나입니다.
      • async 는 함수 앞에 붙이는 키워드이며, asynchronous(비동기)라는 의미입니다.
      • async 가 붙은 함수는 Promise 를 반환합니다.
      • awaitasync 가 붙은 함수 안에서만 사용할 수 있는 키워드로, Promise 객체의 실행이 끝나기를 기다립니다.
      • async/await 키워드를 사용하면 비동기 코드를 가독성 좋게, 디버깅하기 편하게 작성할 수 있습니다.
구분callbackpromiseasync/await
에러 처리콜백 함수 내에서 처리catch() 메서드로 처리try-catch 블록으로 처리
가독성간단한 경우에는 괜찮으나, 점점 복잡해짐.가독성 좋음가독성 좋음
중첩 처리콜백 함수 내에서 처리then() 메서드를 사용await 키워드를 사용

Worker Threads

  • Node.js에서 스크립트 연산을 주 실행 스레드와 분리된 별도의 백그라운드 스레드에서 실행할 수 있도록 하는 API
  • 하나의 프로세스에서 여러 개의 스레드를 구성하고 각 스레드 별로 하나의 이벤트 루프를 실행
  • CPU 집약적인 작업의 퍼포먼스 향상을 목표
  • 메인 스레드와 Worker 사이에서 메시지 시스템을 통해 데이터 송수신
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const { Worker, isMainThread, parentPort } = require('worker_threads');

if (isMainThread) { // 메인 스레드
   const worker = new Worker(__filename); // 같은 dir 폴더에 워커 생성

   worker.on('message', (value) => {
      console.log('워커로부터', value)
   })
   worker.on('exit', (value) => { // parentPort.close()가 일어나면 이벤트 발생
      console.log('워커 끝~');
   })

   worker.postMessage('ping'); // 워커스레드에게 메세지를 보낸다.

} else { // 워커스레드
	// 위에서 생성한 Worker 동작
   parentPort.on('message', (value) => {
      console.log("부모로부터", value);
      parentPort.postMessage('pong');
      parentPort.close(); // 워커스레드 종료라고 메인스레드에 알려줘야 exit이벤트 발생
   })
}
출처: https://inpa.tistory.com/entry/NODE-📚-workerthreads-모듈 [Inpa Dev 👨‍💻:티스토리]

Event Emitter

  • Node.js에서 이벤트를 발생시키고 처리하는 데 사용되는 가장 기본적인 이벤트 처리 방식 중 하나
  • 이벤트 기반 프로그래밍에서 사용되는 객체
  • 장점
    • 이벤트에 여러 개의 리스너를 등록할 수 있다.
    • 다른 객체들과 연동해 사용할 수 있다.
    • Promise에 비해 더욱 유연하다.
    • 비동기 작업의 결과를 처리하는 것 뿐 아니라 이벤트를 사용해 다양한 작업을 처리할 수 있다.
  • 단점
    • 이벤트 리스너에 등록된 콜백 함수들이 처리되지 않을 경우 메모리 누수가 발생할 수 있다.
    • 자체적인 동기화 메커니즘이 없다.
    • 비동기 작업을 보다 쉽게 처리하는 최신 기능을 지원하지 않는다. (async/await 지원 X)
This post is licensed under CC BY 4.0 by the author.