코드스테이츠 동기 분들 중 마음이 맞는 분들과 모여
커리큘럼 프로젝트가 아닌 선행학습으로 수행해보기로 했다.
지금까지 회의 두번을 하며 대략적으로 front/back 폴더 분리와
git 연동 및 jira로 일정관리를 하기로 정한뒤,
간단하게 그림판으로 프로젝트 구조를 그려 초안을 작성하기로 했다.
(메인)
(게시판목록)
(글 상세 페이지)
우선 쭉 봤을때 프론트엔드가 관리하는 폴더내에 분리를 시켰다.
(gradle react 폴더 구조)
로 폴더를 크게 나누었다.
아마 많은 페이지가 구성되진 않아 pages 폴더 내부에
또다시 큰 주제로 폴더를 나눌 필요는 없어 보이고,
현재 반복적으로 사용될 것으로 예상되는 컴포넌트는
1. 네비게이션 헤더
2. 인기글 카드
3. 게시판 목록
으로 보인다.
추후 인기글 카드 및 게시판 목록을 map으로 뿌려주기 위해
dummy폴더를 생성했고,
styles폴더를 만들어 css폴더를 관리하는 것 처럼 만들 예정이다.
그후, App파일을 열어 코드정리를 수행했다.
Router로 파일을 따로 만들어 보통 길어지는 route코드들을 따로 관리하기로 했고,
GlobalStyle을 만들어 reset css 처럼 공통적으로 들어가야 하는 css를 따로 정리했다.
그 후, 레이아웃 구성을 보면 네비게이션 헤더를 제외한 콘텐츠는 양측에 레터박스를 생성 후 가운데로 정렬해야함을 알았다.
모든 페이지에 보이는 Navigation을 상단에 고정하고,
그 아래 컨텐츠에 BaseScreen을 만들어 max-width를 정해준다.
그 후 간단하게 route의 pathname에 따라 메뉴바의 css가 바뀌도록
prop을 먹여줬다.
import styled from "styled-components";
import { useNavigate, useLocation } from "react-router-dom";
const NaviHeader = () => {
const navigate = useNavigate();
const { pathname } = useLocation();
return (
<>
<Container>
<Logo onClick={() => navigate("/")}>로고</Logo>
<div>
<MenuList>
<MenuListContent
isPathMatch={pathname === "/free-board" ? true : false}
>
자유게시판
</MenuListContent>
<MenuListContent
isPathMatch={pathname === "/study-board" ? true : false}
onClick={() => navigate("/study-board")}
>
스터디구인
</MenuListContent>
<MenuListContent
isPathMatch={pathname === "/login" ? true : false}
onClick={() => navigate("/login")}
>
로그인
</MenuListContent>
</MenuList>
</div>
</Container>
</>
);
};
const Container = styled.div`
width: 100%;
height: 5rem;
border: 0.1rem solid black;
display: flex;
justify-content: space-between;
align-items: center;
`;
const Logo = styled.button`
width: 3rem;
height: 2rem;
border: 0.1rem solid black;
margin-left: 1rem;
background: url("/image/logo.jpg") no-repeat 50% 50%;
z-index: 3;
`;
const MenuList = styled.ul`
display: flex;
`;
const MenuListContent = styled.li<{ isPathMatch: boolean }>`
margin-right: 1rem;
color: ${(prop) => (prop.isPathMatch ? "blue" : "black")};
`;
export default NaviHeader;
성공적으로 잘 작동한다.
다음으로는 게시판에서 어떤 데이터를 가져올지 예상해보고
더미데이터를 작성했다.
게시판에서 index,제목,글,작성날짜,작성자 정도를 가져와야하고
추가적으로 댓글을 어떻게 종속되서 올까 하고 추가적으로 작성했다.
export interface IDuBoardList {
id: number;
subject: string;
content: string;
datetime: string;
favor: number;
comment: IDuComment[];
}
export interface IDuComment {
id: number;
content: {
id: number;
content: string;
}[];
}
const DuComment = [
{
id: 1,
content: [
{
id: 1,
content: "정말 좋은 이야기네요.",
},
{
id: 2,
content: "오늘도 좋은 하루 보내시길",
},
],
},
{
id: 2,
content: [
{
id: 1,
content: "꽃이 정말 예뻐요",
},
{
id: 2,
content: "나랏말싸미",
},
],
},
];
export const DuBoardList = [
{
id: 1,
subject: "오늘도 즐겁게",
content: "즐겁게 하루를 시작해보자",
datetime: "2022-05-05",
favor: 30,
comment: DuComment,
author: "홍길동",
},
{
id: 2,
subject: "오늘도 우울하게",
content: "우울하게 하루를 시작해보자",
datetime: "2022-05-04",
favor: 30,
comment: DuComment,
author: "이순신",
},
{
id: 3,
subject: "오늘도 우울하게 재밌게",
content: "우울하게 하루를 시작시작해보자",
datetime: "2022-05-02",
favor: 30,
comment: DuComment,
author: "세종대왕",
},
{
id: 4,
subject: "오늘도 재미지게하게",
content: "우울하게 하루를 재미시작해보자",
datetime: "2022-05-01",
favor: 30,
comment: DuComment,
author: "최무선",
},
];
이런식으로 타입 지정, 들어갈 리터럴등을 넣고
대략 스타일 틀을 만들어 map으로 뿌려준다.
<FavorContainer>
{DuBoardList.slice(0, 4).map((item, index) => (
<FavorCard
onClick={() => navigate(`:${item.id}`)}
key={index}
subject={item.subject}
content={item.content}
/>
))}
</FavorContainer>
이제 FavorCard 컴포넌트를 작성한 파일로 가서
전달한 prop의 스타일을 알려주고, 어디 위치에 사용할지 적는다.
interface Prop {
subject: string;
content: string;
onClick: () => void;
}
const FavorCard = ({ subject, content }: Prop) => {
return (
<>
<Card>
<Subject>{subject}</Subject>
<Content>{content}</Content>
</Card>
</>
);
};
export default FavorCard;
위와 같은 방법으로 대략 게시판 리스트 컴포넌트 생성 & prop전달을 마치고 아주 기초적인 틀이 완성되었다.