icecream: print 디버깅을 견딜 만하게
print 디버깅의 불편을 덜어 주는 icecream(ic). 식 텍스트 자동 표시, 위치 추적, 통과값 반환, 한 줄로 전체 끄기 같은 기능과, 적절한 사용 범위까지 정리합니다.
지난 글에서 실행 중인 프로세스에 바깥에서 붙는 py-spy까지, 무거운 측정 도구들을 두루 살펴봤다. 이제 다시 가장 가벼운 일상으로 돌아온다. 우리는 앞서 print 디버깅의 함정을 짚었지만, 솔직히 잠깐 값을 확인하는 데는 여전히 print만큼 손이 빠른 게 없다. 그렇다면 print의 불편한 부분만 덜어 낼 수는 없을까? icecream은 정확히 그 틈을 노린 작은 도구다. 한 글자, ic()로 print 디버깅을 견딜 만하게 바꿔 준다.
ic()는 식과 값을 함께 보여 준다
print 디버깅의 가장 큰 불편은 “찍힌 값이 뭔지 모른다”는 것이었다. print(total)이 42만 덜렁 출력하면, 출력이 여러 개일 때 어느 것이 무엇인지 구분이 안 된다. ic()는 식 텍스트와 값을 함께 출력해 이 문제를 통째로 없앤다.
from icecream import ic
user = "alice"
total = 42
ic(user) # ic| user: 'alice'
ic(total) # ic| total: 42
ic(total * 2) # ic| total * 2: 84
별도로 변수 이름을 적지 않아도 ic| user: 'alice'처럼 무엇을 찍었는지가 출력에 그대로 남는다. total * 2 같은 식도 텍스트 그대로 보여 주니, “이 값이 어디서 온 거지?”를 되짚을 필요가 없다. 이것 하나만으로도 print 디버깅의 절반은 편해진다.
흐름을 끊지 않는 반환값
ic()의 영리한 점은 인자를 그대로 반환한다는 것이다. 덕분에 기존 식 한가운데에 끼워 넣어도 코드 흐름을 끊지 않는다. 값을 확인하려고 임시 변수를 만들고 줄을 늘릴 필요가 없다.
# 기존 코드를 거의 그대로 두고 값만 들여다본다
result = process(ic(fetch_data()))
# ic| fetch_data(): {'id': 7, 'name': 'box'}
# 인자 없이 부르면 호출 위치와 시각을 찍는다 — 실행 흐름 추적용
ic()
# ic| app.py:42 in run() at 11:03:21.456
인자 없이 ic()만 부르면 그 줄이 실행됐다는 사실을, 파일명·줄 번호·함수·시각과 함께 남긴다. “이 분기까지 정말 들어왔나?”를 확인할 때, print("여기") 대신 ic() 한 줄이면 위치 정보까지 공짜로 따라온다. 이것이 print 디버깅의 둘째 함정인 “어디서 찍혔는지 모른다”에 대한 답이다.
한 줄로 전체 끄기
print 디버깅의 가장 짜증나는 함정은 “지우는 걸 잊는다”였다. icecream은 출력을 코드에서 일일이 지우지 않고도 한 번에 끌 수 있다.
from icecream import ic
ic.disable() # 이 아래의 모든 ic() 호출이 조용해진다
ic(secret) # 아무것도 출력하지 않음
ic.enable() # 다시 켜기
ic.disable() 한 줄로 코드 곳곳에 흩어진 ic()를 통째로 침묵시킬 수 있다. 출력 형식을 바꾸거나(ic.configureOutput), 출력을 print 대신 로거로 보내도록 설정하는 것도 가능하다. 디버그 출력을 남겨 두되 평소엔 끄고, 필요할 때만 켜는 운용이 된다.
적절한 자리
물론 icecream이 만능은 아니다. 외부 의존성이고, 운영 코드에 남길 로그라면 여전히 표준 라이브러리 logging이 정답이다. 레벨·핸들러·포매터로 구조화된 로깅이 필요한 곳에 ic()를 쓰는 것은 도구를 잘못 고르는 일이다. icecream의 자리는 개발 중 빠른 값 확인, 딱 그 영역이다. 커밋 전에는 걷어 내는 것을 전제로, 잠깐 들여다보는 용도로 쓸 때 가장 빛난다.
이렇게 디버깅과 프로파일링의 도구 상자를 한 바퀴 둘러봤다. pdb와 breakpoint()로 멈춰 세워 들여다보고, logging으로 구조적으로 기록하고, cProfile·memory_profiler·tracemalloc·py-spy로 시간과 메모리를 측정하고, 마지막으로 icecream으로 일상의 값 확인을 편하게 만들었다. 도구마다 빛나는 자리가 다르다는 것 — 어쩌면 그게 이 여정에서 가장 중요한 교훈이다. 문제의 성격에 맞는 도구를 고르는 안목이 쌓이면, 버그도 성능 문제도 더 이상 막막한 안개가 아니라 차근차근 좁혀 나갈 수 있는 대상이 된다.
지난 글: py-spy: 코드 수정 없는 샘플링 프로파일러
읽어주셔서 감사합니다. 😊