개발일지

FE에서 OOP(Class)의 대한 고민 (Typescript + Next.js)

FE 2022. 6. 17. 16:08

 

다들 프론트엔드에서의 OOP(객체지향 프로그래밍) 어떻게 생각하시나요?

 

https://www.youtube.com/watch?v=1V6mQom0paI&ab_channel=%EA%B0%9C%EB%B0%9C%EB%B0%94%EB%8B%A5 

 

관련해서 개발바닥 유튜브 영상도 정말 재밌게 봤던 것 같습니다.

 

클래스에 대한 고민은 제가 타입스크립트를 도입하면서 같은 Url Prefix를 사용하는 Api들을 어떻게 묶어볼 수 없을까?부터 시작되었는데요. 레퍼런스가 많이 없기도 하고 실제로 FE에서는 FP가 더 중심적이고 OOP에 대해서 많은 고민과 고찰이 없었던 것도 사실인 것 같습니다. 굳이 필요한가?란 생각도 있구요. 그래서 더더욱 클래스를 도출하기까지 시간이 좀 걸린 것 같기도 합니다. 당연히 클래스만 쓴다고 OOP도 아니기도 하고요. 

 

이번엔 부분적으로 API에 대해서 클래스로 도입해본 후기를 작성해보겠습니다. (대단한 클래스 설계도 아니고 정말 간단한 수준입니다.)

 

export const getInvest = async () => {
  return $axios.get("/v1/test/me");
};

export const postInvestPrivacy = async (props) => {
  return $axios.post("/v1/test/privacy", props);
};

export const putInvestPrivacy = async (props) => {
  const { id } = props;
  delete props.id;
  return $axios.put(`/v1/test/privacy/${id}`, props);
};

 

예를 들어 이렇게 test라는 url로 묶은 api가 10개가 있다고 가정해봅시다. test라는 api가 계속해서 확장되고 기능이 추가됨에 따라 계속 필요한 api를 작성해나가겠죠. 근데 여기에서 이러한 방식으로 계속 추가를 하기보다는 같은 Url Prefix를 사용하는 Api를 모듈화 하고 싶었습니다. 그 생각에서 확장된게 클래스형으로 Api를 설계해보면 어떨까?였습니다. 설계라고 해서 거창한건 아니고 클래스형으로 Api를 묶고 사용하는 곳에서 클래스만 import해서 사용하는 방식이긴 합니다.

 

class InvestorApiService {
  url: string;
  constructor(url: string) {
    this.url = url;
  }
  getRefundAccountInfo = async () => {
    const res = await $axios.get<GetInvestorWithdrawalResponse>(`${this.url}/test2/test3`);
    return res.data;
  };

  postNameCertificationInfo = async (props: InvestorPrivacyRequest) => {
    return $axios.post<InvestorPrivacyResponse>(`${this.url}/test2`, props);
  };

}
export const investorApiService = new InvestorApiService("/v1/test");

 

이렇게 class형으로 Api를 묶으면 어떤 이점이 있었냐?

 

  1. import를 계속 할 필요 없이 클래스만 import 하면 되기 때문에 import 이점이 있습니다. 
  2. .을 찍으면 사용할 수 있는 Api들이 모두 나오기 때문에 자동완성의 이점이 있습니다. (타입스크립트를 사용하며 느끼는 장점과 비슷)

그리고 Api는 바뀔일이 많이 없기 때문에 한번 만들어두면 계속해서 쓸 수 있을거라고 생각했습니다. 근데 여기서 한 가지 드는 의문이 있었습니다. 왜 프론트에서는 OOP가 각광받지 못했을까?란 생각이 들면서 계속해서 생각이 확장되더군요.

 

여러 레퍼런스를 찾아보기도 했고 비판적인 시선도 궁금하여 메일도 보내보고 했습니다. 그러던 중 제가 생각하지 못한 부분의 대해 알 수 있게 되었는데 클래스는 TreeShaking을 할 수 없으며 minify에 약하다는 점입니다. 이는 번들 크기가 커지게 되는 단점이 있습니다. 결과적으로 클래스는 클래스 안에 코드들을 뭉탱이로 불러오기 때문에 번들 덩치가 커지게 됩니다.

 

즉, 페이지에서 필요한것만 사용하는 것이 아닌 클래스를 불러옴으로 인해서 안쓰는 코드들이 다 같이 불러오게 되고 이는 덩치가 커질수록 번들 사이즈에 대한 고민이 생겨버리는 것이죠.

 

그러면 적절히 클래스형과 함수형을 필요한곳에 쓰면서 같이 공존할 수는 없는걸까?란 생각도 자연스럽게 들었습니다. OOP의 대한 관점이 FE에서는 복잡성을 야기할 수 있고 함수형으로 조립하는게 훨씬 더 간편하고 실제 그렇게 사용하는것이 보편화 되어 있으니까요!

 

결국 크기가 작고 메소드 활용을 거의 다하는 class(유틸성 class)라면 문제가 되지 않겠지만 덩치가 큰 녀석들은 class로 하나로 묶기보다는 개별 함수를 export 하여 사용하는 것이 괜찮지 않을까?란 생각을 해봅니다.