포트폴리오 배포 후기

KoEunseo·2023년 2월 7일
1

portfolio

목록 보기
7/12

내 포트폴리오 페이지
https://eunseo-portfolio.vercel.app/

포트폴리오 페이지를 드디어!! 배포했다ㅠㅠ!!
아직 애니메이션도 추가하지 않았고 내용도 다듬지 않았지만...
일단 배포부터 하고 조금씩 고쳐나가자고 생각했다.

느낀점

단순히 next.js를 공부하고 싶어서 쓴건데, 욕심이 과해져서 swr도 쓰고... 하느라고 보름정도 걸렸다.
노션API, Next.js, SWR = 모르는거 + 모르는거 + 모르는거
의 조합이다보니 고생을 많이했다. 거기다 scss도 초면은 아니긴 한데... 두번째 본 느낌... 걍 모른다고 하자 그래.
모르는 scss도 쓰려니까 증말... 휘유

SWR

swr이라도 안썼으면 좀더 빨리 했을 것 같은데, 리액트쿼리를 공부해보니 UI상태랑 서버상태를 분리하는 것이 정말 좋은 방법이라고 생각이 들어서 꼭 써보고싶었다. 왜 swr이었느냐하면... next.js 깃허브에 들어가서 example을 봤는데 react-query에 대한 예시는 없고(있긴 한데 tanstack으로 가는 링크가 게시되어있음) 아래와 같이 SWR을 사용한 예시가 수두룩했기때문이다.

컴포넌트마다 useSWR를 사용했어서 여러번 fetch하는 것 같은 느낌에 찜찜했지만 실제로는 한번만 fetch한것이 맞다. 역시 리덕스든 리액트쿼리든 swr이든 상태관리 툴은 쓰는 것이 이득이다.

Notion API

포트폴리오 특성상 한페이지에 모든 내용이 나오도록 하고 싶었기 때문에 노션 데이터베이스를 페이지별로 두지 않고 about, project, education 등을 다 때려넣었다. 처음엔 데이터 구조가 복잡해서 어렵다고 느껴졌으나 콘솔로 찍어가며 잘 대응할 수 있었다. 아래와 같이 타입스크립트로 타입을 구체적으로 적어준 것도 아주 도움이 되었다. 대신 이미지는 노션에서 따로 다루지 않고 레포지토리에 넣어주었다. 원래는 노션에서 받아서 넣고 싶었는데 어쩐 일인지 undefined가 나와서...

export type NotionDataRow = {
  title: { id: string; title: { text: { content: string } }[] };
  subtitle: {
    id: string;
    rich_text: { plain_text: { content: string | undefined } }[];
  };
  tags: { id: string; multi_select: { name: { content: string } }[] };
  content: {
    id: string;
    rich_text: { text: { content: string | undefined } }[];
  };
  subContent: {
    id: string;
    rich_text: { text: { content: string | undefined } }[];
  };
  url: { id: string; url: string | null };
  period: {
    id: string;
    rich_text: { text: { content: string | undefined } }[];
  };
  team: {
    id: string;
    rich_text: { text: { content: string | undefined } }[];
  };
};

Typescript

잊을만하면 에러가 나타나서 날 괴롭혔다. 대신 도움도 많이 받았다.
특히 서버를 열지 않아도(런타임 전에도)특정 에러를 방지해주는 게 좋았다. 타입스크립트에 빨리 익숙해지고싶다.

scss

mixin & media query

반응형 대응할때 제일 득을 많이 봤다. 나는 항상 데스크탑 기준으로 페이지를 구성하고 나중에 모바일, 태블릿으로 가는 습관 아닌 습관이 있었는데 이번에는 모바일 퍼스트로 꼭 하고싶었다! 그래서 아래와 같이 mixin을 만들고 작업했다. @content라고 해놓고 나중에 @include로 연결해서 쓰면 된다. 클래스네임이 길어진다는 단점이 있었다.

//media query
@mixin for-mobile {
  @media (min-width: 480px) {
    @content;
  }
}
@mixin for-tablet {
  @media (min-width: 600px) {
    @content;
  }
}
@mixin for-desktop {
  @media (min-width: 1024px) {
    @content;
  }
}
//mixin사용법
@include for-desktop {
  margin-left: 20vw;
  margin-right: 5vw;
}

module.scss

모듈로 scss파일을 import해 사용할 수 있다. 나는 common.module.scss파일을 따로 두고 컴포넌트에 따라 컴포넌트명.module.scss파일을 만들어 layouts 폴더에 위치시켰다.
common 파일은 common이라는 별칭으로 import해와서 사용할 때는 common.round_btn 이런식으로 클래스네임을 주었다. 컴포넌트 스타일은 style이라는 별칭으로 import해와 style.education_title 이런식으로 클래스네임을 주었다.
여러개의 클래스네임을 주고싶을때가 아주 귀찮았는데 탬플릿 리터럴 써줘야함. 백틱이랑 ${표현식} 으로 감싸야한다. ${common.stroke_title} ${styles.edu_board_title}
아무래도 클래스네임이 끝도없이 길어진다는 단점이 있다. 그리고 태그마다 클래스네임이 생겨서 엄청... 지저분해보임.(내탓이겠지) 거기다 백틱으로 감써줘서 클래스네임 사이에 엔터라도 치면 중간에 띄어쓰기가 엄청 생김. 대신 이건 배포하면 사라지는 문제라 신경 안써도 된다. 개발할때 편하게 보는게 훨 중요하지.

import common from "@/styles/common/common.module.scss";
import styles from "@/styles/layouts/education.module.scss";

const EducationItem = () => {
  return (
    <section className={styles.edu_board}>
      <div>
        <h3
          className={`${common.stroke_title} 
          ${styles.edu_board_title}`}
        >
          {title}
        </h3>
      </div>
    </section>
  );
};

export default EducationItem;

계층

스타일링하다보면 css파일 구조가 난잡해지기 마련인데 어느정도 방지가 된다. 아래 구조를 보면 어느정도 어떤 요소를 말하는건지 계층구성이 보인다. edu라는 큰 틀에 타이틀과 컨텐츠가 있고,
edu item들을 보드라고 표현했는데 보드에도 각각 타이틀과 서브타이틀, 컨텐츠, 그리고 배지가 있겠거니 파악이 된다.
수정할때나 추가할때도 개발자도구 파고들어가지 않아도 어느정도 감이 와서 좋았다. 대신 기본적으로도 클래스네임 길이가 좀 있고, depth에 따라 클래스네임이 더더 길어질 수 있음.

.edu {
  &_title {
  }
  &_contents {
  }
  //item
  &_board {
    &_title {
    }
    &_subtitle {
    }
    &_content {
      @include for-desktop {
      }
    }
    &_badges {
    }
  }
}

for문 사용

skill.module.scss에서 사용함. skill을 카드뭉치로 표현해서 일반 캐러셀과는 다르게 구현해야했다. 캐러셀은 보통 나란히 두고 overflow:hidden을 주고 한페이지만 보이도록 하면 되는데, 카드뭉치는 겹쳐져있어야하기 때문에; z-index로 앞장과 다음장 요소를 나타내야했다.
아래 예시에 보면 0부터 6까지 반복문을 돌린다. 그리고 0번째 아이템은 z-index가 10-0으로 z-index가 10이다. 1번째는 9, 2번째는 2... 이런식으로 아이템이 순서대로 위치할 수 있게 했다. 그리고 다음 버튼을 누르면 방금 가장 앞에 있던 아이템의 z-index를 1로 줘서 맨 뒤로 보낸다.

.is_carousel_item {
  position: relative;
  @for $i from 0 through 6 {
    &:nth-of-type(#{$i}) {
      z-index: 10 - $i;
    }
  }
}
.is_passed_carousel {
  position: static;
  z-index: 1 !important;
}

그외 (_variables, globals)

글로벌 scss파일을 따로 두고 변수파일도 따로 뒀는데 이건 scss라서 좋다고 할수는 없는 문제고. (다른 css in js 라이브러리에서도 제공) 그래도 컬러를 변수로 두고 사용한건 처음이었는데 편하고 좋았다. 앞으로도 이 방법은 계속 써야겠다 생각함.
scss를 쓰면서 얼마나 props를 넘기고싶었는지 모른다.... styled-components로 돌아가고싶다고 엄청 생각하면서 썼는데 지금 하나하나 나열해보니 또 좋았던 점도 많았구나 싶다.

Next.js

대망의 next.js 차례인데, 음 사실 사용하면서 그렇게 좋다고는 느끼지 못했다. 생각보다 더 새로운 게 많아서 배우느라고 장점을 더디게 느낀 것 같음. pages내에 페이지를 만들면 자동으로 라우팅을 해준다는데 나는 원페이지라 딱히 그 이점을 느낄 수 없었다. _app.js파일를 따로 생성해서 글로벌 설정하는 데 사용하는 것이 좋았던 것 같다. _document.js라는것도 있다는데 파일을 만들기는 했지만 따로 커스텀하지는 않았다. api폴더 내에서 서버 데이터를 같이 핸들링할 수 있어서 좋았다. 그리고 404.js처럼 경로 외 페이지에 대해서도 핸들링해줄 수 있다는 점도 장점이다. import할때 경로도 ../를 남발하지 않고 @를 사용해서 깔끔하게 쓸 수 있는 점도 좋았다. built in css에 대해서는 딱히 뭔가 좋다고 느낀점이 없었다.

  • document.js
    head, body 태그 안에 들어갈 내용들을 커스텀할때 사용(웹 접근성)한다고 함.

추가할것

  1. 애니메이션
  2. 메뉴 경로 추가해야함
  3. Suspense 사용!

개선할점

  • 일단 익숙한 느낌으로 atomic 디자인 시스템 폴더구조를 사용했는데, 딱히 atomic하게 구성하지 않아서 폴더구조를 바꿔야 할 필요성이 있어보인다.
  • getStaticProps를 사용해서 빠르게 렌더링될수 있도록 할것.
  • 프로젝트 이미지 제대로 뽑아서 수정할것
  • css 공통 요소 줄이고(border라던가) 의미에 맞게 정리하기.
profile
주니어 플러터 개발자의 고군분투기

0개의 댓글