print(”*” * 100, variable)
로 디버그를 해왔던 과거를 잊어라. 코드를 지저분하게 만들지 않고, 푸시할 때 안지운게 없는지 체크를 하지 않아도 되며, 하나하나 모든 변수를 print 찍어가며 무한 request 를 날렸던 시절을 추억하며 디버거를 사용해보자.
이 글에서는 vscode 혹은 cursor IDE 에 설정하는 법을 배운다. 참고로 jetbrains 도 아래와 같은 방식으로 설정할 수 있으니 참고하자.
.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.json
의 request
는 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로 실행하면 된다.
.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
: launch
와 attach
옵션이 있는데, 로컬에서 디버거를 실행하는 목적인 경우 launch
를 사용하면 되고, attach
의 경우 원격에서 ssh 등으로 붙었을 때 사용할 수 있는 옵션이라고 한다.(+ docker 로 띄웠을 때도 붙는데 사용한다.)module
: python -m uvicorn
과 동일하다. 현재 활성화된 Python 환경의 모듈로 지정한 모듈을 실행한다.main.py
등으로 실행하고자 한다면 파이썬 스크립트를 실행하는 program
속성을 사용한다.args
: module에 제공되는 인자들을 나열한다.justMyCode
(default true) : 내가 작성한 코드만 디버깅한다는 옵션이다. false 로 하면 외부 모듈도 디버깅할 수 있다.파일 만드는게 귀찮다면, GUI 로 add configuration 을 할 수도 있다.
intellij 패밀리에서도 Run/Debug Configurations 에서 설정 가능하다. module 에 원하는 모듈을 설정하고, 그 밑에 인자를 나열하면 된다.
launch.json
이 설정되었다면, F5
로 Debug 를 실행할 수 있다. 기존의 터미널 창이 아닌 Debug Console 에서 디버그 로그를 볼 수 있다. 브라우저 콘솔처럼 데이터를 읽고 수정하는 것도 가능하다.
Continue(F5)
Step Over(F10)
Step Into(F11)
Step Out(Shift + F11)
우리가 실수로 눌러서 생기던 빨콩이들이 바로 그 break point 이다. (아..앗! 이게 뭐야..!!)
실수로 누르던 것처럼 마우스로 라인 왼쪽의 빈 공간을 클릭해도 되고, 유려하게 그 라인에 커서를 두고 F9
를 눌러도 된다. 다시 누르면 취소 된다.
지정된 break point 는 디버그 패널에 라인 순서대로 나타나며, 체크박스를 통해 비활성화를 할 수도 있다. 이제 디버그 상태에서 해당 로직을 실행하면 지정한 라인에 멈춰서 우리를 기다린다.
이런 기본 break point 외에도 몇 가지 패밀리가 더 있다. 빨콩을 찍던 곳에서 오른쪽 마우스 클릭을 누르면 패밀리가 보인다.
이름처럼 로그를 찍어주는 역할을 한다. 아래처럼 지정하면 다이아몬드 빨콩이 생기고, 이곳을 디버거가 지나가면(hit) debug console 에 노출된다.
이제 코드 안에 이런거 안 해도 된다. 괜히 썼다가 나중에 같이 푸시 되서 마구 프린트 되는걸 볼 수 있다.
print('***************************')
print(data_list)
print('***************************')
현재 실행 환경 내에 있는 데이터도 로그 포인트에 넣어서 출력할 수 있다.
data 는 {data} 이다.
이런 식으로 {} 괄호 안에 변수명을 넣으면 된다. 그 외 로직은 안먹히는 것 같다. 예를 들어 "*" * 100
이런거.
특정 조건을 만족하면 break point 로서 작동하게 해주는 녀석이다. 조건이 true 가 될 경우 작동한다. 예를 들어 len(total_count) > 0 이라든가, use_yn == 'Y' 이런 조건을 해당 지점을 hit 할 때 만족한다면 break point 역할을 하며 멈춰준다.
특정 break point 에 도달하면 자동으로 triggered breakpoint
로 지정한 break point 가 활성화 되게 하는 기능이다. 앞선 기능과의 관계성을 파악해야하는 로직에서 사용하기 좋다.
예를 들어, 입금액이 1억원이 넘은 경우 에 대한 expression break point
가 앞서 걸려있다고 할 때, 알림 로직이 잘 실행되고 있는지 확인하기 위해 expression break point
가 작동할 경우 알림 로직의 break point 를 활성화 시키라고 할 수 있다. (gif 출처 : vscode)
디버그를 실행하면, 왼쪽에는 디버그 패널이 나타나게 된다.
현재 실행 시점 기준 활성화 되어있는 변수들에 대한 정보를 볼 수 있다. 데이터를 수정할 수도 있고, 이 데이터들은 debug console 에서 출력해 볼 수도 있다.
변수명을 적으면 디버그 사이클 동안 해당 변수를 추적해 보여준다. 주의 깊게 관찰해야할 변수들을 지정해서 지켜보면 좋다.
예를 들어 누적 입금 금액을 total_amount += current_amount
와 같은 방식으로 지정하고 있고, 중간중간 이 금액을 보면서 조건이 잘 처리되고 있는지 보고 싶다면 total_amount
를 watch
에 등록하면 된다.
콜스택은 현재 실행되고 있는 각각의 스택들을 순서대로 쌓아서 보여준다. 이 스택들을 클릭하면, 해당 로직을 실행하고 있는 코드를 보여주고, variables 에도 해당 스택의 변수들을 보여준다.
내가 실행한 기능이 어느 순서로 호출되고 사용되는지 보는데 도움을 준다.
위에서도 한 번 소개했지만 지정한 break point 들을 관리할 수 있는 곳이다. 각각 또는 한번에 활성화 / 비활성화를 할 수 있고, 어느 부분에 break point 들이 지정됐는지 한 눈에 볼 수 있다.
기존에 무한 print 로 진행했던 디버깅을 디버거로 전환하니 생산성이 확연히 나아졌다. 이런 깨달음을 팀 내에도 전파하고자 세션을 진행했고, 반응도 좋았다. 참여자 모두 디버거를 사용해보겠다고 응답했고, 기존 방식보다 생산성이 확연이 나아질 것 같다고 응답했다.
정말 이 글을 통해 10분만 배우면 디버거 설정부터 기본 기능까지 익힐 수 있고, 이를 통해 생산성이 확연히 나아지는 경험을 하게 될 것이다.
Do Debugger!