-
[React] 의외로 괴롭히는 폰트 다루기 1탄일찍 알았으면 좋았을 넓고 얕은 개발 지식 2023. 12. 10. 21:12
"일찍 알았으면 좋았을 넓고 얕은 개발 지식"은 개발 공부한 지 얼마 안 됐을 때 대충 알고 넘어가버려, 이제 와서 고통받는 스스로에 대한 반성과, 개발세계에 입문하신 분들에게 도움이 되고자 하는 글을 쓰고 있습니다.
프로젝트를 시작하거나, 제품을 만들때에 일관성 있는 결과물을 도출하기 위해 프로젝트 전역에서 공통으로 쓰일 여러 가지 설정들을 합니다. 라이브러리를 설치하거나 CSS 속성 중에 자주 쓰일 컬러나 간격, 그리고 폰트 설정을 많이 하죠. 분명히 초기세팅에 전역에 적용되는 폰트 설정을 했는데 이상하게 특정 영역에만 폰트가 다르거나, 폰트가 정확히 원하는 대로 설정이 된 건가? 확인하고 싶다면 잘 오셨습니다. 더불어 Form Field에 적용이 안 되는 이유, 그리고 어떻게 적용하는지 알아보겠습니다. 이 글은 React 초기세팅을 해본 경험이 있다면 큰 어려움 없이 보실 수 있습니다.
폰트를 적용하려면 당연한 이야기같지만 적용할 폰트를 다운로드 해야합니다. 다운로드 하는 보편적인 방법은 2가지 있습니다.
1. 물리적인 폰트 파일을 프로젝트 폴더 내에 위치시켜서 설정하는 @font-face 방식
2. 물리적인 폰트 파일 없이 <link>태그에 폰트 다운로드 주소를 넣거나 css @import 구문으로 google font 혹은 adobe font 같은 폰트 호스팅 서비스로 다운로드하는 CDN 방식
* 폰트 다루기 1탄에서는 물리적인 폰트파일로 설정하는 font-face방식을 다룹니다. CDN 방식은 2탄에서 다루겠습니다.이렇게 다운로드 받은 폰트를 웹폰트 라고 합니다. 실제로 많이 사용하는 Pretendard라는 폰트 공식문서를 같이 볼까요. 공식문서를 보면 폰트 다운로드가 있고, github을 가면 CDN 방식으로도 적용할 수 있도록 안내하고 있습니다.


출처 : pretendard 공식문서 https://cactus.tistory.com/306 이렇게 물리적인 폰트 파일 다운로드 방식과, <link> 태그, CSS @import로 다운로드 모두 제공하는 걸 확인할 수 있습니다. 폰트를 다운로드 하면 @font-face 설정부터 시작합니다.
1. @font-face 설정하기
1-1. 다운로드한 폰트 파일 구분하기
다운로드한 파일을 압축 해제 했더니 파일이 아닌 폴더로 구분되어 있을 수 있습니다. 만약 폴더가 public, web 이렇게 구분되어 있다면 참고하세요. public폴더 하위에 파일은 운영체제에 설치해서 시스템 폰트로 쓰일 파일이고 확장자는 .ttf 혹은 .otf 일 수 있습니다. web폴더 하위에 파일은 개발 프로젝트 폴더에 위치시켜서 사용하는 파일로 확장자가 .woff 혹은 .woff2 같은 웹 최적화 폰트형식일 수 있습니다. 우리가 font-face로 적용할 파일은 .woff 혹은 .woff2로 끝나는 파일이 필요합니다. 확장자에 대한 자세한 설명은 더 보기를 눌러보세요.
더보기web 폰트 폴더에, 'Static'과 'Variable' 두 가지 유형으로 구분되어 있을 수 있습니다. Static 폰트는 전통적으로 고정된 두께(예: ExtraBold, Bold, Regular)의 폰트 모음을 의미합니다. 폰트의 두께 별로 파일이 하나씩 존재해요. 반면, Variable (가변 폰트)는 사용자가 원하는 대로 두께를 조절할 수 있는 유연한 형태의 폰트입니다. 이 파일은 하나의 파일에서 다양한 두께를 제공합니다.
폰트파일의 확장자는. woff와. woff2, 그리고 'sub-set'이 있습니다.. woff는 대부분의 브라우저에서 지원되는 확장자로, 널리 사용됩니다.. woff2는. woff보다 약 30-50% 더 압축된 형식이며, 파일 크기가 작지만 모든 브라우저에서 지원되지는 않기 때문에 호환성을 확인해야 합니다.
'sub-set'은 특히 한글과 같은 합성어에 적용되는 형식입니다. 영문은 자음과 모음(a, e, i, o, u)에 해당하는 알파벳이 독립적으로 쓰일 수 있는 반면, 한글은 한 음절 (예시: 가) 적어도 자음(ㄱ)과 모음(ㅏ) 하나씩을 합성해야 1음절이 됩니다. 자음만 혹은 모음만 쓸 순 없죠. 한글 폰트는 이론적으로 자음과 모음의 모든 조합을 포함해야 하며, 이는 약 11,172자에 달합니다. 하지만 실제로 사용되지 않는 조합도 많기 때문에(예: 궳, 넭, 홓, 팕...), 국가 표준 규격인 KS X 1001에 따라 실제로 사용되는 2,350자 만을 포함하는 'sub-set' 폰트가 제작됩니다. 이 'sub-set' 폰트는 실 사용에 필요한 글자만을 포함하여 파일 크기를 줄이고, 로딩 시간을 단축하는데 도움을 줍니다.
1-2. 다운로드한 웹폰트 파일을 저장하기폰트의 굵기마다 파일이 하나씩 존재할 수 있습니다. 필요한 파일만 골라서 저장하는 것도 가능합니다. 프로젝트에 필요한 굵기의 폰트를 저장하시면 됩니다. 모든 굵기가 다 필요할 수도 있고, 특정 굵기만 필요할 수도 있어요. .woff 혹은 .woff2 확장자를 확인하세요.

1-3. CSS 파일에 @font-face 규칙쓰기다운로드한 fonts 파일을 프로젝트에 적용시키기 전에 CSS 파일(src/fonts/fonts.css)에서 @font-face 규칙을 설정하는 밑 작업이 필요합니다. 여기서 font-family는 식별할 수 있는 이름을 적습니다. src에는 폰트파일의 경로를 적고 어떤 format인지 적습니다. 마지막으로 해당 파일의 굵기 값을 적어주고, 어떤 스타일인지 적어주면 한가지 폰트에 대한 설정이 됩니다. 이걸 필요한 폰트만큼 반복하면 됩니다.
/* font-face 설정 예시 */ @font-face { font-family: <a-remote-font-name>; src: <source> [,<source>]*; [font-weight: <weight>]; [font-style: <style>]; } <a-remote-font-name> : font 속성에서 폰트명(font face)으로 지정될 이름을 설정 <source> : 원격 폰트(remote font) 파일의 위치를 나타내는 URL 값을 지정하거나, 사용자 컴퓨터(운영체제)에 설치된 폰트명을 local("Font Name")형식으로 지정하는 속성.즉 개발환경에서 설치된 폰트는 사용자환경에는 없기도 해서 url에 파일 경로를 잘 적어주는게 관건. format은 브라우저에게 폰트 파일 형식을 알려주는 속성. 적지않으면 브라우저는 자동으로 파일형식을 감지해서 처리. 하지만 명시적으로 형식을 지정하는게 좋은 관행입니다. <weight> : 폰트의 굵기(font weight) 값. (예 : 100, 300, 500, light, normal, bold) <style> : 폰트 스타일(font style) 값. (예: normal, italic, oblique) /* 출처 https://developer.mozilla.org/ko/docs/Web/CSS/@font-face *//* 예시를 적용한 예시코드 */ @font-face { font-family: 'Pretendard'; src: url('fonts/Pretendard-Thin.woff2') format('woff2'); font-weight: 100; /* Thin */ font-style: normal; } @font-face { font-family: 'Pretendard'; src: url('fonts/Pretendard-Light.woff2') format('woff2'); font-weight: 300; /* Light */ font-style: normal; } /* ... */ @font-face { font-family: 'Pretendard'; src: url('fonts/Pretendard-Black.woff2') format('woff2'); font-weight: 900; /* Black */ font-style: normal; }font format에 대해 더 자세한 설명은 아래 더 보기를 눌러주세요
더보기W3C의 CSS font-family 명세에 따르면 src 속성에 적용할 수 있는 format은 아래와 같습니다
string (입력 방법) Font Format(형식) Common extensions (확장자) "woff" WOFF 1.0 (Web Open Font Format) .woff "woff2" WOFF 2.0 (Web Open Font Format) .woff2 "truetype" TrueType .ttf "opentype" OpenType .ttf, .otf "embedded-opentype" Embedded OpenType .eot "svg" SVG Font .svg, .svgz 위에서. ttf(truetype),. otf(opentype)는 운영체제에 설치하는 확장자로 설명드렸습니다. 그런데 웹폰트 형식으로도 쓸 수 있다고 하네요?. woff 혹은. woff2, 그리고 sub-set을 웹폰트 형식으로 사용하는 이유 그리고,. otf,. ttf 파일을 웹폰트로 잘 사용하지 않는 이유가 있습니다.
가장 큰 차이는 파일 크기입니다. 예시로 Pretendard의 black 사이즈의 확장자별 용량은 다음과 같습니다.
확장자 크기 .ttf 2.7MB .otf 1.6MB .woff 1.1MB .woff2 802KB .subset.woff 354KB .subset.woff2 275KB 폰트 파일의 크기는 웹페이지 로딩 시간에 영향을 줄 수 있습니다. 폰트 파일 크기가 크면 폰트파일을 다운로드하는 시간이 오래 걸려서 웹폰트를 사용하는 텍스트는 폰트 파일이 로드될 때까지 표시되지 않을 수 있습니다.
또 다른 차이는 웹 호환성입니다. .ttf, .otf는 운영체제의 시스템 폰트에 적용하기 위한 형식으로 개발되었습니다. (TrueTypeFont,OpenTypeFont). woff는 2009년 웹에서 사용할 수 있는 포맷으로 개발됩니다. .ttf .otf 확장자로 웹 폰트를 쓸 순 있지만 웹에 최적화되어있지 않고, .woff는 개발부터 웹에서 사용하는 용도로 개발됐습니다. 그리고 .ttf 파일 형식의 압축버전이기도 합니다. 다만 운영체제에 설치할 수가 없죠. 그래서인지 .otf, .ttf를 검색해 보면 .woff로 변환하는 컨버팅 서비스들이 많이 검색됩니다. 재밌는 건,MDN에서도 .ttf를 .woff로 변환하는 방법을 알려줍니다. 웹에 최적화된 방식으로 사용하게끔 말이죠.
여기까지 font-face의 설정이 끝났다면 렌더 순서를 결정하는 font-family를 설정하러 가시죠.
2. font-family를 설정합니다.가족 구성원들을 비슷비슷하게 생겼어요. 그리고 "가족"이라는 특정 단위에 속해있죠. font-family도 마찬가지에요. 비슷하게 생긴 폰트끼리 그룹으로 묶어서 정의하는 속성이에요. 폰트는 크게 획의 삐침이 있는 세리프(serif), 획의 삐침이 없는 산세리프(sans serif)로 구분할 수 있는데 한글로 치면 명조체 그리고 고딕체 가 됩니다.

출처 - https://drmarkwomack.com/a-writing-handbook/style/typography/ 

어느쪽이 Helvetica 인지 Arial인지... 같은 폰트처럼 보이는 Hevetica,Arial 라는 sans-serif 계열 폰트 입니다. 만약 여러분이 웹 어플리케이션 개발에 Helvetica 폰트 하나만 설정했다고 가정해봅시다. 개발 환경에서는 Helvetica 폰트로 예쁘게 잘 만들었는데, 배포해보니 전혀다른 serif 폰트가 적용됐다면? 기획의도와 전혀 다른 어플리케이션을 보여주게 될꺼에요. 하지만 혹시나 Helvetica가 적용이 안될걸 대비해서 비슷한 폰트인 Arial을 백업 폰트로 설정했다면 큰 문제없이 수정이 가능할꺼에요. 이렇게 폰트 적용 우선순위에 따라서 설정할 수 있는 속성이 font-family 입니다.
font-family는 family-name, generic-name를 입력합니다.
우선 font-face에서 설정한 이름을 적거나, OS에 설치되어있는 font-name 등을 적습니다. font-face에 설정한 폰트를 적용하려면 font-family에도 같은 이름으로 적어야 합니다.예시코드의 "Gill sans"처럼 폰트 이름에 공백이 있을경우 따옴표(" ")로 감싸야하는 규칙이 있습니다.그리고 대소문자를 구분하지 않는 특징이 있습니다. font-face에는 pretendard라고 입력하고 font-family에는 Pretendard로 입력해도 이 둘은 같은 폰트를 참조합니다. 마지막으로 family name끼리는 쉼표(,)로 구분합니다.
generic-name은 family-name의 마지막에 적는데, family-name이 어떤 서체 종류 인지 나타내는 속성으로 특정 폰트 이름 대신 폰트의 일반적인 스타일이나 종류를 지정합니다. 브라우저가 지정된 폰트를 찾지 못했을 때 사용될 백업 폰트의 종류 이기도 합니다.
- serif : 획의 삐침이 있는 폰트 입니다.
- sans-serif : 획의 삐침이 없는 폰트 입니다.
- monospace : 모든 글자가 동일한 너비를 가진 폰트 입니다.
- cursive : 필기체 스타일 폰트 입니다.
- fantasy : 장식이 많고 독특한 스타일의 폰트 입니다.
- system-ui : 사용자 운영체제에 기본적으로 설정된 폰트 입니다.
아래와 같이 설정할 수 있습니다. Pretendard의 경우 아래와같은 font-family를 권장하고있습니다. 사용자 환경을 고려한다면 어떤 사용자에게도 같은 폰트로 렌더해야 하기때문에 아래쪽의 font-family를 적용하는것이 좋겠습니다.

아래의 예시코드 처럼 font-family를 설정했다면 우선 렌더 되는 폰트는 Helvetica부터 브라우저가 찾고, 만약 없으면 Arial이 렌더되고 Arial도 없다면 Gill sans가 렌더되는 식으로 폰트가 적용됩니다.
selector{ font-face : <family-name>, <generic-name> } /*예시코드*/ body{ font-face : Hevetica,Arial,"Gill sans",verdana,sans-serif; }



왼쪽 상단부터 시계방향으로 Helvetica -> Arial -> Gill sans -> verdana 순서로 적용됩니다. font-family 설정시 한가지 주의할점이 있습니다. 운영체제(MacOS Window)에 설치한 폰트랑 font-face에서 설정한 폰트가 같으면 디버깅 하기 어려울 수 있습니다. 왜냐하면 브라우저는 font-face에 설정한 대로 폰트를 찾습니다. 그런데 오탈자, 맞지않는 폰트파일 경로 같은 이유로 인해 font-face에 설정한 폰트를 찾지못하면 같은 이름을 가진 시스템 폰트에서 찾아 렌더합니다. 이럴경우 개발환경에서는 시스템 폰트로 적용되어있는지 모르고 배포하기도 합니다. 그래서 가능하면 운영체제에는 프로젝트에서 사용하는 폰트를 설치하지 않는게 좋습니다.
font-family도 설정이 다 되었습니다. 이젠 어플리케이션에 적용하러 가볼까요.
3. 폰트 적용하기
3-1. 어플리케이션 전역에 적용하기
설정은 다 끝났습니다. 적용만 남았습니다. 어플리케이션의 모든 텍스트를 pretendard로 적용하는걸 가정해서 말씀 드리겠습니다. 어플리케이션 전역에 적용해야 하기때문에 body태그 하위에 모든 텍스트에 적용하도록 설정했습니다. 이렇게하면 body태그 하위에 요소들은 body의 설정을 상속 받기 때문에 하위 요소마다 일일이 font-family를 적어주지않아도 됩니다. 단, form-field는 예외입니다. 이부분은 2탄에서 설명드리겠습니다.
/* src/index.css */ body{ font-family:pretendard,sans-serif }index.css파일에 정의가 되었다면 indes.css파일, 그리고 fonts.css 파일을 index.js에서 import 합니다. 이제 어플리케이션 전역에 설정한 폰트가 동일하게 적용되었다고 브라우저는 알게 됐습니다.
// src/index.js import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App/App'; import './index.css'; <<<<<<<추가 import './fonts/fonts.css' <<<<<<<추가 const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <App /> </React.StrictMode> );3-2. 컴포넌트에 적용하기
App 컴포넌트에서 설정한 폰트의 굵기마다 잘 렌더 되는지 css파일을 추가해서 렌더 해 보겠습니다. npm start로 로컬서버를 띄워서 실제로 브라우저에 잘 나오는지 확인 해 보세요.
/* src/App/App.css */ .black{ font-weight:900; font-size:30px; } .extraBold{ font-weight:800; font-size:28px; } /* ...중략 */ .extraLight{ font-weight:200; font-size:16px; } .thin{ font-weight:100; font-size:14px; }import './App.css' function App() { return ( <div className="App"> <p className="black">Black <br/>대법원과 각급법원의 조직은 법률로 정한다. 국교는 인정되지 아니하며, 종교와 정치는 분리된다. 대통령이...</p> <p className="extraBold">ExtraBold <br/>국정감사 및 조사에 관한 절차 기타 필요한 사항은 법률로 정한다. 모든 국민은 법률이 정하는 바에 의하여...</p> /...중략/ <p className="extraLight">ExtraLight <br/>국가는 여자의 복지와 권익의 향상을 위하여 노력하여야 한다. 비상계엄이 선포된 때에는 법률이 정하는 바...</p> <p className="thin">Thin <br/>광물 기타 중요한 지하자원·수산자원·수력과 경제상 이용할 수 있는 자연력은 법률이 정하는 바에 의하여...</p> </div> ); } export default App;3-3 진짜 잘 된건가? 개발자도구로 확인하기
설정대로 잘 렌더되는것 같습니다. 그런데 화면만 보고 판단하긴 아직 이릅니다.

내가 설정한대로 잘 된건지 확인하려면 개발자도구에서 Elements 탭에 있는 Computed 패널에서 Rendered Fonts 부분을 확인하시면 됩니다. 설정한대로 잘 나오고 있네요.

Rendered Fonts에 Apple SD, Noto Sans 이런게 들어있다면 설정해둔 폰트 파일을 다시 유심히 보면서 디버깅 해야합니다.. 마무리
Q. font-face에 font-weight를 적었는데, 컴포넌트에서 또 font-weight를 적어야 하나요?
A. 네. 또 적어야 합니다. 사용되는 목적이 달라서 그렇습니다.
font-face는 브라우저한테 "./Pretendard-black.woff2"경로에 파일은 폰트 굵기가 900이고 스타일은 normal이야 라고 알려주는것 입니다.컴포넌트에서 설정하는 font-weight는 해당 스타일을 적용하려고 하는 HTML요소에 특정 굵기를 적용할 때 씁니다. 이 경우 브라우저는 font-face 규칙중 font-weight가 900인 폰트 스타일을 찾아서 적용합니다.Q.font-face에서 font-weight, font-style을 정의하지않으면 어떻게 되나요?
A.font-weight가 없으면 100에서 900까지 9단계중 가운데인 400으로 사용됩니다. font-style이 없으면 normal 스타일이 사용됩니다. 그런데, 만약 위의 예시 처럼 font-face에서 여러 폰트 파일을 동일한 font-family 이름으로 정의하고 각각 font-face에 대해 font-weight를 지정하지않는 경우 브라우저는 어떤 폰트 파일을 사용해야할지 명확하게 구분하지 못하기때문에 가장 마지막에 정의된 font-face를 사용할 수 있습니다. 지금의 경우는 thin이 적용됩니다. 그래서 font-face마다 font-weight값을 명시하는게 중요합니다.
참고자료
기본적인 텍스트 및 글꼴 스타일링 - Web 개발 학습하기 | MDN
이 기사에서는 CSS 를 사용하여 텍스트 스타일링을 마스터하기 위한 과정을 시작합니다. 여기에서는 글꼴 굵기, 종류 및 스타일, 글꼴 약식 (shorthand), 텍스트 정렬 및 기타 효과, 줄 및 문자 간격
developer.mozilla.org
CSS Fonts Module Level 3
This CSS3 module describes how font properties are specified and how font resources are loaded dynamically. The contents of this specification are a consolidation of content previously divided into CSS3 Fonts and CSS3 Web Fonts modules. The description of
www.w3.org
What Font Should I Use? – Dr. Mark Womack
What Font Should I Use? The Modern Language Association (MLA) provides explicit, specific recommendations for the margins and spacing of academic papers. (See: Document Format.) But their advice on font selection is less precise: “Always choose an easily
drmarkwomack.com
Pretendard
Pretendard 프리텐다드 Pretendard 프리텐다드 글꼴 다운로드 일본어 버전 다운로드 GitHub에서 보기 system-ui를 대체하는 글꼴 Apple의 system-ui가 익숙한 나로서는 San Francisco와 Apple SD 산돌고딕 Neo가 없는
cactus.tistory.com
@font-face - CSS: Cascading Style Sheets | MDN
CSS at-rule 인 @font-face 를 사용하여 웹페이지의 텍스트에 온라인폰트(online fonts)를 적용할 수 있다. @font-face 를 사용하여 웹페이지 제작자가 원하는 폰트를 사용할 수 있게함으로써, 컴퓨터에 설치
developer.mozilla.org
'일찍 알았으면 좋았을 넓고 얕은 개발 지식' 카테고리의 다른 글
브라우저에서 자바스크립트 코드가 실행되는 과정? (5) 2024.11.10 일찍 알았으면 좋았을 호이스팅 (1) 2024.10.27 브라우저 렌더링은 무엇일까. (2) 2024.10.11 git local 브랜치에서 remote 브랜치를 병합할 때 옵션 (2) 2024.02.04 타입스크립트로 함수 선언 그리고 호출할 때 반드시 해야하는것. (2) 2024.01.21