React - Harry Potter 기숙사 소개 페이지 제작 (Day 1)

조민수·2024년 1월 29일
0

개발

목록 보기
1/9
post-thumbnail

프로젝트 주제 선정

React TS 기반 짤막한 프로젝트를 하고 싶었다.
쓸만한 API가 없나 찾아보다가
https://wizard-world-api.herokuapp.com/swagger/index.html 에서 해리포터 관련된 다양한 API를 get형태로 제공하는 것을 찾았다.

그 중에서

를 사용하기로 했고, 프로젝트 사이즈를 키워보고 한다면 Spells나 Wizards 까지 써봐도 괜찮을 듯 싶다.


개발 언어 및 Framework & Libraries

  • React
  • TypeScript
  • Styled-components
  • Axios
  • React Query

까지는 사실상 필수였고
추가적으로 이번 프로젝트를 통해 가져갈 스킬은

  • AWS Elastic Beanstalk을 통한 정적 배포
  • React Spring # Animation 적용
  • styled components의 theme 적용
  • @babel Webpack

정도가 되겠다.


폴더 구조

  • 폴더 구조 구성에 있어서 theme를 어떻게 가져갈 지 추후에 고민해봐야 할 것 같다.
  • api 호출
  • 페이지 내의 부분으로 쓰이는 Components
  • type, interface를 모아두는 model
  • 전환 시의 페이지를 담당하는 pages

로 구성하였다.
( 어떤 방식이 현업에서 쓰이고, 가장 효율적인지는 배워가며 적용해봐야 알 듯... )


api > getData.ts

House의 전체적인 정보와
House의 이름만 필요한 경우가 있어서 이를 구분해 함수를 만들었다.

  • 현재는 getHouse를 쓰지 않아서, 추후에도 쓰지 않는다면 과감히 삭제...
import axios from "axios";
import { House } from "../model/house";

const data = axios.create({
  baseURL: "https://wizard-world-api.herokuapp.com",
});

export const getHouse = async () => {
  const response = await data.get("/Houses");
  return response.data;
};

export const getHouseName = async () => {
  const response = await data.get("/Houses");
  return response.data.map((item: House) => item.name);
};

// id 통해서 해당 기숙사 정보 가져오기

export const getHouseById = async (id: string) => {
  const response = await data.get(`/Houses/${id}`);
  return response.data;
};

model > house.ts

getHouse를 통해 받아오는 response.data의 타입이
House[] 형식으로 올 수 있게끔 만들어놓았다.

  • 하지만 역시 아직까지 쓰진 않았다.
  • 어차피 각 기숙사 별 정보를 받아올 때 써야하니 미리 만들어놨다고 생각하면 좋을듯.
export interface House {
  animal: string;
  commonRoom: string;
  element: string;
  founder: string;
  ghost: string;
  heads: Head[];
  houseColours: string;
  id: string;
  name: string;
  traits: Trait[];
}

export type Head = {
  id: string;
  firstName: string;
  lastName: string;
};

export type Trait = {
  id: string;
  name: string;
};

pages > MainPage.tsx

  • Header - Body - Footer 의 기본 웹 Layout으로 구성했다.
  • 해리포터 기숙사의 이름이나 개수가 바뀔 일은 절대 없어서 하드코딩을 해도 되지만, 그러면 이 프로젝트에서 API 데이터를 받아와서 동적으로 만들겠다는게 의미가 없어져서 최대한 짧고 가독성이 높게 작성했다.

import React, { useEffect, useState } from "react";
import { getHouseName } from "../api/getData";
import { useQuery } from "react-query";
import styled from "styled-components";
import { ImgHandler } from "../Components/ImgHandler";

export const MainPage: React.FC = () => {
  const [nameArray, setNameArray] = useState<string[]>([]);

  const { data, isLoading, error } = useQuery<string[]>(["house"], () =>
    getHouseName()
  );

  useEffect(() => {
    if (data) {
      setNameArray(data);
    }
  }, [data]);

  if (isLoading) return <div>now in Loading...</div>;
  if (error) return <div>ERROR OCCURED</div>;

  return (
    <StyledDiv>
      <h2>Choose Your House</h2>
      <HouseGrid>
        {nameArray.map((name) => {
          return (
            <div key={name}>
              <ImgHandler name={name} height="130px" />
              <p>{name}</p>
            </div>
          );
        })}
      </HouseGrid>
    </StyledDiv>
  );
};

const StyledDiv = styled.div`
  display: flex;
  flex-flow: column nowrap;
  gap: 5vh;
  padding: 10px;
  align-items: center;
  justify-content: center;
  position: relative;
  height: 70vh;

  & > h2 {
    font-family: "SOGANGUNIVERSITYTTF";
    font-weight: 500;
    color: #acacac;
  }
`;

const HouseGrid = styled.div`
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  column-gap: 2vw;
  width: 95%;

  & > div {
    width: 100%;
    border: 1px solid #787878;
    border-radius: 15px;
    display: flex;
    flex-flow: column nowrap;
    justify-content: center;
    align-items: center;
    gap: 3vh;
    cursor: pointer;
    padding: 3vh 0;

    & > p {
      font-family: "SOGANGUNIVERSITYTTF";
      font-size: 1.1rem;
      margin: 0 !important;
    }
  }
`;

Components는 추후에 Components들로만 따로 작성할 예정

profile
사람을 좋아하는 Front-End 개발자

0개의 댓글