현재 개인 포트폴리오 웹 페이지를 Next.js와 Material UI를 활용하여 개발하고 있다.
이전 프로젝트에서 컴포넌트를 css로 하나하나 직접 만들어서 atomic design pattern을 적용했다면, 이번에는 Material UI를 활용했다. 기본적인 컴포넌트들이 이미 구성된 상태에서 내가 원하는 방식과 형태로 커스터마이징해서 하는 방식이 훨씬 효율적으로 다가왔다.
포트폴리오 디자인
포트폴리오의 디자인 컨셉은 사용자에게 시각적으로 편안하고, 전체적으로 부드러운 느낌을 주는 것이다.
영어는 DM Serif Display, 한국어는 Gowun Batang을 사용했다.
폰트 적용
Next.js와 Material UI에는 기본적으로 적용되는 폰트가 있다. 하지만 내가 원하는 폰트를 사용하려면 몇 가지 설정이 필요했다.
Next.js 공식 문서에서 여러 폰트를 적용하는 방법을 참고하여, 내가 원하는 폰트를 적용했다.
https://nextjs.org/docs/app/building-your-application/optimizing/fonts#using-multiple-fonts
Optimizing: Fonts | Next.js
Optimize your application's web fonts with the built-in `next/font` loaders.
nextjs.org
// styles/font.ts
import { Gowun_Batang, DM_Serif_Display } from 'next/font/google';
const gowunBatang = Gowun_Batang({
weight: ['400', '700'],
style: ['normal'],
subsets: ['latin'],
display: 'swap', // 화면에 폰트가 로딩되기 전 기본 폰트가 적용되도록 함
});
const dmSerifDisplay = DM_Serif_Display({
weight: ['400'],
style: ['normal', 'italic'],
subsets: ['latin'],
display: 'swap',
});
export { gowunBatang, dmSerifDisplay };
next/font/google에서 DM Serif Display와 Gowun Batang 폰트를 import한 후, 각 폰트의 기본 스타일을 포함하여 유틸리티 함수를 만들어 개발 환경에서 사용할 수 있도록 폰트를 export하는 방식으로 구성했다.
Text 컴포넌트 생성
한국어 폰트와 영어 폰트를 다르게 적용해야 했기 때문에 새로운 컴포넌트를 생성하여 적용했다.
'use client';
import { dmSerifDisplay, gowunBatang } from '@/styles/font.ts';
import { Typography, TypographyProps } from '@mui/material';
type TextProps = TypographyProps & {
children: React.ReactNode;
language: 'en' | 'ko';
};
const Text: React.FC<TextProps> = ({ language, children, sx, ...rest }) => {
return (
<>
{language === 'ko' ? (
<Typography className={gowunBatang.className} sx={{ ...sx }} {...rest}>
{children}
</Typography>
) : (
<Typography
className={dmSerifDisplay.className}
sx={{ ...sx }} // 사용자가 전달한 sx 스타일을 병합
{...rest}
>
{children}
</Typography>
)}
</>
);
};
export default Text;
language prop에 따라 한국어와 영어 폰트를 다르게 적용할 수 있도록 구성했다.
폰트는 className으로 적용했는데, 여기서 문제가 발생했다.
문제: dev 서버에서는 잘 적용돼서 보이던 폰트가 production 서버에서는 적용되지 않음
dev 서버와 production 서버에서 폰트가 다르게 적용되는 이유는 빌드 과정의 차이와 환경 설정 등 여러 가지 복합적인 문제가 존재하는 것으로 보였다.
그래서 우선 production 서버에서 폰트 스타일이 어떻게 적용되고 있는지 확인해봤고, 폰트가 적용되지 않는 원인을 알 수 있었다.
원인: MUI의 sx prop에 적용된 스타일이 className을 통해 적용된 스타일보다 우선순위가 높다.
첨부한 사진에서 보이는 것과 같이, className을 사용하여 폰트 패밀리를 설정했으나, production 서버에는 MUI의 Typography 컴포넌트에 기본적으로 설정되어 있는 폰트 스타일이 적용되어 있었다.
MUI의 sx prop을 통해 컴포넌트 안에 스타일을 바로 정의하는 것이기 때문에 인라인 스타일처럼 동작하는 것으로 추측된다. 인라인 스타일은 일반적으로 CSS 규칙에서 우선순위가 가장 높기 때문에, className을 통해 설정된 스타일보다 우선 적용되는 것이다.
해결: className 대신 sx prop 내부에서 직접 폰트 패밀리를 설정하는 방식으로 변경
'use client';
import { dmSerifDisplay, gowunBatang } from '@/styles/font.ts';
import { Typography, TypographyProps } from '@mui/material';
type TextProps = TypographyProps & {
children: React.ReactNode;
language: 'en' | 'ko';
};
const Text: React.FC<TextProps> = ({ language, children, sx, ...rest }) => {
return (
<>
{language === 'ko' ? (
<Typography sx={{ fontFamily: gowunBatang.style, ...sx }} {...rest}>
{children}
</Typography>
) : (
<Typography
sx={{ fontFamily: dmSerifDisplay.style, ...sx }} // 사용자가 전달한 sx 스타일을 병합
{...rest}
>
{children}
</Typography>
)}
</>
);
};
export default Text;