homeblog

Console.log 말고 서버 디버깅은 어떻게 해야 할까?

Jan 8, 2025

1 views

쉽고 빠른 Next.js 서버 디버깅

Next.js 에서 개발하다 보면 서버 사이드 코드를 디버깅할 일이 생깁니다. 그리고 FE 개발자는 브라우저 환경에서 디버깅하는 것은 익숙하지만 서버에서 디버깅은 익숙하지 않죠.

저 같은 경우는 _document, _app, getServerSideProps 같은 서버 전용 코드의 실행 흐름을 명확히 알아야만 특정 문제를 해결할 수 있었는데, **“대체 지금 어디서 이 코드가 어떤 흐름으로 실행되고 있는 거야?"**라는 혼란에 빠졌었습니다.


첫 시도, console.log 만으로는 파악하기 힘들다.

가장 빠르게 해 볼 수 있는 방법은 console.log 를 각 지점에 찍어보는 것입니다. 브라우저에서 중단점을 유용하게 쓰고 있지만, 때론 console.log, console.trace처럼 빠르게 현 상태를 파악해 보곤 하죠. 자연스럽게 서버 디버깅도 console 을 이용했으나, 여러 로그가 섞이고, 필터링이 어려운 터미널에서의 디버깅은 유독 더 불편하게 느껴졌습니다.

// _document.tsx
static async getInitialProps(ctx: DocumentContext) {
  console.log('ctx:', ctx);  // 거대한 객체가 터미널에 출력됨
}

제가 느낀 문제는 아래와 같은데요.

문제점

  1. 조건부 디버깅의 불편함
    조건을 수시로 수정하고 터미널을 clear 하며, 때로는 서버를 재시작해야 했습니다.
  2. 가독성 부족
    브라우저 DevTools처럼 객체를 펼쳐보는 게 불가능하고,
    복잡한 구조는 터미널에서 그냥 한 덩어리 텍스트로 쏟아집니다.
  3. 로그 길이 제한
    수백 줄짜리 로그가 출력되면, 터미널 상단부는 잘려버리는 경우도 흔합니다.
  4. 실시간 조작 불가
    중단점에서 변수 값을 직접 바꾸거나, 실행 흐름을 탐색할 수도 없습니다.

결국 곳곳에 console.log를 심어놓고,
“이제 어디서 찍히나…” 하며 추적하다가 지쳐버리게 되죠.


더 나은 방법은?

생각할 필요도 없이 디버깅 툴을 찾아봐야겠다고 생각했습니다.

방법 1: NODE_OPTIONS와 Chrome DevTools 활용

Node.js의 Inspector 모드를 여는 겁니다.

설정

// package.json
{
  "scripts": {
    "dev:debug": "NODE_OPTIONS='--inspect' next dev"
  }
}

사용 방법

  1. npm run dev:debug로 서버 실행
  2. Chrome 주소창에 chrome://inspect 입력
  3. "Remote Target" 목록에서 inspect 버튼 클릭
  4. DevTools에서 중단점 설정 후 디버깅 시작

이 방식에서 접한 문제

  • Remote Target이 안 보일 때가 있다. -> Target을 로컬 서버로 지정해야 하는데, 목록에 노출되지 않는 경우가 있죠. 조금만 검색해 보면 나오는 흔한 문제인데, 원인을 찾기 위해 여러 가지 스탭에 걸쳐 시도해 봐야 합니다.
  • 파일 구조가 직관적이지 않다.
    .next, .pnpm, node_modules 안쪽 코드가 섞여 보이기 때문에 헷갈릴 수 있습니다.

이런 이유로 Chrome보단 IDE 통합 디버깅을 사용하는 게 더 간편했습니다. 개발자에게 가장 익숙한 환경에서, 내가 작성한 코드에 직접 중단점을 쉽게 등록할 수 있기 때문입니다.


방법 2: VS Code (또는 Cursor)에서 직접 디버깅하기

IDE에 이미 내장되어 있는 Run and Debug 탭을 활용하면 쉽게 시작할 수 있습니다. Next.js는 Node.js 기반이기 때문에, 별도 설정만 해주면 VS Code에서도 바로 중단점 디버깅이 가능합니다.

설정 방법

.vscode/launch.json 파일을 생성하고 본인이 디버깅할 환경에 맞게 다음 내용을 추가합니다.

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug Next.js Server",
      "type": "node",
      "request": "launch",
      "cwd": "${workspaceFolder}",
      "runtimeExecutable": "npm",
      "runtimeArgs": ["run", "dev"],
      "skipFiles": ["<node_internals>/**"],
      "env": {
        "NODE_OPTIONS": "--inspect"
      },
      "console": "integratedTerminal"
    }
  ]
}

사용법

  1. 디버그 탭에서 “Debug Next.js Server” 선택
  2. 디버깅할 코드 줄 번호에 중단점 추가
  3. F5를 눌러 실행
  4. 중단점에 도달하면, 변수 값 확인 / Watch 등록 / 즉석 실행이 모두 가능합니다.

브라우저의 DevTools와 거의 비슷한 경험을
터미널을 왔다 갔다 하지 않고 바로 IDE 안에서 할 수 있습니다.


활용 예시: Next.js 서버 실행 순서 디버깅

자 이제, 제가 겪은 서버 사이드 실행 순서를 쉽게 파악해 보겠습니다. 원하는 위치에서 중단점을 설정하고, Next.js가 어떤 순서로 코드를 실행하는지 명확하게 확인합니다.

  1. getServerSideProps – 페이지 데이터를 서버에서 미리 가져옴
  2. _app – pageProps를 받아 페이지를 감싸는 최상위 컴포넌트
  3. _document.getInitialProps – HTML 뼈대를 구성 (여기서는 pageProps 접근 불가)
  4. _document.render – 최종 HTML 생성

디버깅 결과 요약

  • getServerSideProps → _app: 데이터는 pageProps로 전달됨
  • _app → Page: props 그대로 내려감
  • _document: 렌더링 구조만 담당, 데이터 접근은 불가
  • 실행 환경: 모두 서버에서 실행됨 (getServerSideProps, _document)

이 과정을 직접 중단점으로 따라가 보면,
Next.js가 렌더링을 어떻게 단계적으로 처리하는지 한눈에 들어옵니다.
console.log로 실행 순서와 변수까지 확인하려면 결코 쉽게 얻을 수 없는 결과인 것 같아요.


마무리

이제는 서버 코드를 디버깅할 때 console.log만 붙잡지 않아도 됩니다.
한 번만 설정해 두면, 브라우저처럼 직관적인 중단점 디버깅이 가능하고 서버에서 실행되는 로직도 손쉽게 따라갈 수 있죠.

디버깅 환경을 제대로 세팅해 두면,
**“왜 안 되지?”**보다 **“어디서 멈췄는지 바로 확인하자”**로
개발의 리듬이 완전히 달라질 거예요.

고구마 100개 먹은 듯한 환경에서 벗어 나와 이제, 속 시원하게 디버깅 생활해요.

감사합니다.