본문 바로가기
개발 공부/JS, JQuery

자바스크립트로 문자열 포매팅 구현하기. String.format()

by momo'sdad 2023. 10. 18.

다른 언어에서는 기본 메서드로 제공되는 문자열 포메팅 함수, 또는 메서드가 제공되지 않습니다.

굉장히 자주 사용하는 기능이지만 제공되지 않기 때문에 만들어 써야 합니다.

 

문자열 포매팅을 구현하는 방법은 여러가지가 있습니다.

필요에 따라 단순하게 구현해서 사용하는 방법도 있지만, 범용으로 사용할 수 있는 조금 복잡한 구현 방식으로 구현해서 여러가지 용도로 사용할 수도 있습니다.

 

프로토타입 언어인 자바스크립트의 특성을 살려서 프로토타입 메서드로 구현하는 방법을 주로 사용합니다.

 

ES6부터는 템플릿 문자열이 지원되기 때문에 문자열 포매팅 메서드를 따로 구현하지 않아도 문자열 포매팅을 할 수 있지만, 인터넷 익스플로러 호환성이 필요하거나 템플릿 문자열로는 구현하기 어려운 중간 변환이 필요한 경우, 포매팅 메서드를 별도로 구현해서 사용해야 합니다.

 

 

메서드 중복 체크하기

먼저 문자열 포매팅 메서드는 다른 언어의 이름을 그대로 사용해서 문자열 객체(String)의 "format()" 메서드로 정의합니다.

그리고 이미 "format()" 메서드가 정의되어 있는지 확인해서 중복 정의로 인한 낭비를 줄여야 합니다.

밑에서 "String.format()" 메서드를 정의할 때는 생략하지만 다음과 같이 중복 체크를 기본적으로 한다고 생각해야 합니다.

 

if (!String.format) { String.prototype.format(){ //포매팅 기능 구현 코드 } }

 

기본 문자열 포매팅

문자열 포매팅은 공통 문자열 안에 치환자를 사용해서 원하는 변수 값으로 갈아 끼워서 원하는 최종 문자열을 만드는 것을 말합니다. 따라서 템플릿으로 사용하는 문자열 안에 변수의 역할을 하는 치환자를 끼워넣어 공통 문자열을 정의하고, 문자열 포매팅 메서드는 변수로 받은 파라메터 값들을 템플릿 문자열의 치환자 사용파라메터로 대입해서 변수처럼 적용할 치환자를

가장 단순한 방식의 문자열 포맷 메서드는 다음과 같이 정의합니다.

 

String.prototype.format = function() { var formatted = this; for( var arg in arguments ) { formatted = formatted.replace("{" + arg + "}", arguments[arg]); } return formatted; }; console.log("{0} + {1} = {2}".format(4, 5, 9));

 

콘솔에는 다음처럼 파라메터 3개가 적용되어 "4 + 5 = 9" 문자열이 표시됩니다.

 

단순하고 정확하게 사용하면 되지만, "replace()" 함수로 치환자를 파라메터 값으로 변경하기 때문에 제약이 있습니다.

  1. "arguments" 객체는 파라메터를 담는 로컬 객체이며 0부터 시작하는 인덱스 값을 사용해 n번째 순서의 파라메터 값을 얻게 됩니다. 따라서 치환자는 반드시 "{0}", "{1}", "{2}" ... 처럼 0에서 시작하는 치환자로 표시해야 합니다.

  1. 파라메터 갯수와 치환자 갯수가 일치하거나 파라메터 갯수가 더 많아야 합니다. 일치하지 않으면 남는 치환자는 그대로 문자열에 남아 표시됩니다.

 

다음과 같이 "{1} + {2} = {3}" 치환자 문자열을 작성하면

 

console.log("{1} + {2} = {3}".format(4, 5, 9));

 

다음과 같이 문자열이 출력됩니다. 치환자가 "{1}" 에서 시작하기 때문에 첫 번재 파라메터 값은 지나치고 두 번째와 세 번째 파라메터만 적용됩니다. 그리고 "{3}" 치환자는 4번째 파라메터 값이 없기 때문에 치환되지 않고 그대로 문자열로 출력됩니다.

그리고 replace() 함수는 첫 번째 나오는 치환자만 변경하기 때문에 다음과 같은 치환자 반복에는 대응을 하지 못합니다.

다음과 같이 2개의 같은 치환자를 사용한 문자열에서는

 

console.log("{0} + {0} = {1}".format(4, 5));

 

처음 나오는 치환자만 값으로 적용되어 "4 + {0} = 5" 와 같은 문자열이 생성됩니다.

 

 

반복 치환자 지원 포매팅

"replace()" 함수를 사용할 때 정규표현식을 적용하면 문자열 안에 있는 모든 치환자를 파라메터 값으로 변경할 수 있습니다.

replaceAll() 함수가 없는 자바스크립트에서 기능을 구현하기 위해 사용하는 정규표현식 사용과 같습니다.

 

String.prototype.format = function() { var formatted = this; for (var i = 0; i < arguments.length; i++) { var regexp = new RegExp('\\{'+i+'\\}', 'gi'); formatted = formatted.replace(regexp, arguments[i]); } return formatted; };

 

이렇게 구현된 문자열 포매팅 메서드는 다음과 같은 반복되는 같은 치환자가 있는 문자열에 대응해 "4 + 4 = 8"의 결과 문자열을 반환합니다.

 

console.log("{0} + {0} = {1}".format(4, 8));

 

단, 이 방식도 치환자의 인덱스 갯수만큼 파라메터의 갯수를 맞춰줘야 합니다.

 

반복 치환자를 지원하는 문자열 포매팅 메서드에서 중요한 것은 "replace()" 함수의 첫 번째 파라메터로 사용하는 정규표현식입니다.

"RegExp('\\{'+i+'\\}', 'gi')" 이 정규표현식은 "{정수}" 표현과 매칭되는 것을 찾으며, 정규표현식의 두 번째 파라메터인 옵션 "gi" 는 문자열 전역으로 매칭되는 것을 모두 찾고(g), 대소문자 구분을 하지 않는(i) 다는 뜻입니다.

이 메서드 구현에서는 대소문자 구분을 하지 않는 "i" 옵션은 필요하지 않지만, 뒤에서 영문자로 치환자를 사용하기 때문에 알아둘 필요가 있어서 미리 설명을 하기위해 붙여놓은 것입니다.

 

 

함수형으로 구현한 문자열 포매팅

문자열 프로토타입 메서드 대신 일반 함수처럼 사용할 수 있는 방식으로도 구현할 수 있습니다.

사용할 때 "String.format(템플릿문자열, 파라메터1, 파라메터2, ...)"와 같이 호출해서 사용할 수 있습니다.

템플렛 문자열이 무조건 첫 번째 파라메터로 들어가는 점을 제외하면 앞서의 구현 방법과 동일합니다.

 

String.format = function(formatted) { var args = Array.prototype.slice.call(arguments, 1); return formatted.replace(/{(\d+)}/g, function(match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); } console.log(String.format("{0} + {1} = {2}", 4, 5, 9));

 

정규표현식을 이용한 더 간결한 문자열 포매팅

"{정수}"로 파라메터 순서를 수동으로 표현하는 대신 앞에서부터 파라메터 순서대로 1:1로 매칭을 해서 적용을 하는 경우에는 조금 더 간결하고 직관적으로 다음과 같이 구현할 수 있습니다.

템플릿 문자열 안에 사용하는 치환자는 "%s"로만 사용하고, 정규표현식을 이용해 파라메터 값을 대체할 때는 "%s" 가 나오는 순서대로 파레미터 순서와 1:1로 매칭을 해서 치환을 합니다.

 

String.prototype.format = function() { var formatted = this, i = 0; while (/%s/.test(formatted)) formatted = formatted.replace("%s", arguments[i++]); return formatted; } console.log("%s + %s = %s".format(4, 5, 9));

 

ES6 확산 연산자와 배열 reduce() 메서드로 문자열 포매팅

파라메터 객체를 배열로 확산해주는 확산 연산자와 배열을 하나의 문자열로 합쳐주는 reduce() 메서드를 이용하면 단 한줄의 코드로 간결하게 표현되는 문자열 포매팅 메서드를 구현할 수 있습니다.

 

앞서 구현했던 "%s" 치환자를 이용한 더 간결한 구현 방식을 ES6로 구현하면 다음과 같이 한 줄로 구현할 수 있습니다.

 

String.prototype.format = function() { return [...arguments].reduce((pattern,value) => pattern.replace(/%s/,value), this); }; console.log('%s + %s = %s'.format(4, 5, 9));

 

 

ES6 템플릿 문자열과 백틱을 이용한 문자열 포매팅

ES6 자바스크립트는 코딩량을 획기적으로 줄일 수 있는 새로운 표현과 메서드가 있기 때문에 문자열 포매팅을 아주 간단하게 구현할 수 있습니다.

그중 내장 문자열 포매팅 기능인 템플릿 문자열과 백틱(`)을 이용해 문자열 포매팅을 할 수 있습니다.

값이 할당된 변수를 "${}"로 감싸서 "${변수명}"과 같이 문자열 안에 직접 기입하면 자동으로 변수 값이 치환되면 완성된 문자열이 됩니다.

그리고 이렇게 템플릿 문자열로 만든 문자열은 백틱(`)으로 감싸야 합니다.

따옴표나 쌍따옴표로 감싸면 템플릿 문자열로 표현한 변수 값이 치환되지 않고 변수명이 그대로 출력됩니다.

백틱은 한글로는 역따옴표라고 하며, 키보드 맨 왼쪽 위에 있는 "~"의 쉬프트 입력입니다.

 

let val1 = 4, val2 = 5, val3 = 13; console.log(`${val1} + ${val2} + ${val1} = ${val3}`);

 

 

ES6는 모든 점에서 뛰어나지만 인터넷 익스플로러에서 지원되지 않는 문제가 있습니다. 2022년 6월이면 인터넷 익스플로러 지원이 종료되기 때문에 가까운 미래에는 인터넷 익스플로러 호환이 가능한 문자열 포매팅 메서드를 만들 필요가 없겠지만, 아직은 인터넷 익스플로러 호환이 필요한 환경이 있기 때문에 문자열 포매팅 메서드를 구현할 때는 주의해야 합니다.

반응형