Frontend

Next.js MUI로 헤드라인&카테고리 탭 구현

지미닝 2024. 7. 2. 12:53

갑작스런 프론트 게시물😓


 죄송합니다 죄송합니다. 경단팀 프론트엔드 인력 부족 이슈로, 백엔드 중 한명과 팀장을 맡고 있지만, 디자인과 프론트를 겸하게 되었습니다!! 살려주시라요. 그렇지만 프론트엔드의 무게를 덜기 위해서 적어도 우리 다섯명이 팀을 이뤄서 프로젝트 하는 동안은 열심히 Next.js, TypeScript 공부를 하겠다!! 물론 Java Spring도 열심히 할 것이지만 우리 서연이와 경단을 위해서 열심히 해보게따.

 

 근데 뭐 React 했었으니깐 괜찮지 않을까... 라는 생각은 오늘 PR 두개 올리고 마음이 바뀌었다.

 

일단 나는 Next.js든 타입스크립트든 뭐가뭔지 모르니 한 번만 정리하고 가겠다.

 

 

타입스크립트 (TypeScript)


 타입 스크립트는 마이크로 소프트웨어에서 개발한 오픈 소스 프로그래밍 언어다. 자바크립트의 상위 집합이라고 생각하면 된다. 자바스크립트에 타입 시스템을 추가하여 코드의 가독성과 안정성을 높이는 데 중점을 두고 있는 언어다.

 

특징

 

  1. 정적 타입 검사: 컴파일 타임에 타입 오류를 검출하여 런타임 오류를 줄인다.
  2. 향상된 코드 편집기 지원: 타입 정보를 기반으로 코드 자동 완성, 리팩토링, 내비게이션 등이 향상된다
  3. 객체 지향 프로그래밍: 인터페이스, 제네릭, 네임스페이스 등 자바스크립트에서 부족했던 객체 지향 프로그래밍 기능을 지원한다.
  4. ES6+ 기능 지원: 최신 자바스크립트 표준을 지원하며, ES6 이상의 기능도 타입스크립트 문법으로 사용할 수 있다.
  5. 점진적 채택: 기존 자바스크립트 프로젝트에 점진적으로 타입스크립트를 도입할 수 있다.

 

Next.js


 Next.js는 Vercel에서 개발한 오픈소스 React 프레임워크로, 서버 사이드 렌더링과 정적 사이트 생성을 지원한다. React기반 어플리케이션의 성능과 SEO(검색엔진 최적화)를 개선하는데 중점을 둔다.

 

특징

  1. 서버 사이드 렌더링 (SSR): 초기 페이지 로딩 시간을 줄이고 SEO를 개선한다.
  2. 정적 사이트 생성 (SSG): 빌드 시 HTML을 생성하여 빠른 페이지 로딩을 제공한다.
  3. 자동 코드 분할: 각 페이지마다 필요한 코드만 로드하여 초기 로딩 속도를 개선한다.
  4. API 라우팅: 간단한 파일 기반 라우팅을 제공하며, API 엔드포인트를 쉽게 생성할 수 있다.
  5. CSS 및 Sass 지원: 스타일링을 쉽게 적용할 수 있도록 CSS 및 Sass를 기본적으로 지원한다.
  6. TypeScript 지원: TypeScript를 기본적으로 지원하여 타입 안정성을 높일 수 있다.
  7. 환경설정 최소화: 복잡한 설정 없이도 바로 프로젝트를 시작할 수 있다.

 그러나, 서버가 느릴 경우 웹 페이지가 기하급수적으로 느려지고, 서버 부하가 CSR보다 높을 수 밖에 없다. 

 

 리액트를 사용했다면 Next.js도 그렇게 어렵지 않다고 한다. 왜냐하면 기본 철학이 거의 비슷한데, '설정보다 관습'이라는 취지로 만들었기 때문에 Next.js의 특정 기능을 사용하고자 한다면 복잡한 설정 없이도 쉽게 찾을 수 있다고 한다.

 

 

Next.js와 TypeScript의 결합

Next.js 프로젝트에서 TypeScript를 사용하면 두 도구의 장점을 모두 활용할 수 있다. Next.js는 TypeScript 설정을 간단하게 할 수 있도록 도와주며, 타입 안정성과 함께 서버 사이드 렌더링 및 정적 사이트 생성을 쉽게 구현할 수 있다.

 

 

MUI


 MUI(Material-UI)는 React 기반의 사용자 인터페이스(UI) 라이브러리로, 구글의 머티리얼 디자인(Material Design) 원칙을 따르는 컴포넌트들을 제공한다. MUI를 사용하면 React 애플리케이션에서 일관된 디자인과 사용자 경험을 쉽게 구현할 수 있다.

 

특징

 

  • 머티리얼 디자인 구현: 구글의 머티리얼 디자인 가이드라인을 준수하여, 현대적이고 일관된 디자인을 제공한다.
  • 컴포넌트 기반: 다양한 UI 컴포넌트(버튼, 카드, 다이얼로그, 테이블 등)를 제공하여, 복잡한 UI를 쉽게 구성할 수 있다.
  • 테마 커스터마이징: 색상, 타이포그래피, 간격 등을 포함한 테마 설정을 쉽게 커스터마이징할 수 있다.
  • 반응형 디자인: 다양한 화면 크기에 대응하는 반응형 디자인을 지원한다.
  • 접근성: 접근성(A11Y)을 고려하여 개발되어, 모든 사용자에게 더 나은 경험을 제공한다.
  • 강력한 스타일링 솔루션: styled-components와 emotion을 포함한 다양한 스타일링 솔루션을 지원한다.

 

MUI를 사용하면 React 애플리케이션에서 일관된 디자인을 유지하면서도, 개발 속도를 크게 높일 수 있습니다. 다양한 컴포넌트와 테마 커스터마이징 기능을 통해, 디자인과 기능이 조화된 UI를 손쉽게 구축할 수 있다.

 

특히 놀라웠던 부분은, Figma에서 실제 MUI에서 제공하는 UI를 활용할 수 있다는 점이다.

 

개신기!!

 

 그리고 공식문서에서 매우 많은 정보를 제공해줘서 쉽게 사용할 수 있었다. 설치가이드, 사용법, 테마설정, 디자인 리로스, 템플릿 및 예제 프로젝트를 제공해주고 있어서 매우 편하게 사용해볼 수 있었다!!!

https://mui.com/material-ui/getting-started/

 

Overview - Material UI

Material UI is an open-source React component library that implements Google's Material Design. It's comprehensive and can be used in production out of the box.

mui.com

 

 

MUI를 활용해 탭과 헤드라인 구현해보기


 백문이 불여일타!!우리 프로젝트에 내가 해볼만한 간단한 부분들을 구현해보았다!!! 서연이가 해보라고 한 부분 중에 일단 제일 만만한 것들을 해봤다!

 

카테고리 탭 생성해보기!

 

 

우리 프로젝트에 카테고리 탭이 있다! 이 탭을 생성해보았다. 결과물은 아래와 같다!! Next 기본 테마가 검정색이라 바탕이 검정색인점 ))

import * as React from 'react';
import Tabs from '@mui/material/Tabs';
import Tab from '@mui/material/Tab';
import Box from '@mui/material/Box';
import colors from '../../constants/color';

const tabData = [
  { value: 'economy_business', label: '경제 및 기업', content: '경제 및 기업 관련 내용' },
  { value: 'politics_society', label: '정치 및 사회', content: '정치 및 사회 관련 내용' },
  { value: 'tech_culture', label: '기술 및 문화', content: '기술 및 문화 관련 내용' },
  { value: 'sports_leisure', label: '스포츠 및 여가', content: '스포츠 및 여가 관련 내용' },
  { value: 'opinion_analysis', label: '오피니언 및 분석', content: '오피니언 및 분석 관련 내용' },
];

export default function ColorTabs() {
  const [value, setValue] = React.useState(tabData[0].value);

  const handleChange = (event: React.SyntheticEvent, newValue: string) => {
    setValue(newValue);
  };

  const selectedTab = tabData.find(tab => tab.value === value);

  return (
    <Box sx={{ width: '100%' }}>
      <Tabs
        value={value}
        onChange={handleChange}
        aria-label="primary tabs example"
        sx={{
          '& .MuiTabs-indicator': {
            backgroundColor: colors.brown_light,
          },
          '& .MuiTab-root': {
            color: colors.gray_light,
            '&.Mui-selected': {
              color: colors.brown_light,
            },
          },
        }}
      >
        {tabData.map((tab) => (
          <Tab key={tab.value} value={tab.value} label={tab.label} />
        ))}
      </Tabs>
      <Box sx={{ padding: 2 }}>
        {selectedTab && selectedTab.content}
      </Box>
    </Box>
  );
}

 

 서연이가 일단 카테고리를 하드코딩 하지 말고, 목 데이터를 두고 반복문을 활용하여 구현해보라고 했다! 그래서 목 데이터를 두고, 반복문(map)을 활용해서 카테고리를 집어넣었다. 또한 서연이가 색상을 커스텀 코드(?)로 정의해둬서 갖다 쓰면 되었다!!! MUI에서 Tabs를 활용해서 태그 <Tabs>을 가져오면 바로 탭이 생겨나는게 신기했다!!!! sx 가 prop을 사용하여 디자인 관련 스타일을 적용하는 것이라고 한다!! 

import React from 'react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';

function App() {
  return (
    <Box sx={{ bgcolor: 'primary.main', p: 2 }}>
      <Button sx={{ color: 'white', bgcolor: 'secondary.main', p: 1 }}>
        Styled Button
      </Button>
    </Box>
  );
}

export default App;

 

위와 같이 Box와 Button 컴포넌트에 sx prop을 사용하여 배경색, 패딩 등을 정하고 있는 것을 볼 수 있다!! 이 방법은 일반적인 방법이라고 한다. 그런데 프로젝트 규모나 요구사항에 따라서 CSS, CSS-in-JS를 활용한다고 한다.

 

 내가 작성한 저 카테고리 탭 코드에서 궁금한 점이 있다!!

GPT의 답변..

 

  • 목 데이터를 코드에 넣는 방식: 현재처럼 데이터를 tabData 배열로 정의하고, 이를 컴포넌트 내에서 사용하는 방식은 매우 일반적입니다. 데이터를 컴포넌트 파일 내에 직접 넣을 수도 있고, 별도의 파일로 분리하여 불러올 수도 있습니다.
  • 하나의 tsx 파일에 하나의 컴포넌트 생성: 보통 하나의 tsx 파일에는 하나의 React 컴포넌트를 정의하는 것이 좋습니다. 이는 코드의 가독성을 높이고 유지보수를 용이하게 합니다.
  • 패키지 구조: 일반적으로 컴포넌트는 components 폴더에, 페이지는 pages 폴더에 두는 것이 좋습니다.
  • 컴포넌트 테스트 방법: 페이지에 추가하지 않고 컴포넌트를 테스트하려면, Storybook을 사용할 수 있습니다. Storybook은 UI 컴포넌트를 독립적으로 개발하고 테스트할 수 있는 도구입니다.

 

기사의 제목(헤드라인)을 표시하는 부분 생성

 다음으로 아래 부분을 생성해봤다! 이미지 위에 헤드라인 부분!!

결과는 아래와 같다!!

 난 뭔가 갖다쓰는 것에 재주가 있는 것 같다. 이번에는 MUI의 Chip을 갖다썼다.

 저 밑에 경제, 정치 Chip은 다른 페이지에도 주로 쓰니깐 별도의 tsx파일로 정의했다. 어라 근데 방금 봤는데 커스텀 색상을 안가져왔네!!! 좀이따 수정하도록 하겠다!

import * as React from 'react';
import Chip from '@mui/material/Chip';

const TagChip = ({ label }: { label: string }) => {
  return (
    <Chip label={label}
          sx={{
            color: '#000000',
            display: 'flex',
            alignItems: 'center',
            backgroundColor: '#D8D1C5',
          }}
    />
  );
};

export default TagChip;

 

 그리고 해당 칩을 가져와 해드라인 tsx파일을 정의해주었다.

import * as React from 'react';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
import TagChip from './TagChip';

interface HeadlineProps {
  title: string;
  uploadDate: string;
  viewCount: number;
  source: string;
  categories: string[];
}

const Headline: React.FC<HeadlineProps> = ({ title, uploadDate, viewCount, source, categories }) => {
  return (
    <Box>
      <Typography variant="h1" sx={{ fontSize: '2rem', fontWeight: 'bold', marginBottom: '1rem' }}>
        {title}
      </Typography>
      <Box sx={{ display: 'flex', alignItems: 'center', marginBottom: '1rem' }}>
        <Typography variant="body1" sx={{ marginRight: '0.5rem' }}>
          {uploadDate} | 조회 {viewCount}회 | {source}
        </Typography>
        <Box sx={{ display: 'flex', gap: '0.5rem' }}>
          {categories.map((category) => (
            <TagChip key={category} label={category} />
          ))}
        </Box>
      </Box>
    </Box>
  );
};

export default Headline;

 

나중에 서연에게 리뷰를 받으면 게시물을 한 번 더 수정해보겠다!!! 일단 여기까지~~

 

참고 문서

https://subtlething.tistory.com/115

 

[React] Next.js란 무엇이고 왜 사용하는가

Overview Next.js는 리액트를 위해 만든 오픈소스 자바스크립트 웹 프레임워크로, 리액트에는 없는 **서버 사이드 렌더링server-side rendering(SSR), 정적 사이트 생성static site generation(SSG), 증분 정적 재생

subtlething.tistory.com

 

'Frontend' 카테고리의 다른 글

Junction Asia 2023  (0) 2024.06.05