[Portfolio] 기획부터 배포까지

Miog Yang·2022년 10월 21일
0

Project

목록 보기
3/7
post-thumbnail

Frontend Portfolio

피그마로 작업한 UI

React기반 포트폴리오 사이트입니다. 매거진스타일을 적용하였고 이미지 슬라이드나 프로젝트는 추가될 예정임으로 하나의 컴포넌트내에 json형태의 데이터를 만들고 fetch함수와 map을 이용하여 작업하였습니다.

프로젝트 기획

  • 이미지와 프로젝트 데이터는 json데이터로 만들고 fetch로 호출하여 반환.
  • Tech Stack, Design Skill, Workexperience는 수시로 수정할 필요가 없으므로 하드코딩.
  • 프로젝트 부분은 계속 업데이트 예정으로 컴포넌트화 하여 카드형으로 구성
  • 모달을 이용하여 프로젝트 소개를 구현

언어

언어 : React js, javascript
Style : sass, styled-component
Library : react-icons, react-slider-swiper, page-flip
Verrsion control Tool : Git

프로젝트 구조

App js : fetch함수를 이용하여 data호출하고 해당 페이지와 컴포넌트에 넘겨준다.
page폴더 : 페이지와 해당 컴포넌트, 데이터를 담은 컴포넌트를 넣었다.




구현한 기능 소개

state를 이용한 카테고리


function About() {
  const [tab, setTab] = useState(0);

  const stackContent = {
    0: <TechStack />,
    1: <Workexperience />,
    2: <DesignSkill />,
    3: <ProjectCard />,
    4: <ToyProjectCard />,
  };

  return (
    <AboutWrap>
      <div className="aboutContainer">
        <h3>About</h3>
        <Category tab={tab} setTab={setTab} />
        <div className="contentContainer">{stackContent[tab]}</div>
      </div>
    </AboutWrap>
  );
}
export default About;
  • 카테고리에 index와 onClick이벤트로 인해 지정되는 index별 콘텐츠의 컴포넌트를 생성한다.
  • 카테고리를 state로 만들고 첫번째 index를 초기값으로 설정한다.
function Category({ tab, setTab }) {
  return (
      <ul>
        <li
          className={`${tab === 0 ? "active" : ""}`}
          onClick={() => {
            setTab(0);
          }}
        >
          Tech <span className="hide">Stack</span>,
        </li>

        <li
          className={`${tab === 1 ? "active" : ""}`}
          onClick={() => {
            setTab(1);
          }}
        >
          Design<span className="hide">Skill</span> ,
        </li>
        <li
          className={`${tab === 2 ? "active" : ""}`}
          onClick={() => {
            setTab(2);
          }}
        >
          Work<span className="hide">experience</span>,
        </li>
        <li
          className={`${tab === 3 ? "active" : ""}`}
          onClick={() => {
            setTab(3);
          }}
        >
          Project,
        </li>
        <li
          className={`${tab === 4 ? "active" : ""}`}
          onClick={() => {
            setTab(4);
          }}
        >
          Toy<span className="hide"> Project</span>,
        </li>
      </ul>
  );
}
export default Category;
  • 해당 컴포넌트가 해당되는 카테고리 onClick이벤트에 state로 생성한 index를 지정해준다.

시현영상

📌 카테고리 리팩토링




이미지 슬라이드

swiper를 이용한 이미지 슬라이드 구현


import "swiper/scss";
import "swiper/scss/pagination";
import "swiper/scss/navigation";
import { Swiper, SwiperSlide } from "swiper/react";
import { Pagination, Navigation, Autoplay } from "swiper";

function Slider() {
  return (
    <Swiper
      spaceBetween={10}
      autoplay={{
        delay: 2500,
        disableOnInteraction: false, //스와이프 후 자동재생
      }} //자동 시간
      loop={true} //무한슬라이드
      height={800}
      pagination={{ type: "fraction" }}
      navigation={true}
      modules={[Autoplay, Pagination, Navigation]} //modules에 기능 넣기
    >
      {ImgSliderData?.map((slideData) => {
        return (
          <SwiperSlide key={slideData.id}>
            <img src={slideData.src} alt="pic" className="sliderImg" />
          </SwiperSlide>
        );
      })}
    </Swiper>
  );
}
export default Slider;

  • swiper 공식문서에 보면 react 사용코드도 친절히 나와있다.
    img태그에 소스를 담기보단 ImgSliderData로 이미지를 데이터화한후 import하여 map()으로 호출하고 반환하였다.
  • 데이터로 따로 관리를 해야 다음에 이미지를 변경하거나 UI변경시 텍스트를 이미지내에 추가하는 작업등 수월하기 때문에 이러한 방식으로 하였다.

시현 영상

📌 Swiper로 이미지 슬라이드 구현하기 (상세편)




props로 카드구현 & Modal에 콘텐츠 props넘겨주기

App js에서 데이터를 fetch로 호출하여 Main컴포넌트로 넘겨주고, 데이터가 구현되는 자리인 About js내에 Project js인 카드에 map()으로 호출하고 반환한다.
어떻게 하나의 데이터를 맞춰서 넣어줄까 고민하다가 고유값이 id를 키값으로 지정후 키값을 조건문으로 사용하였다.

function ToyProjectCard({ projectData }) {
  const [introduce, setIntroduce] = useState(0); // 데이터를 맞출 키값 id
  const [toyPrjModal, setToyPrjModal] = useState(false);

  return (
    <>
      {projectData.map((prjCard) => {
        return (
          <div key={prjCard.id}>
            
                <img
                  onClick={() => {
                    setIntroduce(prjCard.id);
                    setToyPrjModal(true);
                  }}
                  src={prjCard.imgSrc} alt="toyprojectImg" />
              
                  <button
                    onClick={() => {
                      setIntroduce(prjCard.id);
                      setToyPrjModal(true);
                    }}
                  > 더보기 </button>
                
          </div>
        );
      })}
      {toyPrjModal === true ? (
          <ToyPrjDetail
            project={projectData} // 데이터
            setToyPrjModal={setToyPrjModal} // modal 닫기 버튼
            introduce={introduce} // 조건문에 사용할 키값 id
          />
      ) : null}
    </StyledToyCard>
  );
}
export default ToyProjectCard;

  • props로 받은 데이터를 map()으로 연결한다. 데이터의 키값으로 카드와 모달의 데이터를 연결하기위해 state로 지정된 키값과 함께 onClick이벤트로 구현될 modal컴포넌트에 넘겨준다.
function ToyProjectDetail({ project, setToyPrjModal, introduce }) {
  return (
      <div>
        {project.map((projectList) => {
          if (projectList.id !== introduce) return null;
          return (
            <div key={projectList.id}>
              
            // 데이터받아오기
          
              </div>
          );
        })}
      </div>
    </StyledToyPrj>
  );
}
export default ToyProjectDetail;
  • 카드에 구현된 데이터의 id와 콘텐츠의 id가 같을 경우 map()으로 호출하여 반환한다.

시현 영상

📌 WARNING 메세지 발생 & 문제 해결




✏️ 마치며

혼자 기획하고 작업한 사이트인만큼 기능하나하나에 고민을 하였다. swiper는 손쉽게 구현은 되지만 커스터마이징이 어려웠고, 클릭하면 연결된 데이터가 구현되는 기능인 카테고리와 카드형 데이터는 기능은 비슷해보이지만 추후 유지보수에 맞춰 다르게 코딩하였다. 간단하게 생각하면 간단하고 어렵게 생각하면 어려워지는게 개발인듯 하다. 기능을 생각하며 로직을 짜고 기능이 구현될때 뿌듯하다. 기세를 몰아 추후 아트웍을 모아놓은 페이지도 구현해야지!!

profile
주니어 개발사전 & 프론트엔드 도전기

0개의 댓글