TypeScript + React 에서 .svg .png 그리고 환경 변수 접근하기

정호진·2022년 10월 13일
1

프로젝트

목록 보기
3/8

사건 발단

문제의 시작은 OAuth를 통한 SNS 로그인 구현에 있었습니다. kakao와 google 등 해당 서비스의 로고나 이미지를 .png파일과 .svg파일을 통해 구현했었는데, TypeScript에서 해당 파일을 읽을 수 없다고 나왔습니다. 그래서 해결한 방식이 확장자의 module을 선언한 뒤, 해당 폴더를 컴파일할 때 같이 추가하는 방식으로 선언했었습니다.

// @types/global/index.d.ts
declare module "*.png";
declare module "*.svg" {
  import React = require("react");

  export const ReactComponent: REact.FC<React.SVGProps<SVGSVGElement>>;
  const src: string;
  export default src;
}

그리고 위와같이 생성한 파일을 tsconfig.json에 다음과 같은 형식으로 선언했었습니다.

 "compilerOptions": {
    ...
    "typeRoots": ["@types"]
 	...	
 }

다음과 같이 선언하니 .svg파일도 잘 불러와지고 아주 순탄하지 않을 수 없었습니다.

또다른 문제

OAuth를 구현하다 보면 API keyClient key와 같이 외부에 노출되면 안 되는 값들이 존재합니다. 그리고 그런 값들을 주로 환경 변수로 설정해서 접근합니다. 하지만 여기서 문제가 발생했습니다.

process를 찾을 수 없습니다.

환경 변수라면 전역변수로 선언되어 있어서 어디서든지 접근이 가능하도록 설정되어 있어야 할 텐데 전역변수를 찾을 수 없다고 나오는 겁니다. @types/node를 설치하라는 VsCode의 조언만 있을 뿐이었습니다... (하지만 @types/node는 이미 추가되어 있었습니다.) 인터넷에 열심히 구글링 한 결과, dotenv라는 라이브러리를 다운로드한 다음에 환경 변수를 사용하고자 하는 파일에 다음과 같이 설정하면 된다고 했습니다.

import * as dotenv from "dotenv";
import process from "process";
dotenv.config();

process.env.TEMP_CLIENT_ID

실제로 이렇게 설정하니까 process에 접근이 가능했고 문제가 해결되었습니다. 이제 환경 변수에 접근할 수 있었고, 이미지 구현도 잘 되었습니다. 이렇게까지 구현하고 잠에 들었습니다.
.
.
.

그리고 다음날 다른 작업을 하기 위해 코드를 실행시켜보니 다음과 같은 에러가 발생했습니다.

[Webpack] BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default

해당 에러가 os, fs, stream등에 나타나며 기존에 process에도 접근을 할 수 없다고 나왔습니다. 해당 에러에 대해 검색을 해보니까 webpack 버전 5 이전에는 폴리필 기능을 자동으로 제공했지만, 이후 버전부터는 폴리필을 수동으로 구성해야 한다. 라는 것이 에러의 요지였습니다. CRA를 통해 리액트 프로젝트를 생성한 경우에는 react-script 버전이 자동으로 5이상으로 설치가 됩니다. 즉 위에서 경고한 대로 폴리필을 수동으로 설정해야 했습니다. 이 문제를 나름 간단하게 해결하기 위해서는 react-script의 버전을 5 -> 4로 다운 그레이드 하는 방법이 있다고 제시했습니다.

이전에 carco에러 역시 react-script 버전으로 인해 생긴 문제였기에 버전을 낮춰볼까? 하고 생각을 했지만, 버전을 낮추고 설치해야 하는 라이브러리도 많고, 나는 환경 변수에 접근하려고 하는 것뿐인데 이렇게까지 해야 하나? 라는 생각에 원점으로 돌아가서 생각하게 되었습니다.

딜레마

다른 리액트 프로젝트를 열어서 환경 변수에 접근해 봤는데 그 버전에서는 접근이 잘 되는 것을 보고 도대체 뭐가 문제일까 생각을 했습니다. 그러다 tsconfig파일에 뭔가 차이점이 있을 것 같다 생각을 하고 해당 파일의 옵션에 대한 설명을 찬찬히 찾아봤습니다. 그리고 .svg.png 파일에 접근하기 위해 작성했던 "typeRoots":["@types"]로 인해 환경 변수 접근이 제한된 것을 알게 되었습니다. typeScript 핸드북에 보면 다음과 같이 나옵니다.

@types, typeRoots 및 types (@types, typeRoots and types)
기본적으로 보이는 모든 "@types" 패키지가 컴파일에 포함됩니다.
동봉된 모든 폴더의 node_modules/@types 패키지는 표시된 것으로 간주됩니다.
구체적으로 ./node_modules/@types/, ../node_modules/@types/, ../../node_modules/@types/ 등의 패키지를 의미합니다.
typeRoots를 지정하면 typeRoots 아래에 있는 패키지만 포함됩니다. 예를 들어:

   "compilerOptions": {
       "typeRoots" : ["./typings"]
   }
}

이 설정 파일에는 ./typings의 모든 패키지가 포함되며 ./node_modules/@types의 패키지는 포함되지 않습니다.
types을 지정하면 오직 해당 패키지 목록만 포함됩니다. 예를 들어:

   "compilerOptions": {
       "types" : ["node", "lodash", "express"]
   }
}

이 tsconfig.json은 오직 ./node_modules/@types/node, ./node_modules/@types/lodash 및 ./node_modules/@types/express만 포함합니다.
node_modules/@types/* 아래의 다른 패키지는 포함되지 않습니다.
types 패키지는 index.d.ts 파일이 있는 폴더 또는 폴더에 types 필드를 가진 package.json가 있는 폴더입니다.
"types": []를 지정하면 @types 패키지가 자동으로 포함되지 않습니다.

간략하게 요약하자면, tsconfig 파일에서 typeRoots 혹은 types로 특정 파일 경로를 지정해 버린다면 node_module에서 접근 가능한 값들이 접근이 되지 않는다는 것이었습니다. (전역변수 사용이 불가능하다.)

그래서 이미지를 선택할 것이냐 아니면 환경 변수를 선택할 것이냐라는 양자택일의 상황에 "잠시" 놓였었습니다.

해결

해결 방법은 나름 간단했습니다. tsconfig.json 파일에서 제일 위에서 선언했던 모듈들을 include에 포함하는 것이었습니다.

{
 "include": ["src", "@types"],
}

ts 컴파일러가 ts|tsx 확장을 처리하도록 tsconfig.json에 @types.global을 호출하도록 설정한 것입니다.

탐욕적 접근법으로 당장 문제를 해결하기 위한 빠른 길을 찾다 보니 위와 같은 해프닝이 있었습니다. 물론 알았으면 하지 않았겠지만, 이번 경험을 통해 tsconfig.json 파일 설정에 한발 더 가까워진 느낌입니다.


참조

https://typescript-kr.github.io/pages/tsconfig.json.html
https://bobbyhadz.com/blog/typescript-cannot-find-name-process
https://velog.io/@jaewoneee/Webpack

0개의 댓글