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

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

사전과제 제출 #41

Open beng9re opened 1 year ago

beng9re commented 1 year ago

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

테스트 코드 작성시 한글 메소드를 활용하면 이해하기 더 쉬운 테스트 코드를 작성 할 수 있어서 공유 드립니다.

@DisplayName("Bearer Auth")
@Test
void myInfoWithBearerAuth() {
    //when
    final ExtractableResponse<Response> 토근_로그인_응답 = 토큰_요청("email@email.com", "password");

    //then
    로그인_됨(토근_로그인_응답);
}

public static ExtractableResponse<Response> 토큰_요청(String email, String password) {
    TokenRequest tokenRequest = new TokenRequest(email, password);
    return RestAssured.given().log().all()
            .contentType(MediaType.APPLICATION_JSON_VALUE)
            .body(tokenRequest)
            .when().post("/login/token")
            .then().log().all()
            .extract();
}

private void 로그인_됨(ExtractableResponse<Response> response) {
    assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value());
    assertThat(response.as(TokenResponse.class).getAccessToken()).isNotEmpty();
}

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

계층 아키텍처 패턴의 각 계층에는 애플리케이션 내에서 특정 역할과 책임이 있어 특정 계층에는 특정 행위만 담당함 

레이어드 아키텍쳐 패턴에서의 구성 요소(component)들은 각 레이어에 수평적으로 구조화되어있다. 레이어드 아키텍처 패턴은 정확히 한 패턴에 몇개의 어떤 레이어가 있어야 하는지를 명시하지 않지만, 가장 보편적인 레이어드 아키텍처 패턴은 4개의 레이어로 구성되어있다; presentation, business, persistence, database이다.

    * Presentation layer: UI, 브라우저에서의 유저와의 통신 로직을 다룸.
    * Business layer: 요청에 따른 비즈니스 로직을 다룸.
    * Persistence layer: DAO(Data Access Object) , ORM과 관련된 데이터베이스에 접근해서 데이터를 저장, 수정하는 함수 로직을 다룸.
    * Database layer: 데이터가  저장되어있는 곳. 데이터베이스.

개인적으로 레이어드 아키텍처는 의존성관리와 응집성을 높히는데 중점을 둔다고 생각이 되며 단일책임원칙과 잘어울리는 아키텍처라고 생각이되며
단점으로 레이어(계층)이 늘어날경우 복잡도가 증가할수도 있겠다라는 생각이 듭니다.

참조 
    1. [레이어드 아키텍쳐( Layered Architecture)](https://velog.io/@hojin11choi/TIL-%EA%B3%84%EC%B8%B5%ED%98%95-%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90-Layered-Architecture])
    2. [오레일리](https://www.oreilly.com/library/view/software-architecture-patterns/9781491971437/ch01.html)

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

 DI 의존성주입이란 의존하는 객체가 직접 의존객체를 생성하지 않고 주입(Set나 ,생성자 ,필드 인젝션 등) 주입 받아서 생성되는 형태를 말한다.

-   의존하는 객체란? (예시)

    public class AhasC {
      C c;

      AhasC(){
          // A객체 생성안에서 C를 생성하고 있다 굉장히 강한 의존관계
          c = new C();
      }

    }

    > DI 를 하게 되면 객체 외부에서 객체가 주입하게 되어 객체 생성시점이 아닌 외부에서 생성이 되기 때문에 온전히 객체를 본연의 객체를 생성할 수 있다.  
    > 가령 A라는 객체 안에서 B라는 객체를 생성한다고 가정을 해보자 B라는 객체의 생성 파라미터가 수정이 되었을때 A라는 객체도 수정되어야한다. 이는 단일책임원칙에 위반된다고 생각이 된다.

-   DI 사용한 예시

      public class AhasC {
        C c;
         //C 의객체의 파라미터가 변경되어도 AhasC 객체에는 영향이 없다.
        AhasC(C c){
          this.c = c;
        }
      }

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

JAVA언어의 Functional Programming은 Stream 패키지로 구현할 수 있습니다.
Collections의 요소들을 이용하여 함수형 연산을 지원합니다.

대표적인 함수  

* map(): map()은 스트림이 가진 요소에 정의한 함수를 적용해 새로운 스트림을 반환합니다. 주로 새로운 데이터를 만들어야 할 때 사용합니다.

```java
List<Integer> number = Arrays.asList(1, 2, 3, 4, 5);
// 곱연산된값의 새로운 리스트를 반환 
List<Integer> square = number.stream().map(x -> x * x)
    .collect(Collectors.toList());

filter(): filter()는 스트림이 가진 요소를 정의한 함수를 이용해 선택하고 새로운 스트림을 반환합니다. 주로 특정 값을 찾아야 하는 경우에 사용합니다.

List<String> values = Arrays.asList("aa", "ab", "bb", "ba");
//a가 포함된 문자열을 필터링하여 새로운 리스트를 반환함  
List result = values.stream().filter(value -> value.contains("a"))
    .collect(Collectors.toList());

reduce(): reduce()는 스트림이 가진 요소를 줄이는데(reduce) 사용됩니다. 주로 sum과 같이 결과 값을 산출할 때 사용됩니다.


List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
//합계를 구함 
int result = numbers.stream().reduce(0, (sum, number) -> sum + number);

기본 매커니즘은 Stream 으로 연산을 진행하고 종결 연산자를 통해 새로운 값을 반환하는것이 특징

참조 [Java - Stream API는 함수형 프로그래밍을 할 수 있게 해준다](https://7942yongdae.tistory.com/160)

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


type SomeFunctionReturnString = () => string;

const makeMillisecond = (seconds: number):number => seconds * 1000

function delay(f: SomeFunctionReturnString, seconds: number): Promise<string> {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      try {
        resolve(f());
      } catch (error) {
        if (error instanceof Error) {
          reject(`ERROR :${error.message}`);
        }
      }
    }, makeMillisecond(seconds));
  });
}

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

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

console.log('after 2 seconds');

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

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

이번 강의를 통해 명확하게 객체지향과 함수형 프로그래밍의 차이를 이해하고 함수형 프로그래밍을 통해 어떻게 프로젝트에 적용할지에 대해서 생각해보고 배우는 과정을 기대하고 있으며 어떨때 함수형을 써야할지와 객체지향을 써야할지를 구분하고 싶습니다.