Skip to main content

신입 웹프론트엔드 개발자 2개월 차 후기

· 18 min read
박서영
프론트엔드 챕터

0. 들어가며

 안녕하세요. 비브로스 웹프론트엔드팀 신입 개발자 박서영입니다. 😀 5월 9일에서 7월 14일까지 약 두 달여 간의 온보딩 과정이 마무리되었습니다. 장장 10차에 걸친 온보딩을 진행하면서 새롭게 학습한 내용, 그리고 좋았던 점과 아쉬웠던 점을 공유해보고자 합니다.

1. 새롭게 학습한 내용

Next.js

pre-rendering

 Next.js에서는 클라이언트 사이드가 아니라 서버 사이드에서 HTML을 pre-rendering 합니다. pre-rendering에는 SSG (static generation), SSR(server-side rendering) 두 가지 방식이 있으며 페이지 단위로 적용할 수 있습니다.

  • SSG - HTML이 빌드 타임에 생성된다.
  • SSR - HTML이 유저 요청 시에 생성된다.

fallback

 동적 라우팅 페이지가 외부 데이터에 의존할 경우, getStaticPaths를 사용하여 빌드 타임에 필요한 path들을 pre-rendering할 수 있습니다. 이때, fallback 옵션을 통해 사전에 생성하지 않은 route들에 대해서 유저 요청 시 생성하거나 커스텀한 에러 페이지로 핸들링할 수 있습니다.

export async function getStaticPaths() {
return {
paths: [
{ params: { ... } }
],
fallback: false // true or 'blocking'
};
}
  • fallback: false

    • status code 404 반환( _error next custom error 페이지로 핸들링)
  • fallback: true

    • 유저 요청이 들어오면 getStaticProps를 호출해 페이지 생성
    • 페이지를 생성하는 동안 fallback HTML을 브라우저에 전달
    • 페이지 생성이 완료되면, 페이지를 다시 렌더링
    • path 리스트에 추가되어 이후 요청부터 static한 페이지 제공
    import { useRouter } from 'next/router'

    function Post({ post }) {
    const router = useRouter()

    // If the page is not yet generated, this will be displayed
    // initially until getStaticProps() finishes running
    // fallback:true 시 페이지를 생성하는 동안 보여주는 페이지
    if (router.isFallback) {
    return <div>Loading...</div>
    }
    }

    export async function getStaticPaths() {
    return {
    paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
    fallback: true,
    }
    }

    // This also gets called at build time
    export async function getStaticProps({ params }) {
    const res = await fetch(`https://.../posts/${params.id}`)
    const post = await res.json()

    return {
    props: { post },
    }
    }

    export default Post
  • fallback: blocking

    • 유저 요청이 들어오면 getStaticProps를 호출해 페이지 생성
    • 페이지 생성이 완료되면, 페이지를 다시 렌더링
    • 빌드된 path 리스트에 추가되어 이후 요청부터 static한 페이지 제공
  • 주의사항: SSG는 production 모드의 build 타임에 가동된다.

    - In development:
    (npm run dev or yarn dev) getStaticProps runs on every request.
    - In production: getStaticProps runs at build time.

    development 모드에서는 요청이 올 때마다 getStaticProps가 실행됩니다. getStaticProps도 SSR처럼 동작하기 때문에 build한 뒤에 start 스크립트를 통해 production 서버를 켜서 확인해야 합니다.

revalidate

export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json()

return {
props: {
posts,
},
// Next.js will attempt to re-generate the page:
// - When a request comes in
// - At most once every 10 seconds
revalidate: 10, // In seconds
}
}

 Next.js 공식문서에서 SSG 사용 예시로 Marketing pages, Blog posts, E-commerce product listings, Help and documentation를 들고 있습니다. ‘빌드 타임에 생성되는데 유저가 blog post를 업데이트하면 어떻게 반영을 한다는 거지?’ 궁금증이 생겼습니다. 찾아보니 SSG도 빌드타임 이후에 DB의 업데이트 상황을 점진적으로 반영할 수 있는 revalidate 옵션이 있었습니다. 페이지에 접속해있으면 n초마다 갱신되는 방식은 아니고 build time/ re-generate time을 기준으로 n초 뒤에 요청이 들어오면 페이지 갱신을 시도합니다. 갱신이 trigger되는 방식이 헷갈릴 수 있는데, Next.js에서 이를 테스트할 수 있는 사이트가 있습니다.



  • 예를 들어 A,B,C라는 유저들이 페이지에 접속했습니다. 이 페이지의 좋아요(👍)는 2,743개입니다.

1.png



  • 유저 A가 좋아요를 눌러 좋아요는 2,744개가 됐습니다.


2.png



  • 유저 B가 페이지를 새로고침합니다. 이때 regeneration이 trigger 되지만 캐시된 페이지를 그대로 받아옵니다. 페이지의 좋아요는 2,743개, 달라진 게 없으므로 status code는 304(Not Modefied)입니다.


3.png



  • 유저 C가 페이지를 새로고침합니다. regeneration이 trigger된 이후에 페이지를 요청했기 때문에 업데이트된 페이지를 받아옵니다. 페이지의 좋아요는 2,744개, 서버가 요청을 성공적으로 응답했기 때문에 status code 200입니다.


모노레포

4.png

 모노레포(Monorepo)란, 하나의 레파지토리에 두 개 이상의 프로젝트를 관리하는 소프트웨어 개발 전략입니다. 10차까지 되는 온보딩을 진행하면서 정말 많은 레파지토리를 생성했는데요. 기존의 멀티레포(Multirepo) 방식으로는 새로운 프로젝트를 시작할 때마다 레파지토리를 생성하고 개발환경을 구축하는 등 번거로운 과정을 반복해야 합니다. 그리고 여러 레파지토리에서 사용하는 패키지에서 변화가 있을 때 일일이 반영해줘야 한다는 단점도 있습니다. 모노레포 방식을 적용하면 기존 환경을 활용하므로 개발 환경 구축 작업을 반복하지 않아도 됩니다. 그리고 공통 모듈은 단일화하여 효율적으로 의존성을 관리할 수 있습니다.



Dependency Module Hoisting

 (yarn workspace를 사용한다는 가정하에) yarn 명령어를 실행하면 루트의 package.json과 각 패키지의 package.json에 명시되어있는 dependency가 최대한 중복을 줄인 상태로 루트의 node_modules 안에 호이스팅됩니다. 이때 루트 경로의 node_modules 에는 각 workspace들이 참조할 수 있는 symbolic link 가 생성됩니다.

5.png

https://classic.yarnpkg.com/blog/2018/02/15/nohoist/

6.png

https://classic.yarnpkg.com/blog/2018/02/15/nohoist/

 예를 들어 package-1는 A와 ‘A를 의존성 모듈로 이용하는’ C를 의존성 모듈로 이용하고 있습니다. 동일한 의존성을 지니는 모듈은 중복 설치할 필요가 없으므로 함께 쓸 수 있도록 루트의 node_moduleshoisting됩니다.



패키지 버전관리 정책

 Fixed/Locked mode 는 패키지 버전을 프로젝트 root에서 관리하고, 하나의 패키지가 업데이트 되면 모든 패키지가 업데이트됩니다. independent mode 는 각 프로젝트마다 독자적으로 버전을 관리합니다. 그리고 lerna publish할 경우, 변경된 프로젝트에 한 해 새 버전으로 업데이트합니다.

7.png

 fixed mode의 경우, my-app1 패키지에 기능이 추가되었지만 my-app2의 버전도 같이 업데이트되는 것을 볼 수 있습니다.


Storybook

 Storybook이란, UI 컴포넌트 개발 도구로 비즈니스 로직과 맥락으로부터 독립된 환경에서 개발할 수 있도록 도와줍니다. 최근에 모달 관련 이슈를 작업하면서 모달들의 종류와 사용처, 작동 방식 등을 확인해보고 싶었습니다. 모달들을 전부 확인하기 위해서는 다음과 같은 과정을 거쳐야 합니다.

  • 일단 모달 서비스를 주입하고 있는 컴포넌트를 전부 검색합니다. 여기서 확인하는 방법은 2가지가 있습니다.
  • A 방안. 모달이 실행되는 조건을 충족시킵니다. 예를 들어 이미지를 20장 이상 등록할 수 없다는 안내 모달은 20장 이상을 등록해서 확인해봅니다.
  • 그것이 귀찮다면 B 방안, 해당 컴포넌트의 코드를 파악하고 실행 조건을 단순화하여 확인해봅니다.

A든, B든 본인이 편한 것을 선택하면 되겠지만 문제는 확인할 모달이 한두 개가 아니라는 점입니다.

8.png

 만약 Storybook이 있었다면 (메뉴를 돌아다니며 모달을 전부 찾아보는) 작업 과정을 단축하고 빠르게 업데이트할 수 있었을 것입니다. Storybook에서 제공하는 기능을 간단하게 살펴보겠습니다.


Actions

 기존 figma, zeplin 등 정적 디자인에서 컴포넌트의 액션에 관해 설명해주지 않는 경우가 있습니다. 모달을 예로 들면, 외부 영역을 클릭했을 때 모달이 닫히는 건지 혹은 외부 영역 클릭은 허용되는 건지 등 움직임에 대한 정책들은 정적 디자인으로 파악하기 어렵습니다. 이때 사용할 수 있는 것이 actions addon입니다. 어떤 함수가 호출되었는지, 함수의 파라미터는 무엇이 있는지 로그에 기록됩니다. 간단한 함수 호출, 라우터 이벤트, Redux 라이브러리를 사용한다면 dispatch되는 action 등을 확인할 수 있습니다.

yarn add --dev @storybook/addon-actions

9.png

https://storybook.js.org/docs/react/essentials/actions


Docs

 공통 UI 컴포넌트를 제작할 때 문서화 작업을 병행한다면 누구나 간편하게 컴포넌트를 사용할 수 있을 것입니다. Storybook의 docs addon을 사용하면 간편하게 컴포넌트 및 스타일 가이드를 제작할 수 있습니다. 기본적으로 대화식 프리뷰, 소스 코드 뷰어, 인자 테이블 등의 기능을 제공합니다. 그리고 MDX를 기반으로 자유롭게 설명과 이미지의 레이아웃이 커스텀 가능합니다.

yarn add --dev @storybook/addon-docs

10.png

 Storybook을 세팅하고 협업 방식을 구축하는 데까지 많은 리소스가 소요될 수 있습니다. 그렇지만 디자인 시스템을 구축해놓는다면 다양한 프로젝트를 신속하게 개발하고, 구성원 간의 지식 격차를 해소하여 업무 효율성을 개선할 수 있을 것으로 기대가 됩니다.



2. 좋았던 점


  • 팀 프로젝트 조사

 favicon을 일괄 교체하는 이슈가 있었습니다. 사실 업무 자체는 반복 작업이었지만 각 레파지토리의 favicon 사용 현황을 조사하면서 우리 팀이 관리하는 프로젝트들이 어떤 게 있는지(🧐), 얼마나 많은지(😇) 파악할 수 있었습니다. 또 release, hotfix 등 브랜치 전략을 이해하고 배포 이후 회사에 공유하는 워크플로우 등에 익숙해지는 시간이었습니다.


  • 빌드 공부

 입사하기 전에는, 단기 프로젝트 위주로 포트폴리오를 구성하다 보니 ‘지속적인 운영’의 관점에서 생각하는 것이 부족했습니다. 다행히 이번 온보딩 프로세스하면서 환경별 혹은 패키지별로 빌드 전략을 구성하고 배포하는 과제를 하는 것이 회사 업무를 이해하는 데 도움이 많이 되었습니다.


  • 운영배포

11.png

 다른 회사 주니어분들이 ‘오늘 배포한다’는 메세지를 보낼 때마다 정말 부러웠었는데요. 온보딩이 마무리되어갈 때쯤 처음으로 운영배포를 해보게 되었습니다. 안내 모달을 하나 추가하는 정도의 마이너한 이슈였지만, 그래도 B2C 서비스에 운영배포를 해볼 수 있어서 기뻤습니다.



3. 아쉬웠던 점

  • 7차 온보딩 과제 부분 통합

     7차 온보딩의 경우, 리뷰 대기 시간에 비해 과제량이 적었습니다. 커리큘럼 자체가 후반부로 갈수록 공식 문서나 검색을 잘하면 수정 사항 없이 accept 받을 수 있는 내용이라 과제를 부분 통합하면 좋겠다는 의견입니다.

    • 7차 온보딩 과제 2. yarn workspace 연동
    {
    "npmClient": "yarn",
    "useWorkspaces": true,
    "packages": [
    "packages/*"
    ]
    }

  • 스크립트나 옵션 설정 과제에 관한 내부 가이드 문서 작성

     자주 사용하지 않으면 까먹기 쉬운 라이브러리 옵션이나 스크립트 같은 경우, 답안지 느낌으로 과제 가이드 문서를 작성해 놓으면 온보딩을 지원하는 팀원들의 시간을 절약할 수 있을 것 같습니다.

    • 3차 온보딩, 과제 9 빌드 스크립트 작성
        frontend:
    phases:
    build:
    commands:
    - if [ "${AWS_BRANCH}" = "master" ]; then npm run build:prod; fi
    - if [ "${AWS_BRANCH}" = "develop" ]; then npm run build:test; fi
    • 9차 온보딩, 과제 2 Controls에서 Description과 Default를 볼 수 있게 설정
      export const parameters = {
    controls: {
    expanded: true,
    },
    }

4. 마무리하며

 온보딩 기간 동안 처음 써보는 기술 스택, 첫 운영이슈, 첫 운영배포, 첫 기획 회의 등 처음 하는 일들이 매우 많았는데요. 프론트엔드팀 뿐만 아니라 QA팀, 기획팀, 디자인팀, 경영지원팀 등 회사 내 여러 팀원분과 소통하면서 제가 정말 비브로스에 입사했다는 게 실감이 났던 것 같습니다. 온보딩 과정이 종료된 만큼 이제는 저도 프론트엔드 팀원으로서 책임감을 가지고 업무를 수행하려고 합니다. 바로 다음 주부터 유저들의 피드백을 실시간으로 업데이트하는 CS도 하게 됩니다. 온보딩 기간 동안 프론트엔드 팀과 회사의 워크 플로우를 충분히 학습한 만큼 앞으로의 업무들도 잘 소화해내고 싶다는 바람입니다.