NUMBEL:: 쿠팡 클론 코딩 챌린지 [1회차] - 회고

HYl·2022년 7월 17일
0

1회차 챌린지 주제 : 좋은 모듈 설계와 객체지향

  • 응집도 있는 모듈을 설계하는 것은 유지보수 가능한 코드를 만드는 데에 필수적
  • Service와 useRequest 모듈을 만들어보며 결합과 응집, 그리고 객체지향에 대해 실전적으로 고민

1. Service

Service, http모듈, cookie 모듈 등의 기능을 논리적으로 분리하고 설정하는 것이 핵심이다.

  • http request 전송 기능은 적절히 모듈화 되었는가?
  • Service 객체와 http 모듈의 관계가 논리적인가?
  • cookie 조회/수정 기능은 적절히 모듈화 되었는가?
  • Service 객체와 cookie 모듈의 관계가 논리적인가?
  • 하위 클래스에서의 확장을 고려해 부모 클래스가 적절히 정의되었는가?

2. useRequest

실무에서는 대부분 외부 의존성을 그대로 사용하지 않고 내부에서 새롭게 정의한 인터페이스를 사용한다.
외부 변경으로 인한 영향을 최소화 할 수 있다는 장점이 있다.
이때 큰 비용을 들이지 않고 적용할 수 있도록 간결한 인터페이스를 구현하는 것이 핵심이다.

  • useQuery가 잘 격리되었는가?
  • useRequest는 간결하게 적용할 수 있는가?
    • 결합, coupling이 최소화된 유지 가능한 구조인가?

고민한 부분

리팩토링 할 AuthService는 인증 관련 비즈니스 로직들을 다루는 모듈이다. 리팩토링을 하면서 이후에 재사용성, 확장성을 고려하여 하나의 부모클래스를 extend하는 방법으로 모듈을 설계하는 미션에 어떻게 설계를 해야할지 고민을 하였다.

또한, 하나의 모듈 (= 파일, 클래스, 메소드, 변수)이 하나의 역할만 수행하도록 설계하는 고민을 하였다.

Service

http 통신 기능을 분리해주었다. 다만 추후에 보완을 한다면, Service가 하는 일은 API 요청 전송 외에도 많을텐데, 각각의 auth.service.ts user.service.ts 가 Service를 extend하고 있는 점이 어색한 점이 다분하여 axios 기능을 추상화할 방법을 좀 더 찾아보아야겠다.

import axios from 'axios';
import { AxiosOptions } from '../types/http';

export default class Service {
  async axios(options: AxiosOptions) {
    const { data } = await axios({
      baseURL: process.env.NEXT_PUBLIC_API_HOST,
      ...options,
    });

    return data;
  }
}

TokenProvider

import cookies from 'js-cookie';

type TokenType = 'access' | 'refresh';

class TokenProvider {
  static get(tokenType: TokenType) {
    return cookies.get(tokenType);
  }

  static set(tokenType: TokenType, token: string, expires: number) {
    cookies.set(tokenType + 'Token', token, { expires });
  }

  static hasExist(tokenType: TokenType) {
    return !!cookies.get(tokenType);
  }

  static clear() {
    cookies.remove('accessToken');
    cookies.remove('refreshToken');
  }
}

export default TokenProvider;

useRequest

useRequset hook을 통해 react-query의 useQuery를 격리하였다.

import { useQuery } from 'react-query';

type Options = {
  refetchInterval?: number;
};

export const useRequest = (request: () => {}, options?: Options) =>
  useQuery(request.name, request, { ...options });

마치며 (+ 아쉬운점)

객제지향과 상속에 대한 이론적으로 공부했었던 원리를 내가 직접 class를 설계하는 과정에서 유의미한 부분을 찾아 추상화할지에 대한 고민을 하는 과정에서 객체지향을 몸소 느낄 수 있었다.

axios를 확장성있게 구현하는 과정에서 axios 인스턴스 만들기, 요청 config, 응답 스키마, 인터셉터 등 다양한 기능들을 사용하는 데에 한계가 있었다. 이 기능들을 어떻게 활용할 수 있을지에 대한 부분도 고민을 해보아야겠다.

profile
꾸준히 새로운 것을 알아가는 것을 좋아합니다.

0개의 댓글