(급페이 프로젝트) 개발환경에만 집중하기 위한 여정

Updated:

배경

이번 프로젝트의 마음가짐은 팀원들에게 도움이 되는 개인이 되자 였는데요. 팀장 직책을 감사하게도 맡게 되어서 좀 더 그 책임이 컸습니다.

그 책임감으로 인하여 제 부분 이외에도 팀원들이 개발에만 집중할 수 있도록 많은 작업들을 해왔는데요.

S3를 이용한 S3 url에 이미지를 올리는 함수 구현같은 꼭 필요한 것부터 블러 처리를 도와주는 컴포넌트 개발까지 제 부분 이외에도 여러가지 작업들을 해왔습니다.

저희 팀이 만났던 문제는 두가지였습니다.

  1. 사장님 계정과 알바님 계정을 분리하는 것까지는 쿠키를 이용해서 가능했지만 접근 제한을 구현하는 게 어렵다.
  2. vercel organization은 유료 배포가 불가능하다. 더불어 PR시 프리뷰까지 보여줬으면 좋겠다.

이를 해결하기 위한 여정을 설명드리겠습니다.

구현

middle ware

미들웨어의 존재는 캡스톤 디자인으로 express 서버를 구현할 때 대략적으로 알고 있었습니다.

무언가의 사이에 있는 존재 정도로 생각했었는데요. next의 공식문서에서 middle ware의 존재를 알게된 후 좀 더 찾아봐야겠다는 생각을 하게 되었습니다.

next에서middle ware는 브라우저와 프론트엔드 서버 사이에 존재한다고 생각하면 됩니다.

프론트엔드 서버에 저장된 쿠키를 활용해 사용자를 판별하고 알맞게 렌더링 시키는 로직을 구현했습니다.

import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { getCookie } from "./app/_util/cookie";

/**
 * 사이트의 제한 조건에 걸렸을 때 다른 곳으로 리다이렉트 시켜주는 미들웨어입니다.
 * @author 이승현
 * @param request
 * @returns
 */
export default async function loginRequired(request: NextRequest) {
  const token = await getCookie("accessToken");
  const type = await getCookie("type");
  const isLandingPage = request.nextUrl.pathname === "/";
  const isAdminPage = request.nextUrl.pathname.startsWith("/admin");
  const isAlbaPage =
    request.nextUrl.pathname.startsWith("/profile-detail") ||
    request.nextUrl.pathname.startsWith("/profile-register");

  if (isLandingPage && token) {
    return NextResponse.redirect(new URL("/notice-list", request.url));
  }

  if (isLandingPage) {
    return NextResponse.next();
  }

  if (!token) {
    return NextResponse.redirect(new URL("/login", request.url));
  }

  if (type === "employee" && isAdminPage) {
    return NextResponse.redirect(new URL("/notice-list", request.url));
  }
  if (type === "employer" && isAlbaPage) {
    return NextResponse.redirect(new URL("/notice-list", request.url));
  }

  return NextResponse.next();
}

export const config = {
  matcher: [
    // 아래 페이지들은 공통으로 들어갈 수 있는 페이지입니다.
    "/((?!login|signup|notice-list|notice-detail|api|_next/static|_next/image|images|icons|fonts|favicon.ico).*)",
  ],
};

request를 받아서 확인한 후 response로 처리한 모습입니다.

사장님 페이지, 알바님 페이지, 초기 화면 등을 잘 구분해서 정리한 후 이를 response에 담아서 가독성을 높혔습니다.

vercel github action

원래는 기초 프로젝트에서 사용했던 netlify를 사용하려고 했으나 Next를 쓰는 것이니 만큼 vercel을 이용한 배포가 좋지 않을까 생각하였고 팀원들도 동의해줘서 이대로 진행하게 되었다.

이번에도 자동 배포를 위해서 github aciton을 사용해야 되나 생각했지만 그럴 필요 없이 vercel에서 자동배포를 해주고 preview까지 pr마다 보여준다고 해서 편하게 생각했었다.

여기서 문제는 team일 경우에는 유료로 배포를 해야한다는 것이다.

다른 yaml 코드를 분석하던 중에 preview 쪽에서 CLI를 이용하는 것을 발견하고 organization은 CLI에서 무료인가? 생각 후 찾아보기 시작했다.

찾아보던 중 깃허브 이슈에서 한마디를 보게 되었다.

vercel CLI로 접근하는 것 밖에는 방법이 없는 것 같네. CLI 한번 써봐 (영어)

organization GUI 유료 > organization CLI 무료 인 거였다.

나의 상황에 딱 맞는 문서를 찾게 되어서 진행하게 되었다. 이제 많이 했기에 간단한 용어 정도는 알고 있음에 기뻐하며 말이다.

vercel CLI 실행

npm i -g vercel

vercel

.github 파일이 존재하면 CLI로 연결되지 않는 문제가 있었다. 따로 옮겨둔 후 연결하고 다시 진행해주면 된다.

vercel을 설치후 실행한다.

위처럼 시키는 대로 대답한 후에 보면 나의 프로젝트 폴더에 .vercel 이라는 폴더가 있는 것을 볼 수 있다.

// .vercel
{"orgId": "...", "projectId": "..."}

위처럼 말이다. 내 프로젝트를 식별하기 위해서 존재하니 어디에 적어두자.

이후엔 vercel에 build를 맡기기 위해 amondnet/vercel-action 라는 액션을 쓸 것이다.

이를 위해선 account token을 발급받아야 한다.

지금까지 얻은 3가지 토큰을 secret에 담아보자.

이후 developer에서 github 자체 토큰도 하나 얻어서 API_TOKEN-GITHUB에 secret으로 저장해놓는다.

이제 준비는 끝났다. /.github/workflows 파일에 아래의 파일들을 넣어주자.

# vercel-merge.yml
name: Deploy to vercel on merge
on:
  push:
    branches:
      - main
jobs:
  build_and_deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: amondnet/vercel-action@v20
        with:
          vercel-token: $
          github-token: $
          vercel-args: "--prod"
          vercel-org-id: $
          vercel-project-id: $

이 파일은 vercel-action을 이용해서 vercel token과 github token에 맞는 배포를 한다. branches를 통해 브랜치를 특정해놨는데 우리 팀은 main이 배포 브랜치이기 때문에 main에 push하는 순간 vercel에 배포할 수 있도록 설정했다.

# vercel-pull-request.yml
name: Create vercel preview URL on pull request
on:
  pull_request:
    branches:
      - develop
jobs:
  build_and_deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: amondnet/vercel-action@v20
        id: vercel-deploy
        with:
          vercel-token: $
          github-token: $
          vercel-org-id: $
          vercel-project-id: $
      - name: preview-url
        run: |
          echo $

preview의 경우에도 이와 같다. 이제 PR에서 commit될 때마다 최상단의 commit이 바뀌게 될 것이다.

github action을 이용한 자동배포가 완료된 것을 확인할 수 있다.

https://gheup-pay-project.vercel.app/

프리뷰 역시 성공적으로 보여지는 것을 확인할 수 있다.

하지만 기존에 vercel을 사용하는 다른 코드가 존재했고 preview는 팀원들이 굉장히 자주 쓰는 부분이기 때문에 교체하는 시기가 애매해져서 적용은 하지 않게 되었다.

아래의 코드도 위의 코드와 유사하게 기능하는 코드이다.

name: Preview

on:
  pull_request:
    branches: ["develop"]

jobs:
  vercel-preview:
    runs-on: ubuntu-latest

    permissions:
      contents: read
      pages: write
      deployments: write
      id-token: write
      issues: write
      pull-requests: write

    env:
      VERCEL_ORG_ID: $
      VERCEL_PROJECT_ID: $

    steps:
      - uses: actions/checkout@v4

      - name: Install Vercel CLI
        run: npm install --global vercel@latest

      - name: Get Vercel Environment Variables
        run: vercel pull --yes --environment=preview --token=$

      - name: Build Project Artifacts
        run: vercel build --token=$

      - name: Deploy Project Artifacts to Vercel
        id: deploy
        run: |
          vercel deploy --prebuilt --token=$ > vercel-output.txt
          echo "preview_url=$(cat vercel-output.txt)" >> $GITHUB_OUTPUT

      - name: Comment PR with Preview URL
        uses: thollander/actions-comment-pull-request@v2
        with:
          message: |
            🎉 구현한 기능 Preview: $

위처럼 PR의 커밋마다 URL을 comment로 달아준다.

reference

vercel CLI 배포 관련 gist

https://nextjs.org/docs/app/building-your-application/routing/middleware

급페이 프로젝트 중 고민했던 방식, 부딪히게 된 문제, 그것의 해결과정을 담은 글입니다!

잘못된 내용이 있다면 말씀 부탁드립니다. 감사합니다.

Categories:

Updated:

Leave a comment