TIL. React - Basic 개념 정리(5)

👩🏻‍💻 면접 기출 문제를 준비하면서, React를 이해할 때 반드시 필요한 기본 개념들들 추가로 정리해보았다.

▪️ MVC 디자인 패턴의 React

M(Model)V(View)C(Control) 디자인 패턴은 어플리케이션에서 조금 더 역할에 맞게 세부적으로 레이어를 나누어서 한가지의 역할을 가질 수 있도록 세분화하여 구조적으로 나누는 역할을 한다. MVC 디자인 패턴은 이 구조적인 세분화를 통해서 좀 더 쉬운 유지보수와 테스트가 가능하다. React는 MVC의 'V'(View) 레이어를 담당하고 있는데, View 레이어를 담당하고 있다고 하여서 단순히 사용자에게 데이터를 보여주고 이벤트 자체를 처리하는 부분만을 맡고 있는 것이 아니기 때문에 오히려 세부적으로 나누고 기능별로 또 역할별로 단순화해서 만들어야 한다.

💬 이 component의 문제점은 무엇일까?

const Detail = () => {
  .
  .
  .
  .
  useEffect(() => {
    var requestOptions = {
      method: "GET",
      redirect: "follow",
    };

    fetch(
      "https://youtube.googleapis.com/youtube/v3/videos?part=snippet&chart=mostPopular&maxResults=24&q=MenITrust&key=Key 주소",
      requestOptions
    )
    .
    .
    .
    (github 레포 참고)
    .
    .
    .
};

export default Detail;

이 Detail Component 코드의 문제점 두가지

  1. 코드 안에 중요한 API key가 공개되어 있다는 점
    • 공개적으로 배포하는 일이 있을 때 보안상 큰 문제가 된다.
  2. Component 안에 네트워크 통신을 하는 로직이 들어있다는 점
    • Component를 Unit Test 하기 위해서는 네트워크 통신 부분도 반드시 검사가 필요하다. 만약 comopnent 안에서 바로 네트워크 통신을 하는 로직이 있다면, Unit Test를 할 때마다 네트워크 통신이 발생되는 단점이 있다.

✔️ 해결 방법

가능한 Comoponent를 기능별로 세분화하고 역할 별로 단순화하여 만드는 것을 지향해야 한다. 네트워크 통신 또한 자체적으로 따로 모아서 class를 만들고, 이 class 자체에 필요한 것을 component에 주입해주면 나중에 Unit Test를 할 때엔 실제로 네트워크 통신하는 class가 아니라, 네트워크 통신을 하는 듯이 보이는 mock class 형태가 되므로 굉장히 빠르고 쉽게 Unit Test를 실행할 수 있다. 이러한 방법을 바로 Dependency Injection 이라고 한다.

▪️ Dependency Injection 하는 방법

service라는 폴더 안에 네트워크 통신을 담을 class 파일.js(순수 자바스크립트 확장명으로 지정함)을 만들어보았다.

youtube API KEY 는 보안 상의 문제가 있으므로, API KEY를 .env 파일에 따로 담아놓을 예정이다. 그리고 dependencyInjection class 에서는 constuctor의 props로 (key)를 받고 각 데이터를 처리할 로직을 담아 export 해주었다.

class youtube {
 constructor(key) {
   this.key = key;
   this.getRequestOptions = {
     method: "GET",
     redirect: "follow",
   };
 }

 ------() {
   return fetch(
     `https://youtube.googleapis.com/youtube/v3/videos?part=snippet&chart=mostPopular&maxResults=24&q=MenITrust&key=${this.key}`,
     this.getRequestOptions
   )
   .
   .
   .
   (github 레포 참고)
 }

 ------(query) {
   return fetch(
     `https://youtube.googleapis.com/youtube/v3/search?part=snippet&maxResults=24&q=${query}&type=video&key=${this.key}`,
     this.getRequestOptions
   )
   .
   .
   .
   (github 레포 참고)
 }
}

export default youtube;

create react-app 에서 제공하는 방법(Environment Variables)을 참고하여 최상위에서 .env(환경파일)을 만든 뒤에

API KEY 주소 앞에 REACT_APP_YOUTUBE_API_KEY 변수 선언을 해주었다.

REACT_APP_YOUTUBE_API_KEY=Key 주소

가장 최상위 파일인 index.js에 new를 사용하여 process.env.REACT_APP_YOUTUBE_API_KEY 를 인자로 받은 오브젝트를 새로이 변수 선언을 해주고, Detail component에 props으로 youtube를 전달해주었다.

import Youtubes from "./service/youtube";

const youtube = new Youtubes(process.env.REACT_APP_YOUTUBE_API_KEY);

ReactDOM.render(
  <React.StrictMode>
    <Detail youtube={youtube} />
  </React.StrictMode>,
  document.getElementById("root")
);

Detail component는 index.js로부터 전달받은 props인 youtube를 인자로 받은 뒤에 각 데이터를 가져와 setVideos 라는 useState에 그대로 전달 받았다.

function Detail({ youtube }) {
  const [videos, setVideos] = useState([]);
  const search = (query) => {
    youtube
      .------(query) //
      .then((videos) => setVideos(videos));
  };

  useEffect(() => {
    youtube
      .------() //
      .then((videos) => setVideos(videos));
  }, []);

  return (
    .
    .
    .
  );
}

export default Detail;

API KEY를 담아둔 .env 파일은 git에 업로드 되지 않도록 반드시 .gitignore 파일에 주석설명을 달아서 작성해줘야 할 것이다.

#API KEYs
.env

▪️ 추가적으로 리팩토링 해주기

Youtube class에서 각각 API를 받는 함수에서 warning 표시가 뜨는 것을 확인했다. 이때 Promise를 return 하고 있으니, async를 쓰라고 vscode에서 자체적으로 제안을 해준 것이다. 아무래도 수정을 하는 것이 좋을 것 같다!

warning 표시가 뜬 함수명을 클릭해보면 창이 뜨고 Quick Fix라는 버튼이 나오는데 이것을 누르면 자동으로

async 문법으로 자동으로 변환되는 것을 확인할 수 있었다.

async ------() {
    const res = await fetch(
      `https://youtube.googleapis.com/youtube/v3/videos?part=snippet&chart=mostPopular&maxResults=24&q=MenITrust&key=${this.key}`,
      this.getRequestOptions
    )
    .
    .
    .
  }

  async ------(query) {
    const response = await fetch(
      `https://youtube.googleapis.com/youtube/v3/search?part=snippet&maxResults=24&q=${query}&type=video&key=${this.key}`,
      this.getRequestOptions
    )
    .
    .
    .
  }
}

이처럼 키워드가 바로 앞에 있으니 API를 볼 때 안의 구현사항을 굳이 살피거나 확인하지 않아도 Promise를 Return 한다는 것을 명시적으로 알 수 있기 때문에 보통 async를 사용하기를 권장하고 있다.

출처 :
이 포스팅은 드림코딩의 [리액트] 강의를 기반으로 작성했습니다.
https://academy.dream-coding.com/

좋은 웹페이지 즐겨찾기