Typescript and React .env

gjeon·2021년 12월 27일
5

TypeScript

목록 보기
2/2
post-custom-banner

react & typescript 에서 .env 환경변수 파일을 사용하려 하는데 왜 .env 내용이 자동완성이 안될까 싶어서 찾게되었다.

//.env.development
REACT_APP_TEST=hello
//src/App.tsx
function App() {
  	console.log(process.env.REACT_APP_TEST);
	return null;
}

export default App;

.env.development 파일을 수정후 react를 재실행하고 process.env.REACT_APP_TEST 를 하면 값이 제대로 나오긴 하는데 자동완성은 안된다.
모듈을 사용해야되는건가 싶어서 이것저것 해보다가 react-app-env.d.ts 파일을 사용하여 나타내는 방법을 알게되었다.

d.ts

우선 d.ts 파일은 선언 파일로 typescript 코드의 타입 추론을 돕는 파일이다.
예를 들면 전역 변수로 선언한 변수를 특정 파일에서 import 구문 없이 사용하는 경우 해당 변수를 인식하지 못한다. 그럴 때 아래와 같이 해당 변수를 선언해서 에러가 나지 않게 할 수 있다.

declare const global = 'sth';

해당 타입 스크립트 파일에서 사용할 순 있지만 선언되어 있지 않은 전역 변수나 전역 함수는 아래와 같이 타입을 선언할 수 있다.

// 전역 변수
declare const pi = 3.14;

// 전역 함수
declare namespace myLib {
  function greet(person: string): string;
  let name: string;
}
myLib.greet('캡틴');
myLib.name = '타노스';

출처

위와 같은 특성으로 d.ts 파일을 사용하여 전역 변수의 타입을 선언할 수 있다.

react-app-env.d.ts

CRA?
create-react-app 을 줄여서 CRA라고 많이 부른다.
리액트를 개발한 페이스북에서 만든 리액트 프로젝트용 보일러플레이트라고 생각하면 되는데, 지속적인 패키지들의 버전업과 리액트의 버전업이 활발히 일어나다 보니 자신만의 보일러플레이트를 가지고 있다고 해도 결국 패키지들의 업데이트에 맞춰 지속적인 관리도 해주게 되고 새로운 기술 또는 아키텍처가 생기면 구조변경을 해야하는 경우도 생기기 마련이라 금방 레거시 프로젝트가 된다. 하지만 CRA를 쓰면 리액트의 지속적인 업데이트를 페이스북에서 주관을 하고있고, 그에 맞춰 페이스북에서 이러한 CRA 보일러플레이트를 업데이트를 시켜줍니다. (출처)
(CRA가 없다면 우리는 바벨, eslint, 웹팩등을 직접 하나하나 설치하고 해당 파일을 일일히 설정 해주어야 할 것이다(출처))

보일러플레이트
보일러플레이트 또는 보일러플레이트 코드라고 부르는 것은 최소한의 변경으로 여러곳에서 재사용되며, 반복적으로 비슷한 형태를 띄는 코드를 말한다.

CRA를 사용하여 React app을 생성하면 src 폴더에 react-app-env.d.ts 파일이 생성되는것을 볼 수 있다. 뭔지 몰라서 그냥 지나치곤 했는데 해당 파일을 살펴보면 아래와 같이 작성되어있는것을 볼 수 있다.

//.src/react-app-env.d.ts
/// <reference types="react-scripts" />

위의 코드를 힌트로 해당 경로에 가면 아래의 파일이 있는데

//.node-modules/react-scripts/lib/react-app.d.ts
/// <reference types="node" />
/// <reference types="react" />
/// <reference types="react-dom" />

declare namespace NodeJS {
  interface ProcessEnv {
    readonly NODE_ENV: 'development' | 'production' | 'test';
    readonly PUBLIC_URL: string;
  }
}

declare module '*.avif' {
  const src: string;
  export default src;
}

declare module '*.bmp' {
  const src: string;
  export default src;
}

declare module '*.gif' {
  const src: string;
  export default src;
}

declare module '*.jpg' {
  const src: string;
  export default src;
}

declare module '*.jpeg' {
  const src: string;
  export default src;
}

declare module '*.png' {
  const src: string;
  export default src;
}

declare module '*.webp' {
    const src: string;
    export default src;
}

declare module '*.svg' {
  import * as React from 'react';

  export const ReactComponent: React.FunctionComponent<React.SVGProps<
    SVGSVGElement
  > & { title?: string }>;

  const src: string;
  export default src;
}

declare module '*.module.css' {
  const classes: { readonly [key: string]: string };
  export default classes;
}

declare module '*.module.scss' {
  const classes: { readonly [key: string]: string };
  export default classes;
}

declare module '*.module.sass' {
  const classes: { readonly [key: string]: string };
  export default classes;
}

여러 파일 확장자들에 대한 타입이 선언되어 있는것을 볼 수 있고 이를 react-app-env.d.ts에서 참조하는 것으로 유추할 수 있다.
이때 상단의 코드를 살펴보면

declare namespace NodeJS {
  interface ProcessEnv {
    readonly NODE_ENV: 'development' | 'production' | 'test';
    readonly PUBLIC_URL: string;
  }
}

process.env. 을 적었을때 자동완성되는 환경변수들을 볼 수 있다.
CRA의 typescript 지원은 NodeJS 네임스페이스 아래의 확장된 정의를 사용하는 것이라 한다.
이것을 우리의 환경에 맞게 확장해주면 된다.

사용하기

//.src/react-app-env.d.ts
/// <reference types="react-scripts" />

declare namespace NodeJS {
	interface ProcessEnv {
      		NODE_ENV: 'development' | 'production' | 'test';
      		PUBLIC_URL: string;
      		REACT_APP_TEST: string;
	}
}

위와 같이 저장한뒤에 process.env.을 작성하면 REACT_APP_TEST를 자동완성하여 사용할 수 있다.

Reference

https://dev.to/louisgv/typescript-and-create-react-app-env-136e
https://velog.io/@swanious/TIL-.d.ts%ED%8C%8C%EC%9D%BC%EC%97%90%EC%84%9C-reference-typesreact-scripts%EC%9D%B4-%EB%AD%98%EA%B9%8C
https://code-anthropoid.tistory.com/275
https://joshua1988.github.io/ts/usage/declaration.html#%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%84%A0%EC%96%B8-%ED%8C%8C%EC%9D%BC
https://fe-churi.tistory.com/33
https://jaewook.me/create-react-app-typescript-window-object
https://charlezz.medium.com/%EB%B3%B4%EC%9D%BC%EB%9F%AC%ED%94%8C%EB%A0%88%EC%9D%B4%ED%8A%B8-%EC%BD%94%EB%93%9C%EB%9E%80-boilerplate-code-83009a8d3297

profile
개발자 되기
post-custom-banner

1개의 댓글

comment-user-thumbnail
2022년 2월 15일

딱 궁금했던 내용인데 글 작성해주셔서 감사합니다 ! 좋은 정보 얻어가요 🙂

답글 달기