ES6로 문자열의 바이트(Byte) 수 구하기

Shin-JaeHeon·2019년 3월 23일
1

이 글은 필요 없는 부분이 일부 있습니다. 코드를 원하시면, '함수' 항목으로 이동하세요.

1. 계기

Share Links는 반응형 바둑판 레이아웃(항목의 가로길이는 고정, 세로길이는 유동적)를 사용합니다. 한마디로 말해서 핀터레스트(Pinterest)의 레이아웃입니다. flexgrid로 하려했으나 실패해 결국에는 자바스크립트의 힘을 빌렸습니다. 처음에 핀터레스트는 어떻게 구현한건지 살펴보니 일일이 topleft를 때려박아서(...) 만들어져있었습니다.

여하튼 한번 만들어놓고 잘 썼었습니다만, 태그 목록이 길어지면 overflow:auto 시켜서 가로스크롤로 표현하는 대신, 세로를 height:auto로 설정해 스크롤 없이 표현하는 것으로 레이아웃을 변경하려고 했습니다. 또한 제목이 길어지면 역시 태그처럼 스크롤을 생성하지 않게 레이아웃을 변경하려했습니다. 이제 auto로 늘어난 만큼을 계산해서 전체 카드의 height를 구하는 것이 관건이었습니다.

2. 문제점

자바스크립트에서 .length는 한글이나 영어나 한글자로 취급해 반환합니다. 하지만 렌더링상으로는 전각과 반각문자이기 때문에, 차지하는 넓이는 다릅니다.
저는 "와 문자열이다!".getLength()의 길이가 14로 취급되는 것을 원했기 때문에, 바이트값으로 문자열의 길이를 측정할 방법이 필요하다고 생겼습니다.

물론 모노(Mono)글꼴을 사용하지 않으면 글자들이 각기 다른 넓이를 갖고 있지만 한글/한자 = 2, 반각문자 = 1, 정도로 계산해도 충분하기 때문에 넘어 갈 수 있습니다.

3. 함수

원본 코드는 https://programmingsummaries.tistory.com/239 에 소개되어있는 코드 중 '개선된 FOR문'의 코드입니다.

아래의 코드는 해당 코드를 map과 reduce를 대신하여 사용한 것입니다. 또한 바이트 수를 구하는 부분은 해당 글에 달려 있는 댓글 중 '노예'라는 분이 써주신 EUC-KR용(2바이트) 코드를 사용했습니다. 만약에 한글을 3바이트로 계산하는 코드가 필요하다면 아래에서 일부 코드를 '개선된 FOR문' 코드에서 따와서 고치면 됩니다.

원리

원리는 아래와 같습니다.
먼저, map과 reduce를 쓰기 위해 문자열을 배열로 쪼갭니다.
그 다음으로, map으로 각 문자의 문자 코드 배열을 만듭니다. 이 과정을 생략하려면 charCodeAt(0)을 reduce 부분에 2번 해주어야합니다.
이제 계산식을 사용해서 reduce로 값을 구해주면 됩니다.

코드

function getByte(str) {
  return str
    .split('') 
    .map(s => s.charCodeAt(0))
    .reduce((prev, c) => (prev + ((c === 10) ? 2 : ((c >> 7) ? 2 : 1))), 0); // 계산식에 관한 설명은 위 블로그에 있습니다.
}

4. 여담

여담으로, 이 글은 https://jaeheon.kr/123 에도 올라와있습니다. 하지만, 분명이 블로그 글이 원본임에도 불구하고 velog에 작성하면서 싹 고친것 + velog의 깔끔한 UI덕분에 velog가 훨씬 더 좋습니다. 물론 여기에 쓰면서 개선된 부분을 블로그에 다시 옮겨 붙이긴 했습니다.

1개의 댓글

comment-user-thumbnail
2020년 4월 14일

잘 참고하였습니다 : )

답글 달기