Jun4928 / wanted-pre-onboarding-challenge-BE-task-JAN.2023

JAN.2023 wanted 프리온보딩 챌린지 BE 사전과제
29 stars 36 forks source link

사전과제 제출 #57

Open loveAlakazam opened 1 year ago

loveAlakazam commented 1 year ago

함수형 프로그래밍, 실무에서 사용할 수 있나요? (feat. TypeScript, Nest.js)

해당 코스는 아래와 같은 주제로 진행돼요

사전과제 진행 가이드

사전과제

  1. 본인이 작성했던 코드 중 공유하고 싶은 코드를 이유와 함께 마크다운 코드블락을 사용해 올려주세요
    • 언어 상관없음
    • 어떤 로직이든 상관없음
    • 단, 길이가 길지 않은 함수 단위가 좋습니다


/* 날씨 데이터 구하기 */
async getWeatherData(IPAddress: string) {
  // IP 주소에 대응되는 위치를 구한다.
  const { lat, lng } = this.getLocationData(IPAddress);

  // const { lat, lng } = await this.getLocationData();
  const weather = this.axiosHttpService
    .get(
      `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lng}&appid=${this.configService.get<string>(
        'OPEN_WEATHER_API',
      )}`,
    )
    .pipe(
      map((res) => res.data?.weather),
      map((weather) => {
        // 현재 날씨 정보를 리턴
        return weather[0]?.main;
      }),
    )
    .pipe(
      catchError(() => {
        // 403 CustomError을 호출한다.
        throw new FailGetWeatherDataException();
      }),
    );

  const result = await lastValueFrom(weather);
  return result;
}

  1. Layered Architecture(계층 아키텍처)에 대해서 설명해 주세요


1. Software Architecture 정의

모든 소프트웨어 시스템의 기본 구조를 의미하며, 시스템 기능을 정상적으로 동작시키는 것을 의미한다.

소프트웨어 시스템에서는 컴포넌트의 설계, 컴포넌트간의 관계, 사용자간의 상호작용, 시스템에서의 사용자의 요구등을 포함한다.


2. Layerd Architecture 정의

N-계층 아키텍쳐. 소프트웨어 개발에서 가장 보편적이고 널리 사용되는 아키텍쳐 프레임워크를 의미한다.

단일 소프트웨어 단위들로 구성되어있는 수평계층 아키텍쳐 패턴이다.

컴포넌트와 코드들을 논리적으로 구분하여 층을 나눈다.


위의 그림처럼, 레이어1은 레이어2와 연결되어있고, 레이어2는 레이어3과 연결되어있는 것처럼 레이어1에서 레이어3으로 이동하려면 레이어2를 거쳐야한다.

레이어마다 독립적이므로, 특정 레이어가 변경한다해서 변경된 레이어에서만 적용될뿐, 연결된 다음레이어나 다른 레이어에는 영향을 미치지 않는다.


계층형 아키텍쳐의 계층수는 일반적으로 소프트웨어 설계자와 개발자에따라 달라진다.

보통은 '사용자 상호작용계층(UI Laeyr, User Interactions Layer)', '데이터 처리계층(Data Processing Layer)' 이 있다.

  1. Presentation Layer
  1. Application/Business Layer
  1. Domain Layer
  1. Domain -> 사전적인 의미로는 '영역', '집합' 이다. -> 실세계에서 사건이 발생하는 집합. -> 비즈니스 도메인. 업무의 집합.

  2. Domain 과 Object 의 차이점 객체는 추상화 또는 구체화할 수 있는 특정요소를 표현할 수 있다. 도메인은 사용자가 사용하는 모든 것을 설명할 수 있다.

  1. Infra Structure / Persistence / Database Layer

각각의 도메인들을 위와 같은 레이어로 분리하여 만드는 것이 DDD(Domain Driven Design)의 핵심설계방식이다.



3. Layerd Architecture 를 사용하는 경우


4. Layerd Architecture 장점과 단점

장점


단점


마치며

아래 참고글을 번역해서 이해를 했지만, 내게는 '계층별 아키텍쳐' 라는 용어가 어색했고 더많은 자료조사와 이해가 필요하다는 것을 깨달았다.

이 글을 보고 떠오른 생각을 나만의 언어로 표현하자면, 클라이언트부터 서버 사이드까지의 요청에서 응답까지의 과정을 층으로 분리시켜서 나타낸게 아닌가 싶다.

참고자료 : baeldung - Layered Architecture 참고자료: coco3o Tistory - DDD계층구조 알아보기



  1. Dependency Injection(의존성 주입)의 개념과 함께, 왜 필요한지 작성해 주세요

정의

"A가 B에 의존한다."


왜 필요한가?

  1. 두 클래스가 강하게 결합되어 있다.

의존성 : 한 객체가 다른 객체를 사용할 때 '의존성이 있다'고 한다. ex) '상점'은 '(상품)연필' 에 의존하고 있다. 의존관계는 '강한 결합'관계 이다. 만일 '상점'에서 '연필'이 아닌 '해산물'이라는 다른 상품을 판매한다면 '상점' 클래스의 생성자에서 변경이 필요하다. '각각 다른 상품'들을 판매하기 위해 생성자만 다르고 나머지는 중복되는 '상점' 클래스들이 파생되는 것은 좋지 않다. 상속은 제약이 많고 확장성이 떨어지므로 피하는 것이 좋다.

  1. 객체들간의 관계가 아니라 클래스간의 관계가 맺어진다.

'상점'과 '연필'은 객체들간의 관계가 아니라 클래스들 간의 관계가 맺어져있다. 객체들간에 관계가 맺어졌다면 다른 객체의 구체클래스(연필, 해산물, 옷 등등등)를 전혀 알지 못하더라도, (해당 클래스가 인터페이스를 구현했다면) 인터페이스의 타입(Product)로 사용할 수 있다.

위와 같은 문제를 해결하기 위해서는 다형성이 필요하다.

연필, 해산물 과 같은 제품을 하나로 표현하기 위해서는 Product라는 인터페이스가 필요하다.

의존성 주입은 의존관계의 결합도를 낮추기위해 인터페이스를 추상화하여 객체가 의존하는 또 다른 객체를 외부에서 선언하고 이를 주입받아서 사용하는 것을 의미한다.


DI 의 장점이 무엇인가?

  1. 의존성이 줄어든다.
  1. 재사용성이 높은 코드가 된다.
  1. 테스트하기 좋은 코드가 된다.

  2. 가독성이 높아진다.


참고자료: edureka! 참고자료: tecoble.techcourse.co.kr 참고자료: 망나니 개발자 님의 블로그


  1. 본인이 사용하는 언어의 Functional Programming(함수형 프로그래밍) 스펙을 예제와 함께 소개해 주세요


함수형프로그래밍(Functional Programming)


함수형 프로그래밍은 대입문 없이 프로그래밍을 하는 것을 의미한다.

반복문에서도 대입이 필요하고 대입이 된다는 것은 데이터를 변환시키는 것으로 반복문을 실행될 때마다 데이터의 변환이 일어난다.

대입없이 상수(Constant)를 인자로 받아서 처음 메모리에 할당하고 할당된 메모리에 데이터를 변경시키지 않는다. 데이터가 변경됨으로 인해 생기는 사이드 이펙트가 발생하지 않는다.

기본적으로 추상화 단계가 높아서 코드의 가독성이 좋지 않다. (이해하기 어려운 코드가 된다.)

Higher-Order Functions

const array =  [1,2,3,4];

const mappedArr = array.map((e) => e*2);

console.log(mappedArr); // [2,4,6,8]

Pure Functions

주어진 Input이 있다면 모든요소가 동등하게 처리되어야하며 사이드 이펙트가 발생하지 않아야한다.

const sum = (a:number, b: number): number => a+b;



  1. (코드 작성) 다음 스펙을 만족하는 delay 함수를 작성해 주세요 (hint: Promise 사용)

    type SomeFunctionReturnString = () => string
    
    function delay(f: SomeFunctionReturnString, seconds: number): Promise<string> {
        // 해당 함수 내부를 구현해 주세요
    };
    
    const success = () => {
      return "successfully done";
    };
    
    const fail = () => {
      throw new Error("failed");
    };
    
    delay(success, 2)
      .then((res) => console.log(res))
      .catch((e) => console.log(e));
    
    delay(fail, 2)
      .then((res) => console.log(res))
      .catch((e) => console.log(e));

    결과값

    $ ts-node delay.ts
    after 2 seconds
    successfully done
    Error: failed


import { response } from 'express';
import { resolve } from 'path';

type SomeFunctionReturnString = () => string;

function delay(f: SomeFunctionReturnString, seconds: number): Promise<string> {
  // 해당 함수 내부를 구현해 주세요
  return new Promise((resolve, reject) => {
    // 2초를 대기한다.
    setTimeout(() => {
      try {
        // 2초 후, 해당함수의 콜백함수 f를 불러와 정상동작하는지 체킹한다.
        resolve(f());

        console.log(`after ${seconds} seconds`);
      } catch (error) {
        // 에러가 있으면, 해당 에러를 매개변수가 e로 전달하여 콜백함수를 불러온다.
        reject(error);
      }
    }, seconds * 1000);
  });
}

const success = () => {
  return 'successfully done';
};

const fail = () => {
  throw new Error('failed');
};

delay(success, 2)
  .then((res) => console.log(res))
  .catch((e) => console.log(e));

delay(fail, 2)
  .then((res) => console.log(res))
  .catch((e) => console.log(e));


try블록 내부의 resolve(f())console.log()의 순서를 바뀌게 되면

에러를 리턴하는 콜벡함수를 실행했을 때도 원하는 결과대로 나오지 않았습니다.

왜 순서를 바꾸면 안되는지에 대한 근거를 찾지 못했습니다. ㅠ.ㅠ

그래도 근거를 찾아 탐구를 해보니

먼저 함수에서 에러나 예외가 발생 없다면, 함수 delay()의 매개변수 f는 함수 suceess() 를 가리킵니다.

이는 "successfully done" 문구를 리턴합니다. resolve()함수가 콜백함수가되며, 이 콜백함수는

then((res) => {...}) 문에서 수행합니다.


반면에 에러가 발생한다면

함수 delay()의 매개변수 f는 함수 fail() 를 가리킵니다.

이는 Error('failed') 에러를 리턴합니다. reject() 함수가 콜백함수가 되며

catch((e) => {...}) 문에서 에러를 핸들링 처리합니다.


  1. 강의를 통해서 기대하는 바, 또는 얻고 싶은 팁을 적어주세요


5번문제를 스스로 풀어보려고 시도하다가 생각보다 쉽게 풀리지 않았고,

나는 아직 함수형 프로그래밍을 제대로 이해하지 못했다는 생각이 들었습니다.

알고있다고 생각했는데 막상 풀어보니 쩔쩔매는 제자신이 정말 부끄러웠습니다.

이 강의를 통해서 함수형 프로그래밍에 대해서 알았으면 좋겠습니다.

실무에서 함수형 프로그래밍이 무엇인지 혼자서는 감이 잡히지 않았습니다.

특히 저는 NestJS 공식문서로부터 독학을 시도를 했으나 어려움이 있었습니다.

이번 프리온보딩을 통해서 실무에서 요구하는 함수형 프로그래밍이 무엇인지 알아가고 싶습니다.