astro + tailwind로 이전 했습니다.
Next.js 기반 정적 블로그를 Astro + Tailwind로 이주하면서 얻은 것들(속도, 단순함, 디자인 시스템).
따라서 다양한 렌더링 옵션을 활용해 유연하고 효율적인 블로그를 만들어보고자 Next.js를 선택했습니다.
MDX는 Markdown 문법에 React 컴포넌트를 섞어 쓸 수 있게 해주는 포맷입니다. 기존에도 Gatsby MDX 플러그인을 활용하여 블로그 포스트를 작성할 수 있었지만, Next.js에서 MDX를 사용하기 위해선 ‘next-mdx-remote’나 ‘@next/mdx’ 같은 패키지를 도입하게 됩니다.
저는 블로그 포스트를 각 마크다운(MDX) 파일로 관리하고, 빌드 시점(혹은 ISR) 또는 요청 시점(SSR)에 해당 MDX 파일을 파싱해주도록 설정했습니다. 이를 통해 새로운 글을 작성하거나 수정할 때의 프로세스를 간소화할 수 있었습니다.
결국, 다양한 컴포넌트, 풍부한 Material 생태계, 그리고 디자인 표준성 때문에 MUI를 선택했습니다.
npx create-next-app my-blog
touch tsconfig.json
npm install --save-dev typescript @types/react @types/node
의존성 설치
npm install next-mdx-remote gray-matter remark remark-html
MDX 파일 로딩 로직 구현
‘libraries/PostManager.ts’ 같은 곳에, 아래와 같은 함수를 만들어서 마크다운을 파싱합니다.
import matter from 'gray-matter';
import { serialize } from 'next-mdx-remote/serialize';
export async function getPostBySlug(slug: string): Promise<PostData | null> {
...
// 3) MDX 변환
const source = await serialize(content, {
mdxOptions: {
remarkPlugins: [remarkGfm],
rehypePlugins: [],
format: 'mdx',
},
});
...
}
페이지에서 MDX 렌더링
import components from '@/components';
import { Box, Container } from '@mui/material';
import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote';
import React from 'react';
import { PostData } from '@/libraries/PostManager';
const ArticleContainer = ({ post }: { post: PostData }) => {
const source = post.source as MDXRemoteSerializeResult;
return (
<Container maxWidth='xl'>
<Box py={4}>
<MDXRemote {...source} components={components} />
</Box>
</Container>
);
};
export default ArticleContainer;
의존성 설치
npm install @mui/material @emotion/react @emotion/styled
테마 생성 및 적용
// theme.ts
export default responsiveFontSizes(
createTheme({
palette: {
primary: {
light: brand[200],
main: brand[400],
dark: brand[700],
contrastText: brand[50],
},
},
typography: {
fontFamily: robotoFont.style.fontFamily,
},
shadows: customShadows,
components: {
MuiLink: {
styleOverrides: {
root: {
textDecoration: 'none', // 기본적으로 밑줄 제거
color: 'palette.link.main', // 테마 링크 색상 적용
'&:hover': {
color: 'palette.link.hover', // 호버 시 색상 변경
textDecoration: 'underline', // 호버 시 밑줄 추가
},
'&:visited': {
color: 'palette.link.visited', // 방문한 링크 색상
},
},
},
},
},
colorSchemes: {
light: true,
dark: true,
},
cssVariables: {
colorSchemeSelector: 'class',
},
}),
);
layout.tsx에서 ThemeProvider 적용
const RootLayout = async ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
const gaId = process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID as string;
return (
<html lang='en' suppressHydrationWarning>
<body>
<InitColorSchemeScript attribute='class' />
<AppRouterCacheProvider>
<ThemeProvider theme={theme} defaultMode={'system'}>
<CssBaseline enableColorScheme />
{children}
</ThemeProvider>
</AppRouterCacheProvider>
</body>
<GoogleAnalytics gaId={gaId} />
</html>
);
};
빌드 시간:
유연한 라우팅:
MDX 관리:
스타일링, 디자인:
생태계, 커뮤니티:
이번 마이그레이션 과정은, 기존에 안정적으로 사용하던 Gatsby 블로그에서 Next.js로의 전환이 과연 큰 이점을 줄 수 있을지 의구심을 갖고 시작했지만, 결과적으로 SSR/ISR, MDX 확장성, MUI 생태계라는 세 마리 토끼를 모두 잡는 성공적인 선택이 되었습니다.
앞으로도 프로젝트 환경과 요구사항에 맞춰 최적의 스택을 탐색하고 적용해보는 과정을 즐겨보시길 바랍니다. 혹시 마이그레이션 과정에 궁금한 점이나 피드백이 있다면 언제든지 이슈로 남겨주세요!
감사합니다.
Next.js 기반 정적 블로그를 Astro + Tailwind로 이주하면서 얻은 것들(속도, 단순함, 디자인 시스템).
Phaser 3의 Scene 중심 Player 코드를 Phaser 4 ECS 스타일로 옮기는 과정을 실전 예시로 정리했습니다. 이동, 점프, 공격 로직을 단계별로 변환해봅니다.
Phaser 3 프로젝트를 Phaser 4로 옮길 때 놓치기 쉬운 포인트를 체크리스트로 정리했습니다. 사전 점검부터 코드 구조, 렌더링, 배포 검증까지 한 번에 확인할 수 있습니다.
Phaser 4의 핵심 변경사항을 Phaser 3와 비교하여 인디게임 개발자 관점에서 정리합니다. 성능, 구조, 렌더링 변화까지 한 번에 이해할 수 있습니다.