[EXT-030][실무] 바꿀 문장의 달러 기호 안전하게 다루기 > IT 기술 공유

본문 바로가기
사이트 내 전체검색

IT 기술 공유

[EXT-030][실무] 바꿀 문장의 달러 기호 안전하게 다루기

페이지 정보

profile_image
작성자 기술팀장
댓글 0건 조회 3회 작성일 26-09-08 20:35

본문

[이번 수업]
자바스크립트 replace()에서 사용자가 입력한 문장을 바꿀 값으로 쓸 때 달러 기호가 뜻밖의 결과를 만드는 이유와 해결법을 배웁니다. 치환 문자열에는 `$&`, `$1`처럼 특별한 토큰이 있습니다. 사용자 문장을 그대로 두 번째 인수에 전달하지 않고 함수를 사용하면 반환값을 문자 그대로 넣을 수 있습니다.

[선수지식]
문자열, 함수, 정규식의 괄호가 일치한 부분을 묶는 캡처 그룹이라는 점을 알고 있으면 됩니다. EXT-029에서 동적 검색어를 RegExp.escape()로 처리하는 방법을 익혔다면 검색 패턴과 치환값의 규칙이 서로 다르다는 점에 주목하세요.

[학습목표]
1. 문자열 치환과 함수형 치환의 차이를 설명할 수 있습니다.
2. 사용자 입력에 있는 달러 토큰을 문자 그대로 삽입할 수 있습니다.
3. replace(), replaceAll(), 정규식 플래그의 역할을 구분할 수 있습니다.

[핵심개념]
replace(searchValue, replaceValue)의 replaceValue가 문자열이면 자바스크립트는 이를 단순한 글자 묶음이 아니라 치환 템플릿으로 읽습니다. `$&`는 일치한 전체 문자열, `$1`부터 `$99`는 번호가 붙은 캡처 그룹, `$<name>`은 이름 있는 캡처 그룹을 뜻합니다. `$$`는 달러 기호 하나가 되고, `$` 뒤의 백틱과 작은따옴표도 각각 일치 앞부분과 뒷부분을 가리킵니다.

반면 두 번째 인수가 함수이면 엔진은 일치한 내용과 캡처, 위치, 원문 등을 함수에 넘긴 뒤 반환값을 문자열로 바꿔 그대로 삽입합니다. 반환값 안의 `$&`나 `$1`은 다시 해석되지 않습니다. 따라서 외부에서 받은 표시 문구를 그대로 넣어야 할 때 `() => userReplacement` 형태가 명확합니다. 검색 패턴을 안전하게 만드는 RegExp.escape()와 치환값을 문자 그대로 넣는 함수형 치환은 서로 다른 자리의 문제를 해결합니다.

[따라하기]
아래 코드를 replace-literal.js로 저장하세요. 별도 패키지는 필요 없습니다.

```javascript
const input = '상품명: red';
const userReplacement = '$& (할인 $1)';
const pattern = /(red)/u;

const templateResult = input.replace(pattern, userReplacement);
const literalResult = input.replace(pattern, () => userReplacement);

console.log(templateResult);
console.log(literalResult);
```

Windows PowerShell, macOS 터미널, Linux 셸에서 모두 `node replace-literal.js`로 실행합니다. 예상 결과는 다음과 같습니다.

```text
상품명: red (할인 red)
상품명: $& (할인 $1)
```

첫 줄에서는 `$&`와 `$1`이 모두 red로 해석됐습니다. 둘째 줄에서는 함수가 돌려준 문장이 그대로 들어갔습니다. 같은 패턴을 모두 바꾸려면 정규식에 `g` 플래그를 붙이거나 문자열 검색과 replaceAll()을 사용하세요. replace()는 일반적으로 첫 번째 일치만 바꿉니다.

[흔한 실수]
첫째, 모든 `$`를 `$$`로 바꾸려다가 이미 들어 있던 여러 달러와 토큰 경계를 잘못 처리합니다. 문자 그대로 삽입하려면 함수가 더 읽기 쉽습니다. 둘째, `RegExp.escape(userReplacement)`를 호출합니다. 이 함수는 검색 패턴용이며 치환값용이 아닙니다. 셋째, 함수형 치환에서 `userReplacement` 대신 콜백의 첫 인수만 반환해 원래 일치 문자열을 다시 넣습니다. 넷째, 여러 건을 바꿔야 하는데 `g`나 replaceAll()을 빼먹습니다.

[보안 주의]
함수형 치환은 달러 토큰의 오해석을 막지만 HTML, SQL, 셸, URL의 출력 규칙까지 해결하지 않습니다. 결과를 HTML에 표시하거나 데이터베이스 질의에 쓰는 단계에서는 해당 문맥의 안전한 API와 출력 인코딩을 별도로 적용하세요. 검색어가 사용자 입력이면 EXT-029의 RegExp.escape()와 길이 제한도 함께 사용합니다. 정규식 구조와 플래그는 개발자가 통제하고, 과도한 되돌아가기가 가능한 복잡한 패턴은 피하세요. 실습은 본인이 소유한 로컬 데이터에서만 수행합니다.

[직접 해볼 과제]
원문을 ‘red와 red’, 사용자 치환값을 ‘가격은 $5’로 바꾸세요. `/(red)/gu`와 함수형 치환을 사용해 두 단어를 모두 바꾸고, 결과가 ‘가격은 $5와 가격은 $5’인지 확인하세요. 이어서 문자열 치환 방식과 결과를 비교해 차이를 기록하세요.

[확인문제]
1. 문자열 치환값에서 `$&`는 무엇을 뜻합니까?
2. 함수형 치환의 반환값 안에 있는 `$1`이 문자 그대로 삽입되는 이유는 무엇입니까?
3. RegExp.escape()를 사용자 치환값에 사용하면 안 되는 이유는 무엇입니까?

[다음 학습]
다음에는 UTF-16 문자열에 홀로 남은 서로게이트가 있는지 isWellFormed()로 확인하고 toWellFormed()로 안전한 유니코드 문자열을 만드는 방법을 배웁니다.

[공식 참고 자료]
ECMAScript 2025 String.prototype.replace 표준
https://tc39.es/ecma262/2025/multipage/text-processing.html#sec-string.prototype.replace
ECMAScript 2025 GetSubstitution 치환 토큰 표준
https://tc39.es/ecma262/2025/multipage/text-processing.html#sec-getsubstitution
ECMAScript 2025 RegExp 치환 알고리즘
https://tc39.es/ecma262/2025/multipage/text-processing.html#sec-regexp.prototype-%symbol.replace%

댓글목록

등록된 댓글이 없습니다.

회원로그인

회원가입

사이트 정보

회사명 : 회사명 / 대표 : 대표자명
주소 : OO도 OO시 OO구 OO동 123-45
사업자 등록번호 : 123-45-67890
전화 : 02-123-4567 팩스 : 02-123-4568
통신판매업신고번호 : 제 OO구 - 123호
개인정보관리책임자 : 정보책임자명

접속자집계

오늘
3,839
어제
6,862
최대
16,772
전체
769,790
Copyright © 소유하신 도메인. All rights reserved.