줍줍 프로젝트는 슬랙 메시지를 아카이빙하는 서비스입니다.
프로젝트 github
이번 글에서는 React 프로젝트를 진행할 경우 폰트를 다루는 방법에 대해 소개하려고 한다. 폰트를 다루는 방법을 설명하기에 앞서 웹 폰트란 무엇인지? 웹 폰트 형식은 어떤게 있는지 먼저 확인해보자.
웹 폰트는 사용자가 가지고 있지 않은 폰트를 웹 페이지에서 사용할 수 있는 방법입니다. 해당하는 사이트에 접속할 경우 웹 폰트를 서버에서 다운로드하는 방식이라고 할 수 있습니다.
웹폰트는 기본적으로 TTF, OTF, EOT, WOFF, WOFF2 처럼 다양한 형식이 존재한다.
아래 이미지는 Roboto font를 ttf, otf, woff, woff2 형식으로 변환후 용량의 차이를 비교한 이미지이다.
위 이미지를 확인하면 폰트 형식이 다른 이유는 용량차이가 있다는 것을 알 수 있다. woff2 < woff < ttf < otf 순으로 폰트의 용량 차이가 존재한다. 따라서 폰트를 사용할 때는 woff2, woff, ttf, otf 순으로 사용하는게 다운로드 속도를 줄여 보다 나은 사용자 경험을 제공할 수 있다는 것을 확인할 수 있다.
그럼 여기서 드는 의문은 woff2 폰트 형식이 용량이 작은데 woff2만 사용하면 되는거 아닌가? 라는 것이다. 단순하게 생각하면 woff2의 font만 설정해주면 되지만, font 형식에 따른 브라우저 지원 상황이 모두 다르기 때문에 현재 프로젝트가 어떤 브라우저를 타겟을 서비스를 제공하는 지에 따라 추가로 설정해주는게 좋다고 생각한다.
다들 아시겠지만, Can i use 사이트를 확인하면 브라우저 지원 현황을 확인할 수 있다.
@font-face의 속성은 다양하지만 font-family, src, font-display 속성에 대해서만 확인해보자.
css 문서에서 사용할 웹 폰트 패밀리명을 명시해줄 수 있는 속성이다.
@font-face {
font-family: 'Roboto-Medium';
src: url(Roboto-Medium.woff2) format('woff2')
}
반드시 Roboto font를 사용한다고 Roboto라고 font-family 속성값을 명시해줄 필요는 없지만, 유지보수 측면을 고려해 보편적으로 통일해 사용한다.
src속성에 사용할 수 있는 속성값으로는 local()
, url()
이 존재한다. 먼저 local()속성을 사용하게 되면, 로컬에 이미 설치 된 폰트명을 적을 수 있다. 다음으로 url() 속성은 폰트를 다운로드 할 경로를 적어줄 수 있다.
@font-face {
font-family: 'Roboto-Medium';
src: local('Roboto-Medium'),
url('./Roboto-Medium.woff2') format('woff2'),
url('./Roboto-Medium.woff') format('woff'),
url('./Roboto-Medium.ttf') format('truetype'),
url('./Roboto-Medium.otf') format('opentype'),
}
위 코드에 src 속성에 여러가지 속성값을 설정한 이유는 첫번째로 local에 설치된 Roboto-Medium 폰트가 있는지 확인 한 후 있다면 local 폰트를 사용하고, 그렇지 않을 경우 woff2 → woff → ttf → otf 순으로 폰트를 다운 받아 사용한다.
font-display는 웹 폰트의 로딩 상태에 따른 다른 동작을 설정할 수 있다.
속성 값으로는 auto, block, swap, fallback, optional 이 존재하는데 swap, fallback, optional에 대해서만 확인해보도록 하자.
swap
@font-face {
// some code...
font-display: swap;
}
fallback
@font-face {
// some code...
font-display: fallback;
}
optional
@font-face {
// some code...
font-display: optional;
}
서버에 직접 업로드하는 경우 @font-face를 직접 설정해줘야한다. 폰트를 많이 사용할 수록 @font-face를 많이 선언해줘야해서 번거로운 부분이 있지만, woff2, woff 폰트를 지원하지 않는 구형 브라우저에도 대응을 할 수 있다는 장점이 존재한다.
@font-face {
font-family: 'Roboto-Medium';
src: local('Roboto-Medium'),
url(Roboto-Medium.woff2) format('woff2'),
url(Roboto-Medium.woff) format('woff'),
url(Roboto-Medium.ttf) format('truetype'),
url(Roboto-Medium.otf) format('opentype'),
font-display: swap;
}
구글 CDN을 사용하게 되면 @font-face를 직접 설정해주지 않아도 되서 편리하지만, 구글 CDN 서버에 문제가 있을 경우 font를 다운로드하지 못하는 문제가 발생할 수 있다. (신뢰되지 않는 CDN Server의 경우)
또한, IE를 지원하는 서비스일 경우 font를 사용할 수 없는 문제가 발생한다. (구글 CDN은 woff, woff2만 지원한다.)
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap"
rel="stylesheet"
/>
Roboto 폰트(구글 폰트)와 tway_air 폰트를 CDN으로 불러오는 경우와 서버에 올려 사용하는 방식의 속도 차이를 확인해보자.
tway_air 폰트 CDN
tway_air 폰트 Server
구글 CDN이 아닌 tway_air 폰트는 두 가지 방식의 속도 및 용량 차이가 거의 나지 않는다.
Roboto 폰트 CDN
구글 폰트는 CDN에서 CSS 파일을 받아오기 때문에 용량 자체도 작고 속도 빠르다.
하지만 CSS로드를 한 이후 폰트를 불러오기 위해서는 다시 요청을 보내야한다.
Roboto 폰트 Server
구글 폰트의 경우 속도 측면에서는 CDN에서 불러오는게 보다 빠르다는 것을 확인할 수 있다.
서브셋 폰트(subset font)는 폰트 파일에서 불필요한 글자를 제거하고 사용할 글자만 남겨둔 폰트다.
실제로 한글을 사용하면서 사용되지 않은 글자를 배제하고, 꼭 필요한 글자만을 모아놓은 국가 표준 한글 2,350자 라고 한다.
가각간갇갈갉갊감갑값갓갔강갖갗같갚갛개객갠갤갬갭갯갰갱갸갹갼걀걋걍걔걘걜거걱건걷걸걺검겁것겄겅겆겉겊겋게겐겔겜겝겟겠겡겨격겪견겯결겸겹겻겼경곁계곈곌곕곗고곡곤곧골곪곬곯곰곱곳공곶과곽관괄괆괌괍괏광괘괜괠괩괬괭괴괵괸괼굄굅굇굉교굔굘굡굣구국군굳굴굵굶굻굼굽굿궁궂궈궉권궐궜궝궤궷귀귁귄귈귐귑귓규균귤그극근귿글긁금급긋긍긔기긱긴긷길긺김깁깃깅깆깊까깍깎깐깔깖깜깝깟깠깡깥깨깩깬깰깸깹깻깼깽꺄꺅꺌꺼꺽꺾껀껄껌껍껏껐껑께껙껜껨껫껭껴껸껼꼇꼈꼍꼐꼬꼭꼰꼲꼴꼼꼽꼿꽁꽂꽃꽈꽉꽐꽜꽝꽤꽥꽹꾀꾄꾈꾐꾑꾕꾜꾸꾹꾼꿀꿇꿈꿉꿋꿍꿎꿔꿜꿨꿩꿰꿱꿴꿸뀀뀁뀄뀌뀐뀔뀜뀝뀨끄끅끈끊끌끎끓끔끕끗끙끝끼끽낀낄낌낍낏낑나낙낚난낟날낡낢남납낫났낭낮낯낱낳내낵낸낼냄냅냇냈냉냐냑냔냘냠냥너넉넋넌널넒넓넘넙넛넜넝넣네넥넨넬넴넵넷넸넹녀녁년녈념녑녔녕녘녜녠노녹논놀놂놈놉놋농높놓놔놘놜놨뇌뇐뇔뇜뇝뇟뇨뇩뇬뇰뇹뇻뇽누눅눈눋눌눔눕눗눙눠눴눼뉘뉜뉠뉨뉩뉴뉵뉼늄늅늉느늑는늘늙늚늠늡늣능늦늪늬늰늴니닉닌닐닒님닙닛닝닢다닥닦단닫달닭닮닯닳담답닷닸당닺닻닿대댁댄댈댐댑댓댔댕댜더덕덖던덛덜덞덟덤덥덧덩덫덮데덱덴델뎀뎁뎃뎄뎅뎌뎐뎔뎠뎡뎨뎬도독돈돋돌돎돐돔돕돗동돛돝돠돤돨돼됐되된될됨됩됫됴두둑둔둘둠둡둣둥둬뒀뒈뒝뒤뒨뒬뒵뒷뒹듀듄듈듐듕드득든듣들듦듬듭듯등듸디딕딘딛딜딤딥딧딨딩딪따딱딴딸땀땁땃땄땅땋때땍땐땔땜땝땟땠땡떠떡떤떨떪떫떰떱떳떴떵떻떼떽뗀뗄뗌뗍뗏뗐뗑뗘뗬또똑똔똘똥똬똴뙈뙤뙨뚜뚝뚠뚤뚫뚬뚱뛔뛰뛴뛸뜀뜁뜅뜨뜩뜬뜯뜰뜸뜹뜻띄띈띌띔띕띠띤띨띰띱띳띵라락란랄람랍랏랐랑랒랖랗래랙랜랠램랩랫랬랭랴략랸럇량러럭런럴럼럽럿렀렁렇레렉렌렐렘렙렛렝려력련렬렴렵렷렸령례롄롑롓로록론롤롬롭롯롱롸롼뢍뢨뢰뢴뢸룀룁룃룅료룐룔룝룟룡루룩룬룰룸룹룻룽뤄뤘뤠뤼뤽륀륄륌륏륑류륙륜률륨륩륫륭르륵른를름릅릇릉릊릍릎리릭린릴림립릿링마막만많맏말맑맒맘맙맛망맞맡맣매맥맨맬맴맵맷맸맹맺먀먁먈먕머먹먼멀멂멈멉멋멍멎멓메멕멘멜멤멥멧멨멩며멱면멸몃몄명몇몌모목몫몬몰몲몸몹못몽뫄뫈뫘뫙뫼묀묄묍묏묑묘묜묠묩묫무묵묶문묻물묽묾뭄뭅뭇뭉뭍뭏뭐뭔뭘뭡뭣뭬뮈뮌뮐뮤뮨뮬뮴뮷므믄믈믐믓미믹민믿밀밂밈밉밋밌밍및밑바박밖밗반받발밝밞밟밤밥밧방밭배백밴밸뱀뱁뱃뱄뱅뱉뱌뱍뱐뱝버벅번벋벌벎범법벗벙벚베벡벤벧벨벰벱벳벴벵벼벽변별볍볏볐병볕볘볜보복볶본볼봄봅봇봉봐봔봤봬뵀뵈뵉뵌뵐뵘뵙뵤뵨부북분붇불붉붊붐붑붓붕붙붚붜붤붰붸뷔뷕뷘뷜뷩뷰뷴뷸븀븃븅브븍븐블븜븝븟비빅빈빌빎빔빕빗빙빚빛빠빡빤빨빪빰빱빳빴빵빻빼빽뺀뺄뺌뺍뺏뺐뺑뺘뺙뺨뻐뻑뻔뻗뻘뻠뻣뻤뻥뻬뼁뼈뼉뼘뼙뼛뼜뼝뽀뽁뽄뽈뽐뽑뽕뾔뾰뿅뿌뿍뿐뿔뿜뿟뿡쀼쁑쁘쁜쁠쁨쁩삐삑삔삘삠삡삣삥사삭삯산삳살삵삶삼삽삿샀상샅새색샌샐샘샙샛샜생샤샥샨샬샴샵샷샹섀섄섈섐섕서석섞섟선섣설섦섧섬섭섯섰성섶세섹센셀셈셉셋셌셍셔셕션셜셤셥셧셨셩셰셴셸솅소속솎손솔솖솜솝솟송솥솨솩솬솰솽쇄쇈쇌쇔쇗쇘쇠쇤쇨쇰쇱쇳쇼쇽숀숄숌숍숏숑수숙순숟술숨숩숫숭숯숱숲숴쉈쉐쉑쉔쉘쉠쉥쉬쉭쉰쉴쉼쉽쉿슁슈슉슐슘슛슝스슥슨슬슭슴습슷승시식신싣실싫심십싯싱싶싸싹싻싼쌀쌈쌉쌌쌍쌓쌔쌕쌘쌜쌤쌥쌨쌩썅써썩썬썰썲썸썹썼썽쎄쎈쎌쏀쏘쏙쏜쏟쏠쏢쏨쏩쏭쏴쏵쏸쐈쐐쐤쐬쐰쐴쐼쐽쑈쑤쑥쑨쑬쑴쑵쑹쒀쒔쒜쒸쒼쓩쓰쓱쓴쓸쓺쓿씀씁씌씐씔씜씨씩씬씰씸씹씻씽아악안앉않알앍앎앓암압앗았앙앝앞애액앤앨앰앱앳앴앵야약얀얄얇얌얍얏양얕얗얘얜얠얩어억언얹얻얼얽얾엄업없엇었엉엊엌엎에엑엔엘엠엡엣엥여역엮연열엶엷염엽엾엿였영옅옆옇예옌옐옘옙옛옜오옥온올옭옮옰옳옴옵옷옹옻와왁완왈왐왑왓왔왕왜왝왠왬왯왱외왹왼욀욈욉욋욍요욕욘욜욤욥욧용우욱운울욹욺움웁웃웅워웍원월웜웝웠웡웨웩웬웰웸웹웽위윅윈윌윔윕윗윙유육윤율윰윱윳융윷으윽은을읊음읍읏응읒읓읔읕읖읗의읜읠읨읫이익인일읽읾잃임입잇있잉잊잎자작잔잖잗잘잚잠잡잣잤장잦재잭잰잴잼잽잿쟀쟁쟈쟉쟌쟎쟐쟘쟝쟤쟨쟬저적전절젊점접젓정젖제젝젠젤젬젭젯젱져젼졀졈졉졌졍졔조족존졸졺좀좁좃종좆좇좋좌좍좔좝좟좡좨좼좽죄죈죌죔죕죗죙죠죡죤죵주죽준줄줅줆줌줍줏중줘줬줴쥐쥑쥔쥘쥠쥡쥣쥬쥰쥴쥼즈즉즌즐즘즙즛증지직진짇질짊짐집짓징짖짙짚짜짝짠짢짤짧짬짭짯짰짱째짹짼쨀쨈쨉쨋쨌쨍쨔쨘쨩쩌쩍쩐쩔쩜쩝쩟쩠쩡쩨쩽쪄쪘쪼쪽쫀쫄쫌쫍쫏쫑쫓쫘쫙쫠쫬쫴쬈쬐쬔쬘쬠쬡쭁쭈쭉쭌쭐쭘쭙쭝쭤쭸쭹쮜쮸쯔쯤쯧쯩찌찍찐찔찜찝찡찢찧차착찬찮찰참찹찻찼창찾채책챈챌챔챕챗챘챙챠챤챦챨챰챵처척천철첨첩첫첬청체첵첸첼쳄쳅쳇쳉쳐쳔쳤쳬쳰촁초촉촌촐촘촙촛총촤촨촬촹최쵠쵤쵬쵭쵯쵱쵸춈추축춘출춤춥춧충춰췄췌췐취췬췰췸췹췻췽츄츈츌츔츙츠측츤츨츰츱츳층치칙친칟칠칡침칩칫칭카칵칸칼캄캅캇캉캐캑캔캘캠캡캣캤캥캬캭컁커컥컨컫컬컴컵컷컸컹케켁켄켈켐켑켓켕켜켠켤켬켭켯켰켱켸코콕콘콜콤콥콧콩콰콱콴콸쾀쾅쾌쾡쾨쾰쿄쿠쿡쿤쿨쿰쿱쿳쿵쿼퀀퀄퀑퀘퀭퀴퀵퀸퀼큄큅큇큉큐큔큘큠크큭큰클큼큽킁키킥킨킬킴킵킷킹타탁탄탈탉탐탑탓탔탕태택탠탤탬탭탯탰탱탸턍터턱턴털턺텀텁텃텄텅테텍텐텔템텝텟텡텨텬텼톄톈토톡톤톨톰톱톳통톺톼퇀퇘퇴퇸툇툉툐투툭툰툴툼툽툿퉁퉈퉜퉤튀튁튄튈튐튑튕튜튠튤튬튱트특튼튿틀틂틈틉틋틔틘틜틤틥티틱틴틸팀팁팃팅파팍팎판팔팖팜팝팟팠팡팥패팩팬팰팸팹팻팼팽퍄퍅퍼퍽펀펄펌펍펏펐펑페펙펜펠펨펩펫펭펴편펼폄폅폈평폐폘폡폣포폭폰폴폼폽폿퐁퐈퐝푀푄표푠푤푭푯푸푹푼푿풀풂품풉풋풍풔풩퓌퓐퓔퓜퓟퓨퓬퓰퓸퓻퓽프픈플픔픕픗피픽핀필핌핍핏핑하학한할핥함합핫항해핵핸핼햄햅햇했행햐향허헉헌헐헒험헙헛헝헤헥헨헬헴헵헷헹혀혁현혈혐협혓혔형혜혠혤혭호혹혼홀홅홈홉홋홍홑화확환활홧황홰홱홴횃횅회획횐횔횝횟횡효횬횰횹횻후훅훈훌훑훔훗훙훠훤훨훰훵훼훽휀휄휑휘휙휜휠휨휩휫휭휴휵휸휼흄흇흉흐흑흔흖흗흘흙흠흡흣흥흩희흰흴흼흽힁히힉힌힐힘힙힛힝
한글 자음 및 모음
ㄱㄲㄳㄴㄵㄶㄷㄸㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅃㅄㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ
숫자와 기호 및 영문
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!"\#$%&'()*+,-./:;<=>?@[^_`|
위 세가지를 합쳐서 생성하게 되면 한글 영문 숫자와 기호가 들어간 subset font를 생성할 수 있다.
그럼 가장 중요한 subset font를 적용하게 되면 용량 차이가 얼마나 나는지 확인해보자!
용량차이가 생각보다 많이 나는 것을 확인할 수 있습니다.
줍줍 프로젝트 내부에는 총 두 가지의 폰트(tway_air, Roboto)를 사용하고 있다.
기존에 프로젝트 내부에서 폰트를 사용하는 방법은 아래와 같았다.
const GlobalStyle = createGlobalStyle<{ theme: Theme }>`
@font-face {
font-family: 'Roboto';
font-weight: 300;
font-display: swap;
src: local('Roboto-Light'), url(${RobotoLightWoff2}) format('woff2'), url(${RobotoLightWoff}) format('woff'), url(${RobotoLightTtf}) format('truetype');
}
@font-face {
font-family: 'Roboto';
font-weight: 400;
font-display: swap;
src: local('Roboto-Regular'), url(${RobotoRegularWoff2}) format('woff2'), url(${RobotoRegularWoff}) format('woff'), url(${RobotoRegularTtf}) format('truetype');
}
@font-face {
font-family: 'Roboto';
font-weight: 600;
font-display: swap;
src: local('Roboto-Bold'), url(${RobotoBoldWoff2}) format('woff2'), url(${RobotoBoldWoff}) format('woff'), url(${RobotoBoldTtf}) format('truetype');
}
@font-face {
font-family: 'Twayair';
font-display: swap;
src: url(${TwayairWoff2}) format('woff2'), url(${TwayairWoff}) format('woff'), url(${TwayairTtf}) format('truetype');
}
// some code ...
`;
tway_air 폰트는 preload를 통해 다운로드를 진행해주고, Roboto 폰트는 프리로드를 하지 않고 사용하고 있었다. 이유는 tway_air 폰트의 경우 생소한 폰트이기 때문에 사용자 컴퓨터에 다운로드 되어있을 확률이 낮다고 생각해서 preload를 통해 조금 더 빠른 다운로드를 진행해주었고, Roboto 폰트의 경우는 자주 사용하는 폰트?! 라는 생각에 preload를 해주지 않고 사용자 컴퓨터에 폰트가 다운로드 되어있을 경우 local에서 해당하는 폰트를 import 할 수 있도록 설정을 해주었다.
폰트에 대해 추가적으로 공부하고 정리하면서 잘못된 생각들이 있다는 것을 알게 되었다.
첫 번째. 일반적인 사용자는 컴퓨터에 내장된 폰트를 사용하지 폰트를 다운로드하는 사용자들은 많지 않다는 점이다.
두번째. 프로젝트에서 tway_air 폰트를 사용하고 있지만 자주 접근하지 않는 2페이지를 제외한 페이지에서는 tway_air 폰트를 사용하지 않는다는 점이다.
따라서, tway_air 폰트의 preload는 제거해주고, Roboto font의 local 속성을 제거한 후 preload를 할 수 있도록 설정해줬다. 모든 폰트에 font-display: swap 옵션을 설정해줬는데, 네트워크 환경이 어떻던 간에 font 로드가 되면 우리의 폰트로 대체될 수 있도록 만들어 주기 위해서 설정해줬다.
Roboto 폰트의 경우 구글 CDN을 사용하지 않은 이유는?
const GlobalStyle = createGlobalStyle<{ theme: Theme }>`
@font-face {
font-family: 'Roboto';
font-weight: 300;
font-display: swap;
src: url(${RobotoLightWoff2}) format('woff2'), url(${RobotoLightWoff}) format('woff'), url(${RobotoLightTtf}) format('truetype');
}
@font-face {
font-family: 'Roboto';
font-weight: 400;
font-display: swap;
src: url(${RobotoRegularWoff2}) format('woff2'), url(${RobotoRegularWoff}) format('woff'), url(${RobotoRegularTtf}) format('truetype');
}
@font-face {
font-family: 'Roboto';
font-weight: 600;
font-display: swap;
src: url(${RobotoBoldWoff2}) format('woff2'), url(${RobotoBoldWoff}) format('woff'), url(${RobotoBoldTtf}) format('truetype');
}
@font-face {
font-family: 'Twayair';
font-display: swap;
src: url(${TwayairWoff2}) format('woff2'), url(${TwayairWoff}) format('woff'), url(${TwayairTtf}) format('truetype');
}
// some code ...
`;
https://d2.naver.com/helloworld/4969726
https://boramyy.github.io/dev/front-end/etc/font/