문자 코드와 호환
- 문자 코드
- 컴퓨터에서 문자를 표시하기 위해 대응하는 고유 번호, 문자에 할당된 번호
- 웹 브라우저 위에 표시되는 많은 글들이 숫자의 나열[바이너리], 컴퓨터가 그 숫자의 나열을 문자로
인식하여 표시
- 문자 코드가 어려운 이유
- 알파벳과 숫자만 있다면 1byte로도 충분히 모든 문자가 표현이 가능하지만,
- 한글이나 일본어, 중국어 등의 경우에는 문자의 수가 많아 2byte(0~65535)를 사용하지 않고서는
모든 분자를 표현하는 것이 불가능하다.
- 이들 언어의 문자를 컴퓨터상에서 다루기 위한 다양한 방법이 고안.
- 다만 문제는 문자 코드 간의 호환성, 문자 코드의 인식에 실패하거나 문자 코드 간의 변환이 잘못되면
이른바 '문자가 깨지는' 현상이 발생
- 현재의 주류 : 유니코드 (UNICODE)
- 세계에서 사용되는 모든 문자를 공통의 문자 집합에 정의한 코드 체계
- 문자 집합과 부호화 스킴(CHRAACTER ENCODING SCHEME)
- 유니코드에는 각 문자에 대한 코드 번호를 정의한 문자 집합과
- 문자 집합을 어떻게 바이트 값으로 표시할지에 관한 문자 부호화 스킴이 정의되어 있다.
- 문자 집합은 같아도 부호화 방식이 다를 수도 있다
- 유니코드를 예로 들면, 유니코드를 2바이트로 표현한 것이 UTF-16이고 1바이트로 표현한 것이 UTF-8
- 둘 다 유니코드의 문자 집합을 사용하고 있지만, 다른 부호화 방식을 사용하므로 텍스트를 바이너리로
봤을 때는 다르게 보인다.
- 같은 문자 집합을 사용하고 있으면 상호 간에 변환은 쉽다.
- 자바스크립트의 문자 코드
- 내부적으로 UTF-16을 사용한다.
- HTML의 문자 코드가 EUC-KR이라 해도 변환되어 UTF-16이 사용된다.
- Node.js의 경우
- Node.js에서는 파일을 쓸 때 UTF-8을 기본으로 사용한다. 간단한 예로 fs 모듈을 사용하여
UTF-8 텍스트 파일을 읽고 쓰는 프로그램을 만들어 볼 것이다.
코드
// read and write a file for Node.js
const fs = require('fs');
// read a file 'utf-8'
const text = fs.readFileSync("sample-utf8.txt","utf-8");
console.log(text);
// write a file as 'utf-8'
fs.writeFileSync("text.txt", text);
- 파일을 동기적으로 읽는 fs.readFileSync() 메소드와 동기적으로 쓰는 fs.writeFileSync() 메소드를 사용
- 읽고 쓰기를 할 때 옵션으로 문자 인코딩을 지정할 수 있고, 파일에 쓰기를 할 때에는 명시적으로
utf-8을 지정하지 않아도 기본으로 utf-8로 데이터가 작성
- 그러나 읽을 때는 utf-8을 지정하지 않으면 정상적인 결과를 얻을 수 없다.
// read and write a file for Node.js
const fs = require('fs');
// read a file 'utf-8'
const text = fs.readFileSync("sample-utf8.txt");
console.log(text);
// write a file as 'utf-8'
fs.writeFileSync("text.txt", text);
- 텍스트를 읽을 때 문자 코드를 지정하지 않는 경우 결과는 Buffer 객체로 인식된다
- <Buffer 73 61 6d 70 6c 65 0a>
- fs.readFileSync() 메소드는 문자 코드 'EUC-KR'을 지원하지 않기 때문에, 실행 인자의 옵션으로
'EUC-KR'을 지정하면 지원하지 않는 문자 코드라는 내용의 메시지가 뜬다.
- Node.js에서 문자 코드 변환
- Node.js의 문자 표준 상태에서는 'EUC-KR'등의 문자 코드를 다룰 수 없으므로 외부 모듈을 설치
- 문자코드 변환에는 'iconv'라는 라이브러리가 널리 쓰인다.
- 하지만 goormide는 패키지가 제대로 인식되지 않기 때문에 'iconv-lite'를 사용
- 문자 코드의 자동 판정용 모듈 'jschardet'도 있다.
- 설치
- npm install iconv-lite
- npm install jschardet
코드
// read 'EUC-KR' file and then save to 'UTF-8' file.
const fs = require('fs');
const iconv = require('iconv-lite');
// write a text as 'euc-kr'
let str = "안녕하세요";
let fname = "iconv-lite-test-euckr.txt";
// convert to 'euc-kr'
let buf = iconv.encode(str, "euc-kr");
// save
fs.writeFileSync(fname, buf, "binary");
// display after reading a text of 'euc-kr'
let bin = fs.readFileSync(fname, "binary");
// convert binary of 'euc-kr' to 'utf-8'
let txt = iconv.decode(bin, 'euc-kr');
console.log(txt);
결과
Iconv-lite warning: decode()-ing strings is deprecated. Refer to https://github.com/ashtuchkin/ico nv-lite/wiki/Use-Buffers-when-decoding 안녕하세요 |
- 유의 사항은 위의 'decode()-ing string is deprecated'라는 출력문이다.
- js의 type conversion 때문에, string의 경우 코드가 자동적으로
- chunkBuffer.toString('utf8');로 변환되기 때문에 2중으로 디코딩되는 경우가 발생
- 권장사항은
- iconv.decode(Buffer.concat(chunks), 'utf-8');
- 자세한 내용은 https://github.com/ashtuchkin/iconv-lite/wiki/Use-Buffers-when-decoding 참조
- 문자 코드를 모르는 텍스트를 읽는 경우
- jschardet 모듈을 사용하여 문자 코드를 판정
코드
// read 'EUC-KR' file and then save to 'UTF-8' file.
const fs = require('fs');
const iconv = require('iconv-lite');
const jschardet = require('jschardet');
let fname = "iconv-lite-test-euckr.txt";
// read a unknown character code file
let buf = fs.readFileSync(fname);
// perform character code judgement
let det = jschardet.detect(buf);
console.log(det);
let buf2 = iconv.decode(buf, det.encoding);
let txt = buf2.toString('utf-8');
console.log(txt);
결과
{ encoding: 'EUC-KR', confidence: 0.6666666666666666 }
안녕하세요
정규표현식을 사용한 데이터 변환
- 정규 표현식
- Regular Expression, 문자열의 패턴을 표현하는 표기 방법으로 문자열의 검색과 치환에 유용하다.
- 문자열의 패턴을 메타 문자(미리 약속된 특별 기호)를 조합하여 표현함으로써 문자를 검색하거나 치환
- 자바스크립트에서의 정규표현식 사용법
- 소스 코드 중에 '/패턴/'으로 정규표현식 객체를 생성가능.
- let re = /value=\d+/; // 정규 표현식 리터럴
- RegExp 객체를 생성하여 사용가능
- let re = new RegExp("value=\d+");
- 정규 표현식 리터럴을 사용하면 스크립트가 로드되는 시점에서 정규 표현식이 컴파일됨로
성능에 유리하다.
- RegExp 객체를 사용하면 문자열 변수로 정규 표현식 패턴을 지정할 수 있어 동적으로 정규표현식을
다룰 수 있게 된다.
- 정규 표현식 메소드
메소드 |
설명 |
exec |
문자열 중에서 일치하는 부분을 검색하여 결과를 반환한다. 검색에 실패한 경우 null을 반환한다 (RegExp의 메소드) |
test |
문자열 중에서 일치하는 부분이 있는지를 테스트한다. true/false 중 하나를 반환한다. (RegExp의 메소드) |
match |
문자열 중에서 일치하는 것을 검색하여 결과를 배열로 반환한다. 일치하는 패턴이 없는 경우 null을 반환한다. (String의 메소드) |
search |
문자열 중에서 일치하는 것이 있는지를 테스트한다. 일치하는 인덱스를 반환하거나 일치하는 부분이 없으면 -1을 반환한다. (String의 메소드) |
replace |
문자열 중에서 일치하는 것을 찾아서 다른 문자열로 치환한다. |
split |
문자열을 정규 표현식으로 분할하여 부분 문자열의 배열을 반환한다. |
- 어떤 문자열 안에 정규표현식 패턴이 있는지 확인만 하고 싶을 때
- test() or search()
- 더 자세한 정보를 알고 싶을 때
- exec() or match()
- RegExp.exec()
- 정규표현식에 해당하는 문자열을 검색하여 패턴이 존재하면 문자열의 배열을 반환함과 동시에
RegExp 객체의 속성을 업데이트하고, 일치하는 패턴이 없으면 null을 반환한다.
- 결과로 반환되는 배열에는 정규표현식에 일치하는 문자열이 첫 번째 요소에 담겨 있고, 이어서
정규 표현식 중 괄호로 묶인 부분에 해당하는 부분문자열이 차례로 담겨있다.
- 또한, 이 배열에는 속성으로 정규식에 해당하는 문자열의 인덱스 정보와 입력받은 문자열 값을
포함하고 있다.
코드
> var re = /([0-9]+)([a-z+])/g;
> str = "111jpy,8usd,xxx";
'111jpy,8usd,xxx'
> console.log(re.exec(str))
null
undefined
> console.log(re.exec(str))
[
'111j',
'111',
'j',
index: 0,
input: '111jpy,8usd,xxx',
groups: undefined
]
undefined
> console.log(re.exec(str))
[
'8u',
'8',
'u',
index: 7,
input: '111jpy,8usd,xxx',
groups: undefined
]
undefined
> console.log(re.exec(str))
null
undefined
- 지정한 정규표현식 패턴은 한 개 이상의 숫자에 이은 한 개 이상의 소문자 조합을 뜻한다.
- 괄호가 두 번 사용되었는데, 각각 부분 패턴을 뜻한다.
- 정규 표현식에 g플래그를 지정하면 문자열 안에 일치하는 모든 패턴을 포함하게 된다.
- 위의 예에서는 exec()를 여러 번 호출하며 일치하는 패턴을 차례로 출력하고 있다.
- exec() 메소드는 test()나 search()에 비해 실행속도가 느리므로 패턴의 존재 여부만을 확인하고
싶은 경우엔 권장되지 않는다.
- RegExp.test() 메소드
- 인자로 주어진 문자열에 정규표현식에 해당하는 문자열 패턴이 있는지 여부를 조사한다.
결과로 true나 false의 boolean 값을 반환한다
코드
> var re = /^\d{3}-\d{4}$/;
undefined
> re.test("123-1234");
true
> re.test("12-1234");
false
> re.test("440-0011");
true
> re.test("aaa-bbbb");
false
- 자릿수가 부족한 "12-1234"는 false를 리턴한다.
- String.match() 메소드
- String 객체에 준비된 match() 메소드는 인자로 전달받은 정규표현식 패턴을 조사한다.
정규표현식에 g플래그를 포함하지 않은 경우는 RegExp.exec() 메소드와 같은 결과를 반환하지만
- g플래그를 포함하는 경우에는 일치하는 부분을 모두 포함한 배열을 반환한다.
- 일치하는 패턴이 없으면 null을 반환한다.
코드
> var str="v=20, n=40, c=30";
undefined
> str.match(/[0-9]+/);
[ '20', index: 2, input: 'v=20, n=40, c=30', groups: undefined ]
> str.match(/[0-9]+/g);
[ '20', '40', '30' ]
> str.match(/\w+=\d+/g)
[ 'v=20', 'n=40', 'c=30' ]
- String.search() 메소드
- 대상 문자열에 정규표현식에 해당하는 패턴이 있는지 확인할 때 사용한다.
- 정규표현식에 해당하는 패턴이 발견되면 발견된 인덱스를 돌려주고, 없으면 -1을 반환한다.
코드
> var str = "zip:999-9999, mail:a@example.com";
undefined
> str.search(/\d{3}-\d{4}/);
4
> str.search(/\w+\@\w+\.\w+/);
19
> str.search(/https?:\/\//);
-1
- String.replace() 메소드
- 정규표현식으로 치환을 수행하는 replace() 메소드
- 두 가지 형태의 사용법이 있다.
- [서식1] 정규표현식을 이용한 치환 : str.replace(정규표현식 치환 될 문자열)
코드
> var str = "Today 10per OFF";
undefined
> str.replace(/\d+/, "30");
'Today 30per OFF'
> str.replace(/\d+[a-z]+/, "500yen");
'Today 500yen OFF'
> str.replace(/[a-zA-Z]+/g, "");
' 10 '
- 치환될 문자열에 특수한 치환 패턴을 포함할 수 있다.
패턴 |
설명 |
$$ |
문자 ‘$’를 삽입한다 |
$& |
매치된 부분 문자열을 삽입한다 |
$` |
매치된 부분 문자열 직전의 문자열을 삽입한다. |
$’ |
매치된 부분 문자열 직후의 문자열을 삽입한다. |
$1$2$3 |
괄호로 묶인 부분 문자열을 삽입한다. |
코드
> var str = "tel:045-111-222";
undefined
> str.replace(/(\d+)-(\d+)-(\d)/, "($1)-$2-$3");
'tel:(045)-111-222'
- 콜백 함수를 사용하는 replace() 메소드를 살펴보자
- [서식2] 콜백 함수를 사용하여 치환 : str.replace(정규표현식, 치환)
- 문자열 str안의 정규 표현식에 일치하는 문자열에 대해 치환 함수가 수행된다.
그러면 수행된 치환 함수의 반환 값으로 치환된다.
코드
str.replace(/[a-z]+/g, function(v) {
... return v.toUpperCase()
... });
'TEL:045-111-222'
> var str = "price: 100 won";
undefined
> str.replace(/\d+/, function(v) {
... v = parseInt(v);
... return Math.ceil(1.08 * v);
... });
'price: 108 won'
더 자세한 정규표현식은
https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/%EC%A0%95%EA%B7%9C%EC%8B%9D
정규 표현식
정규 표현식은 문자열에 나타는 특정 문자 조합과 대응시키기 위해 사용되는 패턴입니다. 자바스크립트에서, 정규 표현식 또한 객체입니다. 이 패턴들은 RegExp의 exec 메소드와 test 메소드 ,
developer.mozilla.org