출처 영상
[Track 2-6] 곽희범 - 글로벌 서비스를 하게 되면 겪게 될 폰트 렌더링 문제
: 안에 가려진 것들도 많고, 브라우저마다 특성이 다 다르다.
⇒ 폰트가 너무 많기 때문에, 모든 문자를 다 폰트가 해결해주지 않아 문제가 발생하기도 한다.
글자 중 지원하지 폰트를 사용한다면 폰트가 두 가지가 섞여져서 보여질 수 있다.
렌더링 된 폰트를 확인하기 위해서는 개발자 도구(F12)
- Elements
- Computed
- Rendered Fonts
를 확인하면 된다.
font-family: "Helvetica Nenu", "Apple SD Gothic Neo", sans-serif
- 알파벳 + 숫자 + 기호:
Helvetica Nenu
- 한글:
Apple SD Gothic Neo
- 그 외:
sans-serif
(기본 고딕체)
지원하는 순서대로 보여줌..
font-family: "Helvetica Nenu", "Hiragino Sans", sans-serif
일본어 폰트의 문자가 잘 안맞는 현상이 발생한다. 평균적으로 일본어와 중국어 폰트들이 다른 폰트들에 비해 조금 크다. 그래서 일본어 앞에 숫자들을 붙이면 일본어가 조금 커 보인다.
: 글꼴 꼬리에 꾸밈이 없는 고딕계열 기본 폰트
sans
는 “~이 없는”이라는 전치사 이고, serif
는 글꼴, 꼬리를 의미한다. 하여 글꼴 꼬리에 꾸밈이 없는 고딕 계열의 기본 폰트
로 알고 있지만, 자세히 보면 글꼴 꼬리에 꾸밈이 없는 고딕 계열 언어별 설정에 따른 기본 폰트
이다.
둘 다 애플에서 동작하는 기본 폰트이다.
-apple-system
은 Safari에서 동작BlinkMacSystemFont
는 Chrome에서 동작이 둘을 합쳐서 system-ui
로 분류하였는데,
Bootstrap
과 Github
에서는 폰트가 엄청 촌스러워보인다.
다른 글로벌 사이트는 어떻게 되어있을까
페이스북은 system-ui
폰트를 그대로 사용하고 있다.
폰트를 OS별로 설정을 다 추가해놓았지만, 동아시아에선 굉장히 불친절한 하다. 동아시아에서는 결국 sans-serif
로 설정되기 때문이다.
폰트가 다양하지만 가장 이상적인 방식이다. 그러나 테스트를 해야할 것이 많은 것이 단점이다.
lang
: 언어를 지정하는 전역 속성이어서 어느 태그에든 붙을 수 있다.
sans-serif
를 사용할 수 있게 도와줌lang
에 따라 폰트가 달라져서 길이가 다 달라진다.lang
를 sans-serif
에 넘겨주면 알맞은 값을 반환해준다는 내용. 함수로 표현하는게 좋은 것 같다고 생각한다.
lang
을 통해 언어별로 다른 폰트를 사용할 수 있다.
이렇게 사용하면 ko
랑 default
도 다르게 표현할 수 있다.
: 폰트 크기가 커져도 문제 없는 디자인
유연한 디자인을 통해 폰트가 불러오는 문제를 해결할 수 있다.
sans-serif
를 사용하고 있다.…(ellipsis)
처리를 통해 고정을 시킴이렇게 깨지는 UI가 없는게 특징이다.
: 웹폰트 최적화만 잘 시키자.
파편화된 디바이스의 폰트를 고정시킬 수 있다는 장점이 있다.
만약, 최적화를 시키지 않으면 최악의 경우.
웹 폰트는 로마자 → 일본어 → 한글 → 중국어 순으로 용량이 커지는 것을 알 수 있다. 그리하여 다운로드 다 받을 때까지 화면에 안나올 수 있다.
lang
attribute는 선택이 아니라 필수이다.E2E테스트로 찾아낼 수 있을까? cypress.io
일본어 메뉴의 경우, 폰트의 크기로 인해 로그아웃 버튼이 사라져버렸다면?
cy.get('.section).then($el => {
const parentNode = $el[0];
for (let child of parentNode.children) {
expect(Cypress.dom.isHidden(child).to.be.false
}
})
언어 변경에 따라 글자가 네모 영역을 벗어난 경우에 Element
의 offsetWidth, scrollWidth, offsetHeight, scrollHeight
로 알 수 있다.
cy.get(".section").then($el => {
const parentNode = $el[0];
for (let child of parentNode.children) {
const {
offsetWidth, scrollWidht,
offsetHeight, scrollHeight
} = child;
expect(offsetWidth > scrollWidht).to.be.true;
expect(offsetHeight > scrollHeight).to.be.true;
}
})
offsetWidth
은 border를 포함한 보여지는 크기를 가진다. scrollWidht
은 content영역에 보이지 않는 부분을 포함한다.
이렇게 잘려 있는 것을 알 수 있다.
일본어 쪽에 약간 커져서 스크롤이 생기는 문제가 있었다. Cypress.dom.isScrollable($element)
로 스크롤이 생겼는지 알 수 있다.
cy.get(".section").then($el => {
expect(Cypress.dom.isScrollable($el)).to.be.false
}
})
UI 상으로 깨진 부분이 없어서 찾기 어려웠다. 그래서 기본 언어의 화면을 기록하고 나머지 언어와의 화면을 비교하였다.
const traning = () => {
const elementSection = Cypress.$(".section");
const { children } = elementSection[0];
const childrenTop = [];
for (let i = 0; i < children.length; i++) {
const child = children[i];
childrenTop.push(child.getBoundingClientRect().top)
}
// 학습한 값
baseValue = {
width: elementSection.width();
height: elementSection.height();
childrenTop
}
}
예제 상태와 비교했을 때, childrenTop
이 다르면 검출이 될 것이다.
cy.get(".section").then($el => {
const parentNode = $el[0];
for (let i = 0; i < parentNode.children.length; i++ ) {
const child = children[i];
const { top } = child.getBoundingClientReact();
expect(top === baseValue.childrenTop[i]).to.be.true;
}
})
글로벌 서비스를 테스트할 때, 스타트업에서는 이러한 다양한 환경에 대해 익숙하지 않거나 충분히 이해하지 못하는 경우가 많다. 현재 회사에서도 글로벌 서비스를 진행하고 있지만, 대부분의 테스트가 한국에서만 이루어지고 있어 각국의 브라우저와 OS에서의 UI 차이를 미리 파악하지 못하고 있다는 걸 깨달았다. 이를 해결하려면 테스트 범위를 확장하고, Cypress
와 같은 도구를 적극 활용하여 다양한 환경에서의 UI 동작을 체크하고 신뢰를 유지하는 것이 중요해 보인다. 글로벌 서비스를 안정적으로 제공할 수 있도록 앞으로도 지속적으로 관리 해야겠다.