개발자

환경변수 주입 및 빌드(모노레포)

2024년 08월 19일조회 89

모노레포 프로젝트 환경 및 요구사항 - 프로젝트는 front(React), back(Node), common 패키지로 구성되어 있으며, 모노레포로 되어있음 - Dockerfile 스크립트에서는 build → run 순서로 실행되도록 구현되어 있음 - 서버 배포 시에는 하나의 포트만 사용해야 하므로 back(Node)에서 front의 정적 파일(index.html)을 실행해야 함 - Docker 빌드 시, front(webpack 빌드)와 back 둘 다 build 스크립트를 실행하고, 이미지 실행 시에는 back만 run 스크립트를 실행하여 back에서 front의 정적 파일을 실행해야 함 - 환경변수는 이미지 실행 시 docker-compose.yml의 env_file 속성을 사용해 외부에서 주입해야 함(환경변수가 바뀌는 상황이 있다면 .env 파일을 수정한 후 다시 빌드해야 합니다.) 예외 상황 Docker 빌드할 때 .env 파일을 포함하지 않고 run 스크립트를 실행(이미지 실행) 시 주입하는데, front 패키지에는 run 스크립트가 존재하지 않습니다. (back에서 front의 정적 파일을 실행) 즉, 환경변수가 주입되지 않고 있음 해결 방법 첫번째는 back에서 front의 dist 파일 호출 시 환경변수 객체를 만들어 value 값을 key 값으로 치환해서 함께 넘기고, index.html의 head에서 window 객체를 활용해 값을 받는 방법 하지만 이 방법은 개발자 도구에서 환경변수 값이 노출되고, window 객체를 활용하기 때문에 새로운 브라우저를 생성할 때마다 사이드 이펙트가 발생할 수 있음 두번째는 모노레포 root 패키지에서 prerun 스크립트로 front의 build 스크립트를 실행하는 방법 스크립트 -> "prerun": "lerna run build --parallel --scope @projectname/front --stream", 이 방법은 빌드를 두 번 실행하므로 자원을 많이 소모하지만, 예외 상황이 없는 것으로 보임 질문 받은 내용 Q. 환경변수를 바꾸는 상황이 존재할까요? A. 회사의 인프라 환경에 따라 다르지만, 포트나 IP가 변경될 수 있는 상황이 있음 예를 들어, 외부 서버에 요청을 보낼 경우 그 서버의 정보가 바뀌면 설정을 변경해야 하며, 다른 서버에 요청할 때 인증 정보를 입력해야 하는데, 토큰이나 사용자 패스워드 값이 변경될 경우에도 수정이 필요함 고민되는 부분 다른 해결 방법이나 비슷한 상황이 있다면 함께 논의하고 싶습니다. ㅎㅎ *프로젝트 구조 root ├── packages │ ├── back │ │ ├── package.json │ │ ├── index.ts │ │ ├── .babelrc │ │ └── ... │ ├── common │ ├── front │ │ ├── public │ │ │ └── index.html │ │ ├── package.json │ │ ├── src │ │ │ └── index.js │ │ ├── src │ │ ├── webpack.config.js │ │ └── ... ├── package.json ├── lerna.json ├── docker-compose.yml ├── Dockerfile * 프로젝트의 중요 정보는 제외했습니다.

1//window 방식
2const envVars = {__REACT_APP_A__: process.env.__REACT_APP_A || ''}
3//back
4app.get('*', async (req, res) => {
5	const indexFile = path.resolve('../front/dist/index.html');
6        //readFileAndReplaceVars 치환 객체
7        try {
8        const data = await readFileAndReplaceVars(indexFile, envVars);
9		return res.send(data.replace('content=""', 'content=""'));
10        } catch (err) {
11		console.error(err);
12		return res.status(500).send('Internal Server Error');
13       }
14 });
15//front - index.html
16<script>
17	window.__ENV__ = {REACT_APP_A: '__REACT_APP_A__'};
18</script>
이 질문이 도움이 되었나요?
'추천해요' 버튼을 누르면 좋은 질문이 더 많은 사람에게 노출될 수 있어요. '보충이 필요해요' 버튼을 누르면 질문자에게 질문 내용 보충을 요청하는 알림이 가요.

답변 1

성지수님의 프로필 사진

COPY .env ./ -> 이거는 이미 빌드 시점에 프로젝트에 있는 .env 파일을 사용하는 것이고 요구사항에 충족되는 부분은 외부에 있는 .env 파일을 주입하는 것이다. 'process.env':{'REACT_APP_A': JSON.stringify(process.env.REACT_APP_A) ->이부분은 웹팩 빌드 시점에 환경변수를 적용해야 되기 때문에 이미 설정 되어있다.

지금 가입하면 모든 질문의 답변을 볼 수 있어요!

현직자들의 명쾌한 답변을 얻을 수 있어요.

또는

이미 회원이신가요?

AI 답변
커리어리 AI 봇 프로필 이미지

커리어리 AI 봇

GPT가 달아주는 답변입니다.

2024년 08월 19일

이 문제의 해결 방법 중 하나로는 Docker 이미지를 빌드할 때 환경 변수 파일(.env)를 복사하는 것이 있습니다. 따라서, 컨테이너가 시작될 때 해당 환경 변수를 사용하게 됩니다. Dockerfile에 다음과 같은 코드를 추가해 보세요: ``` # Dockerfile ... COPY .env ./ ... ``` 이렇게 하면, 특정 단계에서 환경 변수가 필요할 경우, 해당 단계에서 `.env` 파일을 읽어들여 사용할 수 있습니다. 그러나 이런 접근법은 각 프로젝트/패키지에 독립적인 설정 파일이 필요한 경우 어려움을 초래할 수 있습니다. 대신, 각 패키지의 build script에 필요한 환경 변수를 제공하는 것도 고려해 볼 만합니다. 예를 들어, front 패키지의 webpack 설정에서 `DefinePlugin`을 이용하여 프로세스 환경변수 등을 포함시킬 수 있습니다: ```javascript // webpack.config.js const webpack = require('webpack'); module.exports = { ... plugins: [ new webpack.DefinePlugin({ 'process.env':{ 'REACT_APP_A': JSON.stringify(process.env.REACT_APP_A) } }) ], ... }; ``` 그러면 프론트엔드 코드 내에서 `process.env.REACT_APP_A`와 같은 방식으로 환경변수에 접근할 수 있게 됩니다. 이 접근법은 코드에서 직접적으로 환경 변수를 바라보는 것이므로, 빌드 시점의 값들이 bundle에 포함되게 됩니다. 이와 같은 방법들은 모두 Docker 이미지 빌드 단계에서 환경변수를 처리하는 방식이므로, 이미지를 실행한 후에 환경변수가 변경될 경우 다시 빌드해야 할 필요가 있습니다. 그래서, 이러한 경우에는 Kubernetes와 같은 오케스트레이션 도구나 AWS Parameter Store / Secrets Manager와 같은 서비스를 사용하여 운영환경에서 설정값을 관리하는 것도 고려해 보세요.

목록으로

지금 가입하면 모든 질문의 답변을 볼 수 있어요!