작은프론트이야기

React 프로젝트 보안 강화 난독화 및 소스코드 비노출 처리 본문

문제 해결

React 프로젝트 보안 강화 난독화 및 소스코드 비노출 처리

돌핀코딩 2025. 5. 21. 10:50

최근 기존에 개발된 React 기반 프로젝트를 유지보수하면서, 중요한 보안 이슈 하나를 발견했었다.

바로 브라우저 개발자 도구로 소스코드가 거의 원본 수준으로 노출된다는 점이었다.

이 글은 해당 문제를 해결하기 위해 난독화를 도입한 과정을 공유하기 위해 작성했다.


문제 인식

처음 프로젝트를 인수받았을 때는 기능적으로 큰 문제가 없었다. 하지만 개발자 도구에서 Sources 탭을 통해 번들된 JavaScript 파일을 확인해보니

  • 함수명, 변수명, GraphQL 요청 구조가 모두 그대로 노출됐었다
  • 로그인, 인증, 데이터 처리 흐름까지 분석이 가능한 수준이었다

즉, 누구나 손쉽게 주요 로직을 추적하고 분석할 수 있는 위험한 구조였다는 점을 인지했었다.


난독화 전략 수립

  • 기존 아키텍처를 해치지 않으면서 난독화를 적용하고자 했다
  • CRA 기반 구조이므로 Webpack 설정은 react-app-rewired로 우회하도록 했다
  • 빌드 환경별(dev, qa, op 등)로 난독화가 포함되도록 구성했었다

개발 환경 구성

1. react-app-rewired 설치 및 적용

npm install --save react-app-rewired
package.json 스크립트를 수정
"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test",
  ...
}

 

2. JavaScript Obfuscator 패키지 설치

npm install --save-dev javascript-obfuscator webpack-obfuscator

 

3. config-overrides.js 추가

const JavaScriptObfuscator = require('webpack-obfuscator');

module.exports = function override(config, env) {
  if (env === 'production') {
    config.plugins.push(
      new JavaScriptObfuscator(
        {
          compact: true,
          rotateStringArray: true
        },
        ['excluded_bundle_name.js'] // 제외할 파일 이름
      )
    );
  }
  return config;
};
controlFlowFlattening, deadCodeInjection 같은 고강도 설정은 Apollo, React Hook 구조와 충돌 가능성이 있어 사용하지 않았었다.

브랜치별 환경 빌드 및 배포

이 프로젝트는 GitLab CI 환경과 연동되어 있어, 환경별 브랜치(dev, qa, op 등)에 소스를 push하면 자동으로 해당 브랜치에 맞는 .env 파일이 적용되어 빌드가 진행되도록 구성돼 있었다.

CI 파이프라인에서 react-app-rewired build 명령을 실행하면서, config-overrides.js에 설정된 난독화 로직이 자동으로 적용되었다.

이로 인해 개발자는 별도로 로컬에서 빌드 명령을 실행할 필요 없이, 브랜치에 코드만 push해도 난독화된 JS가 자동으로 빌드되고 S3로 배포되는 구조를 완성했었다.

이러한 자동화 구조 덕분에 소스코드 노출 없이 안정적으로 환경별 난독화 배포를 운영할 수 있었다.

npm run build:dev
npm run build:qa
npm run build:op

 


적용 결과

  • 개발자 도구에서 소스코드 추적이 불가능해졌다
  • 함수명, 변수명, 문자열 등 모두 압축/축약 처리됐다
  • GraphQL 요청 구조, 인증 로직이 외부에 노출되지 않게 됐다