JS 정규식의 \1, $1이 헷갈린다면? 역참조 개념부터 오류 해결까지 친절한 가이드

2025-10-11

역참조는 정규 표현식 패턴 내에서 이전에 캡처된 그룹이 일치시킨 텍스트와 동일한 텍스트를 다시 일치시키고자 할 때 사용하는 기능이에요.

캡처 그룹은 괄호 $(\text{})$로 묶인 패턴을 말하며, 일치된 부분이 임시로 저장되죠. 역참조는 이 저장된 내용을 \1, \2와 같은 형태로 불러와요. 여기서 숫자는 캡처 그룹의 순서(왼쪽부터 1, 2, 3...)를 의미합니다.

// 연속된 두 개의 같은 단어를 찾는 정규식
const regex = /(\w+)\s+\1/g; 
const text = "빨리 빨리 가자, 천천히 천천히 가자.";

// \1은 첫 번째 캡처 그룹 (\w+)이 일치시킨 '빨리'나 '천천히'를 다시 참조합니다.
const matches = text.match(regex);
console.log(matches); // ["빨리 빨리", "천천히 천천히"]

가장 흔한 실수는 캡처 그룹 번호를 잘못 지정하는 거예요.

문제 상황설명
번호 착각캡처 그룹이 여러 개일 때, 내가 원하는 그룹이 \1이 아니라 \2 또는 \3인데 잘못 사용하는 경우.
존재하지 않는 그룹 참조패턴에 캡처 그룹이 2개뿐인데 \3을 참조하는 경우. JavaScript에서는 유니코드 인식 모드(u 플래그)를 사용하지 않으면 구문 오류가 발생하지 않고, 구식 8진수 이스케이프 시퀀스로 해석될 수 있어요. (하지만 이는 지양해야 할 구식 방식입니다.)

숫자 대신 이름을 사용하면 가독성이 높아지고 번호 착각 오류를 방지할 수 있습니다.

// 문법: (?<이름>패턴)
const regex = /(?<tag>\w+)\s+\k<tag>/g;
const text = "좋아 좋아, 싫어 싫어";

// \k<tag>로 'tag'라는 이름을 가진 그룹을 참조합니다.
const matches = text.match(regex);
console.log(matches); // ["좋아 좋아", "싫어 싫어"]

// 참고: named backreference는 ES2018부터 지원됩니다.

역참조 자체는 계산 비용이 많이 들 수 있으며, 특히 탐욕적(Greedy)인 양화자(∗, +)와 함께 사용될 때 최악의 백트래킹(Catastrophic Backtracking) 문제를 일으킬 수 있습니다.

문제 상황설명
느린 실행복잡하고 긴 문자열에서 역참조가 포함된 복잡한 패턴을 사용할 경우, 일치하는 부분을 찾기 위해 정규식 엔진이 너무 많은 경우의 수를 탐색(백트래킹)하게 되어 실행 속도가 매우 느려집니다.

가능한 한 최소 일치 양화자(∗?, +?)를 사용하거나, 문자 클래스를 명확하게 지정하여 패턴의 탐색 범위를 제한하세요.

// HTML 태그 쌍을 찾는 예시 (흔한 실수)
// 문제: .*는 너무 '탐욕적'이며 역참조를 만나 백트래킹을 많이 할 수 있습니다.
// 예: "<b>굵게</b> 그리고 <i>기울임</i>" 에서 전체를 잡아버릴 수 있음.
// const badRegex = /<(\w+)>.*<\/\1>/g; // 피해야 합니다.

// 해결책: 최소 일치 양화자 (*?)와 특정 문자가 아닌 경우를 명시
// 이 예시에서는 닫는 태그가 아닌 문자[^>]로 내부 내용을 제한하는 것이 더 명확합니다.
const goodRegex = /<(\w+)[^>]*>([\s\S]*?)<\/\1>/g; 
const text = "이것은 <B>굵은 글씨</B>입니다.";

// replace를 사용하면 더 명확하게 그룹을 참조하고 내용을 바꿀 수 있어요.
// $1: 1번 그룹(태그 이름), $2: 2번 그룹(내부 내용)
const replacedText = text.replace(goodRegex, "[[ 태그: $1, 내용: $2 ]]");
console.log(replacedText); // "이것은 [[ 태그: B, 내용: 굵은 글씨 ]]입니다."

문자열의 replace() 메서드에서 역참조를 사용할 때 발생하는 오류에 대한 질문도 많아요.

문제 상황설명
대체 문자열 내 오류JavaScript의 String.prototype.replace()에서 정규식 일치 후 대체 문자열 안에 역참조를 사용할 때는 달러 기호($)를 사용해야 합니다. $\backslash 1$이 아니라 \*\*$$ 1$**을 사용해야 해요.

replace() 메서드의 두 번째 인수인 대체 문자열 내에서는 \n 대신 $n을 사용하여 캡처 그룹을 참조합니다.

// 이름과 성을 '성, 이름' 형식으로 바꾸는 예시
const nameRegex = /(\w+)\s+(\w+)/; // (이름)(공백)(성)을 캡처

const name = "Gildong Hong"; 

// $2: 두 번째 그룹(Hong), $1: 첫 번째 그룹(Gildong)
const replacedName = name.replace(nameRegex, "$2, $1");

console.log(replacedName); // "Hong, Gildong"

// 명명된 그룹을 사용했다면:
const namedRegex = /(?<first>\w+)\s+(?<last>\w+)/;
// 대체 문자열에서는 '$<이름>' 형식으로 참조합니다.
const replacedNamed = name.replace(namedRegex, "$<last>, $<first>"); 
console.log(replacedNamed); // "Hong, Gildong"

javascript



JavaScript String.repeat() 완벽 가이드: 흔한 오류와 대체 방법 3가지

String. repeat()는 특정 문자열을 지정된 횟수만큼 반복하여 새로운 문자열을 반환하는 편리한 기능이죠.String. repeat() 자체는 사용법이 간단하지만, 몇 가지 흔한 실수가 있습니다.문제 반복 횟수(count)에 음수를 전달하면 RangeError가 발생합니다


ZonedDateTime.toPlainDateTime, 이것만 알면 실수 끝! (대안 코드 포함)

Temporal. ZonedDateTime. toPlainDateTime() 메서드는 시간대 정보(Time Zone)를 포함하는 ZonedDateTime 객체에서 시간대 정보를 제거하고, 해당 시점의 로컬 날짜와 시간만을 나타내는 PlainDateTime 객체를 반환합니다


콜백 함수 최적화! 화살표 함수의 장점과 생성자/메서드 사용 시 주의점 총정리

화살표 함수를 사용할 때 개발자들이 가장 많이 겪는 문제와 그 해결 방법을 알아봅시다.일반 함수와 화살표 함수의 가장 큰 차이점은 this 키워드를 다루는 방식이에요.객체의 메서드를 화살표 함수로 정의하면, this가 객체 자신이 아닌 전역 객체(window 또는 global)를 가리키거나



AsyncDisposableStack 오류 처리: try...finally와 Promise.allSettled 활용

AsyncDisposableStack은 비동기적으로(asynchronously) 자원을 해제해야 할 때 사용하는 스택 구조입니다. 자원 해제 로직(cleanup logic)을 등록해 두면, 나중에 disposeAsync() 메서드를 호출했을 때 스택에 쌓인 순서의 역순으로 모든 자원을 비동기적으로 깔끔하게 해제해 줍니다


태그로 포맷하여 보여드릴게요. 친근하고 명확한 제목들로 구성해봤습니다!

정규 표현식 수정자는 슬래시(/)로 패턴을 감싼 뒤 마지막에 추가하는 플래그(Flags)를 말해요. 이 플래그들을 사용하면 검색 방식(예 대소문자 구분, 다중 행 처리 등)을 바꿀 수 있어요.자주 사용하는 주요 수정자는 다음과 같습니다


태그로 감싼 코드 블록 형태로 출력하겠습니다.

친절하고 자세하게, 친구에게 설명하듯이 한국어로 쉽게 설명해 드릴게요.TypedArray. prototype. map() 메서드는 일반 Array. prototype. map()과 거의 똑같이 작동해요. 호출한 Typed Array의 모든 요소에 대해 주어진 함수를 호출하고


태그로 감싸진 코드 블록으로 출력됩니다.

Object. defineProperties()는 기존 객체에 하나 이상의 데이터 속성(Data Descriptor) 또는 접근자 속성(Accessor Descriptor)을 추가하거나 수정하는 데 사용됩니다. 일반적인 속성 할당(‘obj


Temporal.ZonedDateTime.timeZoneId: 시간대 식별자 확인 및 변환 대체 코드 예시

Temporal. ZonedDateTime. timeZoneId는 Temporal. ZonedDateTime 객체가 가지고 있는 시간대 식별자(Time Zone Identifier) 문자열을 반환하는 속성입니다. 이 식별자는 IANA 시간대 데이터베이스(예 "Asia/Seoul", "America/New_York")의 표준 형식을 따릅니다


JavaScript Math.hypot() 완벽 가이드: 문제 해결과 대체 코드

Math. hypot()은 인수로 전달된 숫자들의 제곱의 합의 제곱근을 반환하는 함수예요. 쉽게 말해, 인수가 직각삼각형의 변의 길이라고 가정했을 때, 빗변의 길이를 계산해주는 피타고라스 정리 $\sqrt{v_1^2 + v_2^2 + \dots + v_n^2}$를 구현한 거라고 보시면 돼요


JS TypedArray.filter 사용 시 흔한 실수와 성능 최적화 대안

친절하고 쉽게 설명해 드릴게요.TypedArray는 일반 JavaScript 배열과 달리, 배열에 저장될 데이터의 타입(type)이 미리 정해져 있고, 메모리 상에서 연속적인 공간을 차지하는 특징이 있어요. 이는 대용량 데이터나 숫자 데이터를 다룰 때 성능상 이점을 제공합니다