nextjs 13 winston 적용기 2

이명진·2024년 1월 18일
0

winston 에러 로거 를 하던 프로젝트에 적용하기 위해서 고군분투하고 있다.

이전 글

왜 사용하게 되었는지는 "이전글" 을 참고해서 보면 알수 있다.

next js 에서 로거를 사용하기 위해 next js Route Handlers를 이용해 자체 api를 활용한것 까지 적용했었다.
테스트를 하고 테스트 까지 완료 했다.

이전글의 마지막 을 보면 결국 api에러를 잡기 위해서 이 logger를 사용하고 있다.

그리고 이 에러는 백엔드에서 이미 잡고 있기 때문에 굳이 내가 잡을 필요가 있을까? 에 대한 생각을 갖게 했었다.

미리 결론부터 말하면 나는 생각 자체를 좁은 생각을 가지고 있었다. 좁은생각으로 코드를 짜고 있었고 잘못된 방향으로 코드를 짜고 있었다. 이래서 리팩토링 할것도 많아지고 생각할것이 많아져서 큰 걱정이 되었지만. 지금은 다른방법을 생각해서 간단하게 적용할수 있게 되었다.

결과적으로 에러로그에 대해서 다시 정립하게 되었고 router handler 에 대해서도 자세히 공부할수 있었던 시간이 되었다.

자, 내가 직면했던 에러들과 적용기를 정리해보도록 하겠다.

시작 .

이전 글에서 는 api 자체를 만드는 것에 대해서 nextjs 13 에서는 잘 몰랐기 때문에 간단하게 공식문서를 보면서 쉬운 get 방식의 백엔드에서 만들어 준 api에 적용을 했었다.

이에 대해서 next js 13 에서 router handler 에 대해서 공부를 했었고 다양한 api에 적용을 했어야 했기에 기왕 만들거 동적 Route Segment를 활용해서 기존의 api들을 다 리팩토링 해보자 생각을 하게 되었다.

동적 router segment 에러

동적 Router segment에서 에러를 직면했다.. 동적으로 사용하려면 [] 이 슬로거를 활용해서 폴더 구조를 만들어서 사용하면 되는데 , 공식 문서에서도 나와 있는데 나는 적용이 안되었고 에러가 계속 발생되었다.

공식 문서에서 나온 그대로 폴더구조와 코드를 복붙해서 사용해도 에러가 나온다… 왜그런지 모르겠다.
에러에 대해 구글에 검색해도 이런 에러에 대해 나오지 않고… chatGpt 는 nextjs 13 의 존재에 대해서 모른다..
그래서 어쩔수 없이 query param형식으로 코드를 구현했다.

결과적으로는 잘 해결할수 있었다.
함수 이름과, 발생하는 오류에 대해서도 logger로직도 짜서 적용했다. 아래는 내가 짠 코드이다.

import logger from "@/app/logger";
import { NextRequest, NextResponse } from "next/server";
import { cookies } from "next/headers";

export async function GET(request: NextRequest) {
  const cookieStore = cookies();
  const searchParams = request.nextUrl.searchParams;
  const functionName = searchParams.get("fn");
  const apiName = searchParams.get("an");
  // console.log("reqest", request);
  console.log("cookieStore:", cookieStore);
  try {
    const url = `${process.env.NEXT_PUBLIC_API_KEY}/Airdrop/${apiName}`;
    const res = await fetch(url);
    const data = await res.json();

    return NextResponse.json(data);
  } catch (err) {
    logger.error(`nextjs ${functionName} Error : ${err}`);
    return new NextResponse(null, { status: 500 });
  }
}

문제점 직면

잘 작동되는 것 까지 확인하고 GET먼저 손봐야지 생각을 하던 순간 문제를 만나게 된다.

처음에는 기본 GET 호출이라서 TOKEN 정보를 header 에 전달없이 그대로 호출할수 있었다.

다만 복잡한 로직이 있었는데 바로 웹앱에서 안드로이드와 소통해서 Token을 얻어와서 api를 호출하는 것이었다.

여기서 막혔던 것이 토큰 값을 보안 문제로 굳이 저장하지 않고 사용하고있었는데 이 토큰을 전달해 주는 것이 문제였다.

보안 문제 때문에 쿠키, 세션에도 저장하지 않았던 것을 저장해서 가져올수는 없었고 router handler 자체에 동적으로 cookies를 가져오는 방법이 있었는데 server컴포넌트에서만 저장하고 가져올수 있어서 use훅을 사용할수 없다는 것이 문제였다.
그렇다고 queryprams로 토큰을 전달하기에는 웹 개발자 옵션 네트워크 탭에서 api url을 까볼수 있어서 탈취되는 것은 시간 문제였다.

이 토큰을 어떻게 전달해야 하는가 에 대해서 고민을 엄청하게 되었다.

useEffect를 활용해서 처음 토큰을 받아와야 나머지 api들과 통신들이 이루어 져서 서버컴포넌트로 전환한다면 useEffect를 사용할수 없었고 이를 어떻게 해결해야 하는가 머리를 싸매고 있을때 선임 사수분(백엔드)이 오셔서 잘되어 가냐고 물었다.

이에 대해서 토큰을 전달함에 있어서 문제가 있다고 의견을 나누니 당최 이해를 못하는 분위기였다.

이해가 가는 것이 백엔드 쪽이어서 next js에 대해서 하나씩 설명해야 하고 나의 상황을 자세히 설명해야 했다.

결국 나의 좁은 생각으로 인해..

결국 회의실로 자리를 옮겨서 나에 대한 상황과 문제 상황에 대해서 설명드렸다.
그리고는 해결책을 얻을수 있었다.

애초에 제안을 하였을때 함수 이름과, 에러 등등을 전달해서 에러를 저장해야 했다.

백엔드 개발자 : 함수이름과, 에러를 저장해서 로거를 사용할수 있도록 개발 진행해보세요. 

나: 하고 있는데 토큰 값을 전달해 줄수가 없어서 사용하기 힘듭니다 

백엔드 개발자 : ??? 토큰 값이 왜 필요한거죠? 

나: 자체 api로 사용하고 있는데 백엔드 api호출하기 위해서는 토큰 값이 필요합니다. 

백엔드 개발자 : ??? 

나 : ??? 

이전의 나의 생각은 이랬다.

자체 api를만들어서 백엔드에서 받은 api를 호출 하고 try catch 로 catch 된 에러를 logger로 정리하자.

즉, next/api 를 호출하면 여기에서 백엔드에서 받은 api를 호출하고 catch할때 logger를 저장하는 것이었다. (백엔드 api를 next api로 감싼것)

그래서 백엔드에서 받은 api에서 토큰값이 필요하기에 토큰값을 서버에 전달해줘야 하는데 어떻게 하지 ? 라는 생각이 들었던 것이었다.

왜?

다른 곳에서 사용하는 것을 봤을때 (유튜브, 블로그 등) 다들 next에서 api를 만들때 api를 fetch로 호출하고 catch로 로거를 사용해서 에러를 잡았기 때문이다. 이 방법이 틀린거라고 생각되지는 않는다. 그들은 풀스택 개발자로 나는 지금 백엔드가 캐치하고 있는 에러를 그들은 next js로 풀스택으로 개발해서 백엔드 에러를 캐치해놓고 싶었던 것이었겠지(?) 라고 생각한다. 이 과정과 사례들을 계속 보면서 api 를 호출한다음에 catch로 로거를 사용해야 하는 구나 라는 고정관념을 가지게 된것이었다.

새로운 해결방안

하지만 이렇게 사용하면 안되었다. 일편적인 생각이었다.

논의 결과 결국 logger는 백엔드 api에러를 캐치하는 것이 아니라는 것을 깨닫게 되었다.

자체 api를 만드는것 자체가 api를 호출하는게 아니라 logger를 호출하는 api를 만들어서 사용해야 했던 것이다.

이를 통해서 백엔드에서 전달해주는 api문제만 보는 것이 아니라 전체 어떤 함수 든 적용가능한 로거를 만드는 것이 목적이었다.

next/api/logger를 만들어서 logger만 호출해서 seq 페이지에 에러를 쌓는다.
컴포넌트 렌더링 에러때 이 next/api/logger를 호출해서 쌓을수도 있고 다른 클릭 이벤트나 인터렉티브한 이벤트에도 이런 로거를 만들어서 쌓을수 있다.

다양한 고객들이 개발된 앱과 웹을 사용하면서 로거들을 쌓아줄 것이다.

다시한번 생각을 고쳐먹고 방향을 다시 잡으니 이전의 api들을 리팩토링할것에 대해서 걱정이 사라지고 쉽게 해결할수 있었다.

profile
프론트엔드 개발자 초보에서 고수까지!

0개의 댓글