← 모두의 툴

JS 압축기의 문자열 손상 위험, 경고는 엉뚱한 곳에 뜬다

가이드 · 2026.08.25 최종 확인

정규식만으로 주석과 공백을 지우는 압축기는 SQL 압축기의 -- 버그, GraphQL 압축기의 # 버그와 같은 종류의 함정을 안고 있습니다. 문자열 리터럴 경계를 인식하지 못하면, 문자열 안에 우연히 주석처럼 보이는 패턴이 들어있을 때 그 내용을 진짜 코드로 착각해 지워버릴 수 있습니다. JS 압축기의 실제 소스를 함수 단위로 읽어 어느 옵션이 이 함정에 걸리고 어느 옵션이 걸리지 않는지 확인했습니다.

1. 정규식 압축의 근본적인 문제

프로그래밍 언어의 문법을 제대로 파싱하려면 문자열 리터럴이 시작되고 끝나는 지점을 추적해야 합니다. "http://example.com"이라는 문자열 안의 //는 주석이 아니라 그냥 텍스트지만, 문자열 경계를 모르는 정규식 입장에서는 코드 전체가 평평한 텍스트일 뿐이라 이 둘을 구분할 방법이 없습니다. 안전한 압축기는 보통 문자열·템플릿 리터럴을 먼저 플레이스홀더로 치환해 보호한 다음 주석·공백을 제거하고, 마지막에 다시 복원하는 순서를 씁니다. 이 도구가 실제로 그런 보호 단계를 거치는지 소스를 직접 읽어봤습니다.

2. 5가지 옵션, 실제로는 안전도가 다 다르다

결론부터 말하면 5개 옵션 중 하나만 문자열을 인식하고 나머지 4개는 인식하지 않습니다.

옵션구현 방식문자열 보호 여부
// 주석 제거문자 단위 스캐너(stripLineComments)보호됨 — 따옴표를 만나면 이스케이프까지 인식하며 문자열 전체를 건너뜀
/* */ 주석 제거정규식 /\/\*[\s\S]*?\*\//g를 원문 전체에 바로 적용보호 안 됨
줄바꿈 제거정규식 /\r?\n/g를 원문 전체에 적용보호 안 됨
연속 공백 제거정규식 /\s{2,}/g를 원문 전체에 적용보호 안 됨
연산자 주변 공백 제거정규식으로 =,+,-,쉼표,괄호 등 주변 공백 제거보호 안 됨

// 주석 제거만 따옴표(", ', `)를 만나면 그 문자열을 통째로 건너뛰는 문자 단위 루프로 짜여 있어, 문자열 리터럴 안의 //는 실제로 안전합니다. 반면 나머지 4개 옵션은 전부 원본 텍스트에 정규식을 그대로 적용하는 방식이라 문자열 경계라는 개념 자체가 없습니다.

3. 코드로 직접 재현: http:// URL은 의외로 안전하다

가장 흔히 걱정하는 케이스인 const url = "http://example.com"; // 여기까지 같은 코드를 넣어 봤습니다.

입력: const url = "http://example.com"; // 여기까지
출력: const url="http://example.com";
URL 문자열 안의 //는 그대로 남고, 진짜 줄 끝 주석(// 여기까지)만 정확히 제거됩니다.

이건 stripLineComments가 따옴표를 만나면 그 안의 모든 문자(이스케이프 포함)를 그대로 통과시키고 닫는 따옴표에서만 "문자열 종료"로 인식하기 때문입니다. 즉 가장 널리 알려진 위험 시나리오는 이 도구에서 실제로는 처리되어 있습니다.

4. 진짜 위험한 케이스: 블록 주석 정규식

반대로 /* */ 주석 제거는 문자열 여부를 전혀 구분하지 않으므로, 문자열 값 안에 우연히 /**/가 둘 다 들어있으면 그 사이 내용이 실제로 삭제됩니다.

입력: const note = "/* 이건 그냥 문자열 */";
출력: const note="";
문자열 값이 완전히 비어버립니다 — 프로그램은 오류 없이 조용히 다른 값을 담게 됩니다.

연산자 주변 공백 제거, 줄바꿈 제거, 연속 공백 제거도 같은 이유로 위험합니다. 예를 들어 문자열 값이 "a = b"라면 연산자 공백 제거 정규식이 이를 "a=b"로 바꿔버릴 수 있습니다. 코드 밖에서는 스타일 차이일 뿐이지만 문자열 "값" 자체가 바뀌는 것이므로 데이터 손상입니다.

5. 화면 경고는 왜 엉뚱한 곳에서 뜨는가

이 도구는 optLineComments가 켜져 있을 때 /["'`].*\/\//.test(j)라는 별도의 정규식으로 "문자열 안에 // 가 있는지"를 검사해서 경고 배너를 띄웁니다. 그런데 앞서 확인했듯 // 주석 제거 자체는 문자열을 안전하게 건너뛰는 방식이라, 이 경고가 뜨는 상황은 사실 이미 안전하게 처리되고 있는 경우입니다. 반대로 진짜 위험한 블록 주석 정규식, 줄바꿈·공백·연산자 정규식에는 이런 검사 로직 자체가 아예 없어서 문자열이 실제로 손상되는 순간에는 어떤 경고도 뜨지 않습니다. 경고 시스템과 실제 위험이 서로 다른 곳을 가리키고 있는 셈입니다.

6. 실무에서는 어떻게 압축해야 하나

이 도구는 정규식 리터럴(/.../)을 별도로 인식하는 코드도 없어서, 정규식 패턴 안에 공백이나 하이픈처럼 연산자 문자 클래스에 포함된 기호가 있으면 코드와 똑같이 지워질 수 있습니다. 변수명 단축(맹글링)도 지원하지 않습니다. 간단한 스니펫을 빠르게 줄여보는 용도로는 적합하지만, 실제 배포용 코드라면 실제 파서로 문자열·정규식·주석을 정확히 구분하는 Terser, esbuild, webpack 같은 AST 기반 도구를 쓰는 것이 안전합니다. 반대로 JSON처럼 문자열 안에 ///*가 나올 일이 거의 없는 포맷을 압축한다면 JSON 압축기가 더 예측 가능하고, CSS나 HTML을 다룬다면 각각 CSS 압축기, HTML 압축기를 쓰는 편이 이런 언어별 함정에서 자유롭습니다. 압축을 풀어 원래 형태로 되돌려야 할 때는 JS 정렬기를 참고하세요.

자주 묻는 질문

Q. URL 문자열이 있는 코드를 압축해도 안전한가요?

// 주석 제거 옵션 자체는 문자 단위 스캐너라 http:// 같은 URL 문자열은 안전하게 보존됩니다. 다만 같은 코드에 블록 주석 제거·공백 제거 옵션이 함께 켜져 있으면 그쪽 정규식은 문자열을 구분하지 못하므로 별개로 주의해야 합니다.

Q. 화면에 경고가 안 떴다면 안심해도 되나요?

아니요. 경고는 "문자열 안에 // 가 있는지"만 검사하며, 정작 더 위험한 블록 주석·공백·연산자 정규식에는 검사 로직이 없습니다. 경고가 없다고 문자열이 손상되지 않았다는 보장은 없습니다.

Q. 정규식 리터럴이 포함된 코드는 어떻게 되나요?

이 도구는 정규식 리터럴(/.../)을 별도로 인식하지 않으므로, 정규식 패턴 안에 공백이나 하이픈이 있으면 일반 코드와 똑같이 처리되어 패턴이 바뀔 위험이 있습니다.

Q. 그럼 이 도구는 언제 쓰는 게 맞나요?

문자열 안에 /*, */, 연산자 기호가 들어갈 일이 거의 없는 짧고 단순한 스니펫을 빠르게 확인할 때는 무리 없습니다. 실제 프로덕션 배포 코드처럼 손상되면 안 되는 코드라면 Terser·esbuild 같은 AST 기반 도구를 쓰세요.