기존 작업자가 작업해 둔 코드가 있었고, 요구 조건에 따라 이슈가 전달되어왔다.

 

기존 코드

function addComma(value) {
	return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}

 

addComma 결과 값

 

요구 조건은 아래와 같았고.. 

1. 숫자 천 단위마다 콤마 추가

2. 소수점에서는 콤마 추가하지 않아야 함

 

기존 코드에서는 소수점에서도 콤마가 추가되고 있었다.

function addComma(value) {
	return value.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ',');
}

수정한 addComma 결과 값

 

잘되는 듯 했지만, 크로스브라우징 이슈가 있었다. 

safari에서 흰페이지로 뜨는 것이었다. 두둥.. 

그리고 SyntaxError: Invalid regular expression: invalid group specifier name 에러 메시지가 출력되고 있었다.

 

왜???

검토해보니, 정규식에 사용된 lookbehind 패턴 때문이었다.

 

정규식에는 두가지 알고리즘이 존재한다고 한다.

  • Deterministic Finite Automaton (DFA): 문자열의 문자를 한번만 확인한다.
  • Nondeterministic Finite Automaton (NFA): 최적의 일치를 찾을 때 까지 여러번 확인한다.

여기에서 자바스크립트는 NFA 알고리즘을 사용하고 있고 이 알고리즘의 동작으로 인해 Catastrophic Backtracking 가 일어날 수 있다고 한다.

 

regexp-catastrophic-backtracking 란?

더보기

오랜 시간 실행됨에 있어서 js 엔진이 중단되는 현상이라고 한다.

일반적인 증상으로 특정 문자열의 경우 CPU를 100% 사용하여 중단된다고 한다. 

그리고 중단되기 때문에 화면에 아무것또 뜨지 않았던 것이다.(;;)

해결법으로는..

1. 조합의 수를 줄여서 순서대로 찾아 나가는 방식

2. 역 추적을 방지하는 lookahead 패턴으로 개발

두번째 방식을 권장한다고 한다.

 

정규식의 전방 탐색(Lookahead)과 후방 탐색(Lookbehind) 패턴에 대해 간단히 알아보면...

전방 탐색은 작성한 패턴에 일치하는 영역이 존재하여도 그 값이 제외되어서 나오는 패턴이고

후방탐색은 전방 탐색이 앞에 있는 문자열을 탐색하는 거라면 후방탐색은 뒤에 있는 문자열을 탐색하는 것이라고 한다.

이해가 잘 안되면 이 블로그 글을 읽어보자! (저는 이해에 도움이 많이되었습니다 -> https://blog.hexabrain.net/205)

 

즉, 처음에 수정한 정규식에서 (?<!\.\d*) 이 부분이 lookbehind에 해당하는 것이었다.

(1234.1234) <- 뒤의 문자열을 탐색

해결법을 찾기 위해 검색에 검색을 해봤고~!

정리가 잘되어있는 블로그 글을 발견했다!!! ㄳㄳ -> Javascript에서 천 단위 구분 기호로 쉼표가 있는 숫자를 인쇄하는 방법

 

그리고 선택한 방법들을 작성해보았다.!

1. split, join

function addComma(value) {
	let splitVal = value.toString().split('.');   
	splitVal[0] = splitVal[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); 
    return splitVal.join("."); 
}

split-join 방식

 

2. replace function

function addComma(value){ 
	return value
    	.toString()
        .replace(/(\..*)$|(\d)(?=(\d{3})+(?!\d))/g, (digit, fract) => fract || digit + ',');
}

replace function을 방식

 

3. toLocaleString('ko-KR')

이때 maximumFractionDigits를 따로 수정하지 않으면 소수점 자릿수는 3으로 기본 값으로 출력된다.

(예시로 5로 바꾸어봤다)

function addComma(value) {
	return value.toLocaleString('ko-KR', { maximumFractionDigits: 5 });
}

toLocaleString 방식

 

여러 방식을 알아보면서 정규식에 대해서 정말정말 공부하면 도움이 많이 되겠다고 생각한 하루였다.

인프런에 정규식 강의가 있던데,.ㅎㅎ..

 

 


참고!! (감사감사! 합니다.)

toLocaleString()

lookbehind 문법은 사파리와 익스플로러에서 쓸 수 없다.

Javascript에서 천 단위 구분 기호로 쉼표가 있는 숫자를 인쇄하는 방법

내장 메소드를 사용하여 숫자 천단위마다 콤마 찍기

+ Recent posts