[React]-DI(Dependency Injection)의존성 주입으로 리팩토링 해보자!

badassong·2023년 5월 21일
0

React

목록 보기
51/56
post-thumbnail

이전 포스트에서 context api를 통해 충분히 깔끔한 코드로 리팩토링 했지만,
youtube.jsfakeYoutube.js에서의 코드 중복은 어떻게 해결할 수 있을까?

방법은, DI(Dependency Injection)을 하는 것이다!

실제 api를 호출하는 client, mock data를 호출하는 client를 각각 따로 만들어서 각각 다른 client를 사용하는 youtube class로 만들어주면 된다.

우선 youtube.js를 복사해서 youtubeClient.js로 바꿔주고, fakeYoutube.js를 복사해서 fakeYoutubeClient.js로 바꿔준다.

그럼 client가 두개 생성되는 것이다.

이제 youtube.js에서 client를 내부적으로 만드는 것이 아니라, 외부로부터 받아오게 한다. 이 말은 즉 필요한 dependency를 주입 받는다는 의미이다. 그리고 이것이 바로 DI!

// youtube.js

export default class Youtube {
  constructor(apiClient) {
    this.apiClient = apiClient;
  }

  async search(keyword) {
    return keyword ? this.#searchByKeyword(keyword) : this.#mostPopular();
  }

  async #searchByKeyword(keyword) {
    return this.apiClient
      .search({
        params: {
          part: "snippet",
          maxResults: 25,
          type: "video",
          q: keyword,
        },
      })
      .then((res) => res.data.items)
      .then((items) => items.map((item) => ({ ...item, id: item.id.videoId })));
  }

  async #mostPopular() {
    return this.apiClient
      .videos({
        params: {
          part: "snippet",
          maxResults: 25,
          chart: "mostPopular",
          regionCode: "KR",
        },
      })
      .then((res) => res.data.items);
  }
}

이렇게 기존의 코드를 수정해준다!

// youtubeClient.js

import axios from "axios";

export default class YoutubeClient {
  constructor() {
    this.httpClient = axios.create({
      baseURL: "https://www.googleapis.com/youtube/v3",
      params: { key: process.env.REACT_APP_API_KEY },
    });
  }

  async search(params) {
    return this.httpClient.get("search", params);
  }

  async videos(params) {
    return this.httpClient.get("videos", params);
  }
}

이렇게 params를 전달받으면 this.httpClientget 요청을 해주고, search인지 videos인지에 따라 key를 붙여주고 전달받은 params를 전달해서 axios를 사용하도록 만든다.

fakeYoutubeClient.js도 같은 방식으로 만든다.

// fakeYoutubeClient.js

import axios from "axios";

export default class FakeYoutubeClient {
  async search() {
    return axios.get("/data/search.json");
  }

  async videos() {
    return axios.get("/data/popular.json");
  }
}

fake에서는 constructor가 필요없고 search인지 videos인지에 따라 json파일만 get하면 된다.

마지막으로 context파일에서

// YoutubeApiContext.jsx

const client = new FakeYoutubeClient();
// const client = new YoutubeClient();
const youtube = new Youtube(client);

client 인스턴스를 각각 만들어서 상황에 맞게 사용해주면 된다!

이전 방법까진 이해가 어느정도 됐는데 의존성 주입이라는 개념이 더해지니 아직까진 생소하게 느껴진다..ㅠ 개념에 대해서 더 공부 해야겠다..!

profile
프론트엔드 대장이 되어보쟈

0개의 댓글