개인적으로 깃허브 호스팅을 애용하는 편이다. 그 이유로 별도의 인프라 구축없이 깃허브 소스관리 시스템에서 정적인 페이지를 무료로 간단하게 배포할 수 있어서 그렇다.
매번 서버를 구축하고 관리하는건 귀찮은 일이니까
이번에 개인용 아카이브 사이트를 개발할 일이 있어서 간단하게 개발을 하였는데 기술스택으로는 프레임워크인 Next.js13버전을 처음으로 적용해서 변경점들을 확인해보았고 CSS in JS로는 styled-components를 상태관리로는 recoil, react-query를 ajax요청은 axios, 테스트 및 문서화는 storybook의 도움을 받았다. CI/CD는 간단하게 github action으로 호스팅은 gh-page를 사용했다.
기본적인 사이트 구조는 벡엔드 - 프론트의 기본적인 구조로 state와 UI를 물리적으로 분리했다. 벡엔드의 경우 현재 방문자가 데이터 조작을 하는 케이스가 없어서 간단한 json-server 형식으로 데이터만 구조적으로 정리한 정도 수준이다.
기획부터 디자인까지 생각날때마다 혼자서 조금씩 처리했는데 디자인 모티브는 게임에서 따왔다. 내가 즐겨하는 게임들의 게임사인 호요버스의 아카이브 사이트인 호요랩에서 기본 구성을 따오고 개인적으로 최근에 꽂혀 있던 언디셈버라는 게임에서 느낀 다크(?) 판타지 장르의 핵앤슬레시 감성을 나름 표현해내기 위해서 노력했고 끝나고보니 그럭저럭 어두컴컴하면 여러 몬스터가 튀어나올 듯한 갬성을 어느정도는 살리지 않았나 싶다.
적어도 내눈에는.. 사이트 자체는 기본적인 반응형웹으로 일반적인 pc환경과 일반적인 모바일 환경을 지원 할 수 있도록 설계했다.
Next 13의 APP Dir 구조를 사용해보면서 느낀건 해당 구조가 개인적으로 기존에 설계해서 쓰던 구조에서 크게 다르지 않다는 점 정도 인거같다. App을 Pages레이어로 삼고 거기 들어갈 기능들은 따로 Features로 프레젠테이션 컴포넌트는 컴포넌트로 구분하고 State Model은 Store에서 구조를 짜고 해당 상태를 use 하는 부분은 Custom hook으로 Hooks 레이어에서 짜준다. 벡엔드의 API를 호출하는 로직은 Api에서 관리하고 해당 부분은 Hooks에서 hook내부에서 처리한다. 도메인에 상관없이 여기저기서 보편적으로 쓰이는 컴포넌트는 Provider로 유틸함수는 Utils로 정리하는 구조 필요에 따라서 레이어를 추가하는 정도의 차이가 있을뿐 어느정도 정석적으로 굳어진 구조라고 봐도 될거같다.
Next13에서는 use client라는 지시어로 SSR과 CSR 컴포넌트를 구분하는데 브라우저의 API를 호출하거나 Context를 사용하는 코드들의 경우 use client가 거의 필수어가 되었다. 그래서인지 recoil 같은 상태관리는 당연하고 기존에 브라우저 환경을 전제로 쓰는 styled-components나 emotion 같은 패키지들은 전부 ssr 컴포넌트에서 제대로 지원이 안되는데 그냥 따로 SSR용 CSS in JS 패키지를 사용하거나 아래처럼 코드를 추가해줘야 레이아웃 시프트가 최소화 된다.
'use client';
import React, { useState } from 'react';
import { useServerInsertedHTML } from 'next/navigation';
import {
ServerStyleSheet,
StyleSheetManager,
createGlobalStyle,
} from 'styled-components';
export default function StyledComponentsRegistry({
children,
}: {
children: React.ReactNode;
}) {
// Only create stylesheet once with lazy initial state
// x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet());
useServerInsertedHTML(() => {
const styles = styledComponentsStyleSheet.getStyleElement();
styledComponentsStyleSheet.instance.clearTag();
return <>{styles}</>;
});
if (typeof window !== 'undefined') return <>{children}</>;
return (
<StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
{children}
</StyleSheetManager>
);
}
export const GlobalCSS = createGlobalStyle`
:root {
--color-background-space: #12172f;
--color-background-card: #1e202c;
--color-point: #8a40b8;
--color-rare: #c4c118;
--color-unique: #9e2e06;
--color-legend: #6e0303;
}
body {
background: var(--color-background-space);
font-family: 'Noto Sans', sans-serif;
font-family: 'Noto Sans KR', sans-serif;
color: #fff;
&::-webkit-scrollbar {
width: 8px;
background: none;
}
&::-webkit-scrollbar-thumb {
background: var(--color-point);
border-radius: 12px;
}
&::-webkit-scrollbar-track {
background: var(--color-background-card);
border-radius: 12px;
}
}
`;
이부분은 그렇게 어려운건 아니니 금방 문제가 해결될거 같긴 하지만 개인적으로 SSR과 CSR 호환성에 대해서 한번쯤 다시 생각해보게 만드는 경험이였다. 그외는 개발하는 입장에서는 React를 사용하는 것과 별차이가 없어서 좋았던거같다 개인적으로 귀찮아서 Next js에서 제공하는 API들을 wrap을 안하고 사용했는데 해당 부분까지 따로 컴포넌트를 wrap한다면 프레임워크 종속성이 거의 없는 수준에 가까워질거 같다.
import React, { useEffect } from 'react';
import styled from 'styled-components';
import Image from 'next/image';
import Link from 'next/link';
import Card from '../../components/atoms/Card';
import WCarousel from '../../components/organisms/WCarousel';
import useSelectList from '../../hooks/select/useSelectList';
import NoImage from '../../assets/images/noimg.png';
여기서 Image나 Link같은 컴포넌트를 바로 import하지 않고 wrap해서 처리하면 그냥 일반 React코드와 차이점을 거의 못느끼지 않을까? 기존에 이질감 들었던 부분들이 API로 녹아들고 조금 더 React에 가까워진거 같다. + 편의성은 추가되고
CI/CD도 간단히 아래와 같이 처리했다. 테스트의 경우 스토리북만 사용해서 따로 안넣었다.
# Simple workflow for deploying static content to GitHub Pages
name: Deploy static content to Pages
on:
# Runs on pushes targeting the default branch
push:
branches: ["main"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: write
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
install-and-build:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install and Build
uses: actions/setup-node@v3.8.1
- run: npm install
- run: npm run build
- run: npm run export
env:
CI: true
DEPLORY_TARGET: gh-pages
- run: touch out/.nojekyll
- name: Deploy GitHub Pages site
uses: JamesIves/github-pages-deploy-action@v4
with:
folder: out
branch: gh-pages
clean: true
일단 초기버전은 구축완료 되었으니 앞으로 지속적으로 필요한 부분들을 추가하면서 관리하면 될듯.
새삼 느끼지만 개발과정에서 디자인에 쓸데없이 소모되는 시간을 얼른 디자인시스템으로 줄일 수 있길 바란다.
그러나, 디자인 시스템 개발도 디자인이라 그런가 힘들구만..
https://yoonjonglyu.github.io/
https://github.com/yoonjonglyu/yoonjonglyu.github.io
https://github.com/yoonjonglyu/archivedata
https://64ee73e8852cf4ea07ac0a39-bibuwbzxbx.chromatic.com/
'프로젝트' 카테고리의 다른 글
[Memo]v1.0.1 개발 후기 (1) | 2024.08.21 |
---|---|
[메모장] Memo프로토타입 릴리즈 -2- (0) | 2023.03.14 |
[메모장] Memo 프로젝트 -1- (0) | 2023.03.05 |
유틸과 헬퍼함수를 정리해보기. (0) | 2022.12.21 |
오픈소스 디자인 시스템 만들기 -4- (0) | 2022.11.29 |