본문 바로가기

Programming/JavaScript & TypeScript

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

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


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


자바스크립트에서 `.length`는 한글이나 영어나 한글자로 취급해 반환합니다. 하지만 렌더링상으로는 전각과 반각문자이기 때문에, 차지하는 넓이는 다릅니다.

저는 `"와 문자열이다!".getLength()`의 길이가 `14`로 취급되는 것을 원했기 때문에, 바이트값으로 문자열의 길이를 측정할 방법이 필요하다고 생겼습니다.


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


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

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


원리는 아래와 같다. 

  • 문자열을 배열로 쪼개고(map과 reduce를 쓰기 위함)
  • map으로 각 문자의 문자 코드 배열을 만든다. ( 안하면 charCodeAt(0)이 reduce에 2번 들어가게 된다.)
  • reduce로 합을 구한다. 

getByte(str) {
return str
.split('')
.map(s => s.charCodeAt(0))
.reduce((prev, c) => (prev + ((c === 10) ? 2 : ((c >> 7) ? 2 : 1))), 0);
}


태그