debugger - 10분 배우고 하루 30분 벌자

jomminii·2024년 12월 24일
1

easy-coding

목록 보기
1/3
post-thumbnail

print(”*” * 100, variable) 로 디버그를 해왔던 과거를 잊어라. 코드를 지저분하게 만들지 않고, 푸시할 때 안지운게 없는지 체크를 하지 않아도 되며, 하나하나 모든 변수를 print 찍어가며 무한 request 를 날렸던 시절을 추억하며 디버거를 사용해보자.

Debugger 설정

이 글에서는 vscode 혹은 cursor IDE 에 설정하는 법을 배운다. 참고로 jetbrains 도 아래와 같은 방식으로 설정할 수 있으니 참고하자.

vscode/cursor

python

.vscode/launch.json

{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387

  "version": "0.2.0",
  "configurations": [
    
    {

      "name": "Python Debugger: FastAPI",
      "type": "debugpy",
      "request": "launch",
      "module": "uvicorn",
      "args": [
        "app.main:app",
        "--reload",
        "--host",
        "host 정보 입력", // ex) localhost
        "--port",
        "포트정보 입력", // ex) 8080
        // 그 외 인자 정보
      ]
      
    }
  ]
}

만약 main.py 등의 파일로 실행하고자 한다면 아래처럼 설정을 좀 변경해야 한다.

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Python Debugger: FastAPI",
      "type": "debugpy",
      "request": "launch",
      "program": "main.py",
      ...
    }
  ]
}

도커로 서버를 띄웠다면 아래처럼 설정하면 된다.

# Dockerfile
...
# 도커에 debugpy 설치
RUN uv pip install --system -r /app/requirements.txt && \
    pip install debugpy 
...
version: '3.8'

services:
  backend:
    ports:
      - "5678:5678"     # debugpy port 노출
      
    # 기존 서버 실행자 앞에 debugpy 실행하고 port 설정
    command: ["python", "-m", "debugpy", "--listen", "0.0.0.0:5678", "--wait-for-client",
              "-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
    env_file:
      - .env.dev
    volumes:
      - .:/app

launch.jsonrequest 는 launch 가 아닌 attach 로 설정하고, 연결 설정을 해준다.

// launch.json
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387

    "version": "0.2.0",
    "configurations": [

        {
            "name": "Python Debugger: Docker FastAPI",
            "type": "debugpy",
            "request": "attach",
            "connect": {
                "host": "localhost",
                "port": 5678
            },
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}",
                    "remoteRoot": "/app"
                }
            ],
        }
    ]
}

이후에는 docker-compose up 등으로 도커 띄우고, 똑같이 F5로 실행하면 된다.

vue

.vscode/launch.json
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "type": "chrome",
      "request": "launch",
      "name": "Launch Chrome against localhost",
      "url": "로컬 접속 url",
      "webRoot": "${workspaceFolder}/src",
      "sourceMapPathOverrides": {
        "webpack:///*": "${workspaceFolder}/src/*"
      }
    }
  ]
}
  

설정 파일을 간단히 살펴보면,

  • version : 템플릿 버전으로, 제시된 고정 값을 사용하면 된다.
  • name : 디버거의 이름을 설정할 수 있다. 아래에 표출되는 이름이다.

  • type : debug 를 하는 타입이다. debugpy 는 파이썬을 디버깅 할 수 있는 타입이다.
  • request : launchattach 옵션이 있는데, 로컬에서 디버거를 실행하는 목적인 경우 launch 를 사용하면 되고, attach 의 경우 원격에서 ssh 등으로 붙었을 때 사용할 수 있는 옵션이라고 한다.(+ docker 로 띄웠을 때도 붙는데 사용한다.)
  • module : python -m uvicorn 과 동일하다. 현재 활성화된 Python 환경의 모듈로 지정한 모듈을 실행한다.
    • 만약 main.py 등으로 실행하고자 한다면 파이썬 스크립트를 실행하는 program 속성을 사용한다.
  • args : module에 제공되는 인자들을 나열한다.
  • justMyCode(default true) : 내가 작성한 코드만 디버깅한다는 옵션이다. false 로 하면 외부 모듈도 디버깅할 수 있다.
  • 그 외 python, pythonArgs, console 등의 속성들도 있는데, 필요한 경우 찾아서 적용하자.

파일 만드는게 귀찮다면, GUI 로 add configuration 을 할 수도 있다.


intellij 패밀리

intellij 패밀리에서도 Run/Debug Configurations 에서 설정 가능하다. module 에 원하는 모듈을 설정하고, 그 밑에 인자를 나열하면 된다.


Debugger 주요 기능

launch.json이 설정되었다면, F5로 Debug 를 실행할 수 있다. 기존의 터미널 창이 아닌 Debug Console 에서 디버그 로그를 볼 수 있다. 브라우저 콘솔처럼 데이터를 읽고 수정하는 것도 가능하다.

Debugger 스텝 바

  • Continue(F5)
    • 다음 breakpoint 까지 프로그램을 계속 실행한다.
    • 이후 breakpoint 가 없으면 프로그램 실행을 완료한다.
    • 딱 지정한 부분으로 넘어가고 싶을 경우 사용한다.

debug_continue.gif

  • Step Over(F10)
    • 현재 라인의 코드를 실행하고 다음 라인으로 이동한다.
    • 함수 호출 시 함수 내부를 들여다보지 않고 전체적으로 실행한 후 이동한다.
    • 현재 코드 레벨에서 한줄 한줄 실행해보고 싶을 때 사용한다.

debug_stepover.gif

  • Step Into(F11)
    - 현재 라인에서 함수 호출이 있는 경우 함수 내부로 진입한다.
    - 코드의 상세한 실행 과정을 추적하고 싶을 때 사용한다.
    debug_stepinto.gif
  • Step Out(Shift + F11)
    - 현재 함수의 실행을 완료하고 호출한 상위 함수로 돌아간다.
    - 내부 디버깅을 마치고 상위 컨텍스트로 빠져나올 때 사용한다.
    debug_stepout.gif

Break point 패밀리

우리가 실수로 눌러서 생기던 빨콩이들이 바로 그 break point 이다. (아..앗! 이게 뭐야..!!)

실수로 누르던 것처럼 마우스로 라인 왼쪽의 빈 공간을 클릭해도 되고, 유려하게 그 라인에 커서를 두고 F9 를 눌러도 된다. 다시 누르면 취소 된다.


지정된 break point 는 디버그 패널에 라인 순서대로 나타나며, 체크박스를 통해 비활성화를 할 수도 있다. 이제 디버그 상태에서 해당 로직을 실행하면 지정한 라인에 멈춰서 우리를 기다린다.

이런 기본 break point 외에도 몇 가지 패밀리가 더 있다. 빨콩을 찍던 곳에서 오른쪽 마우스 클릭을 누르면 패밀리가 보인다.

Log Point

이름처럼 로그를 찍어주는 역할을 한다. 아래처럼 지정하면 다이아몬드 빨콩이 생기고, 이곳을 디버거가 지나가면(hit) debug console 에 노출된다.

이제 코드 안에 이런거 안 해도 된다. 괜히 썼다가 나중에 같이 푸시 되서 마구 프린트 되는걸 볼 수 있다.

print('***************************')
print(data_list)
print('***************************')

현재 실행 환경 내에 있는 데이터도 로그 포인트에 넣어서 출력할 수 있다.

data 는 {data} 이다. 이런 식으로 {} 괄호 안에 변수명을 넣으면 된다. 그 외 로직은 안먹히는 것 같다. 예를 들어 "*" * 100 이런거.

Expression

특정 조건을 만족하면 break point 로서 작동하게 해주는 녀석이다. 조건이 true 가 될 경우 작동한다. 예를 들어 len(total_count) > 0 이라든가, use_yn == 'Y' 이런 조건을 해당 지점을 hit 할 때 만족한다면 break point 역할을 하며 멈춰준다.

Triggered breakpoint

특정 break point 에 도달하면 자동으로 triggered breakpoint 로 지정한 break point 가 활성화 되게 하는 기능이다. 앞선 기능과의 관계성을 파악해야하는 로직에서 사용하기 좋다.

예를 들어, 입금액이 1억원이 넘은 경우 에 대한 expression break point 가 앞서 걸려있다고 할 때, 알림 로직이 잘 실행되고 있는지 확인하기 위해 expression break point 가 작동할 경우 알림 로직의 break point 를 활성화 시키라고 할 수 있다. (gif 출처 : vscode)

디버그 패널

디버그를 실행하면, 왼쪽에는 디버그 패널이 나타나게 된다.

variables

현재 실행 시점 기준 활성화 되어있는 변수들에 대한 정보를 볼 수 있다. 데이터를 수정할 수도 있고, 이 데이터들은 debug console 에서 출력해 볼 수도 있다.

Watch

변수명을 적으면 디버그 사이클 동안 해당 변수를 추적해 보여준다. 주의 깊게 관찰해야할 변수들을 지정해서 지켜보면 좋다.

예를 들어 누적 입금 금액을 total_amount += current_amount 와 같은 방식으로 지정하고 있고, 중간중간 이 금액을 보면서 조건이 잘 처리되고 있는지 보고 싶다면 total_amountwatch 에 등록하면 된다.

Call Stack

콜스택은 현재 실행되고 있는 각각의 스택들을 순서대로 쌓아서 보여준다. 이 스택들을 클릭하면, 해당 로직을 실행하고 있는 코드를 보여주고, variables 에도 해당 스택의 변수들을 보여준다.

내가 실행한 기능이 어느 순서로 호출되고 사용되는지 보는데 도움을 준다.

Break points

위에서도 한 번 소개했지만 지정한 break point 들을 관리할 수 있는 곳이다. 각각 또는 한번에 활성화 / 비활성화를 할 수 있고, 어느 부분에 break point 들이 지정됐는지 한 눈에 볼 수 있다.


결론

기존에 무한 print 로 진행했던 디버깅을 디버거로 전환하니 생산성이 확연히 나아졌다. 이런 깨달음을 팀 내에도 전파하고자 세션을 진행했고, 반응도 좋았다. 참여자 모두 디버거를 사용해보겠다고 응답했고, 기존 방식보다 생산성이 확연이 나아질 것 같다고 응답했다.

정말 이 글을 통해 10분만 배우면 디버거 설정부터 기본 기능까지 익힐 수 있고, 이를 통해 생산성이 확연히 나아지는 경험을 하게 될 것이다.

Do Debugger!



참고 사이트

profile
고민은 격렬하게, 행동은 단순하게

0개의 댓글

관련 채용 정보