한빛N MSA(Micro Seminar Assemble)는 한빛미디어 디지털콘텐츠개발연구소에서 준비한 세미나 시리즈다. 학교와, 학원 등에서 다루지는 않지만, 현업에서 일을 할 때 필요한 지식, 기술, 정보 등을 전달하는 걸 목표로 진행되는 세미나다.
유일하게 현장에서 듣지 못한 첫 세미나인 Debugger 활용법.
이번 리뷰는 한빛N 사이트에서 제공하고 있는 VOD, PDF 자료를 보고 정리했다.
본 게시글에 사용된 강의 자료는 한빛미디어의 지원을 받았습니다.
소년탐정 김전일 옆에는 미유키와 마린이 옆에 있고,
셜록홈즈에는 왓슨 박사가 있는 것 처럼.
프로그래머가 버그라는 범인을 잡기 위해선 디버거라는 조수가 필요하다.
과연 우리가 디버깅 기술을 익히면 회사에 입사하는데도 도움이 될까? 그 이유를 한번 따져보자.
파란색 부분: 변수명 생각하기
노란색 부분: 스택오버플로우 검색하기
주황색 부분: 버그 찾기
초록색 부분: 코딩 하기
개발자 유머로 떠돌아다니는 사진이다. 어느정도 개그라 치더라도 솔직히 틀렸다고 볼 순 없다. 실제로 버그를 잡는데는 개발 시간의 몇배씩 걸리니까.
실제 경험담으로, 발표자 분이 다녔던 회사에서의 1~2명 정도의 프로그래머는 아예 예비인력으로 빠져 버그만 잡는 역할을 담당했다고 한다. 실제로 본인 또한 2년 정도 이런 역할을 했던 적이 있었고.
코딩을 하는 많은 사람들이 vi의 키맵을 익힌다던가, 취향에 맞는 폰트를 쓴다며 세팅에 많은 시간을 쓴다. 근데 냉정하게 놓고 보자면 코딩 속도는 좀 느리더라도 상관없다. 요즘은 Copilot의 힘을 받을 수도 있고! 스택오버플로우 또한 같은 측면에서 원하는 자료를 찾는데 속도가 느리다해도 크게 문제되진 않는다.
근데 버그는 아예 상황이 다르다. 버그를 10분만에 잡으면 아무 문제가 없을 수 있는데, 버그를 잡는데 1시간이 걸렸다면 장애 리포트를 쓸 수도 있고, 하루가 걸렸다면 임원진에게 불려가는 대참사가 날 수도 있다.
이렇게 디버깅은 굉장히 급한일이기에, 코딩을 도와주는 각종 세팅에 투자하는 것도 좋지만 자신이 현재 사용하는 환경의 디버깅 기법을 익혀두는 것도 굉장히 유리하다는 것을 알아두자.
"그냥 console.log, log.debug로 로그 출력하면 안되나요?"
한빛 세미나를 들으며 강연자 분들이 공통적으로 하셨던 말이 '수단 자체가 목적이 되면 안된다'는 것이다, 코딩이 비즈니스를 위한 수단인 것 처럼 디버거 또한 버그를 잡는 수단이지, 그 자체가 목적이 아니다.
생각보다 위처럼 물어보는 사람들이 많다며, 간단한건 로그 찍어서 보는게 맞다고 하셨다.
디버거는 환경에 영향을 많이 받는 편이라, 유용할때가 있는 반면에 전혀 쓸모없는 경우도 있다.
내가 사용하는 언어, 프레임워크, 개발 방식(로컬/원격)에 따라 굉장히 많은 영향을 받는 기법이다.
이렇게 까칠한(?) 디버거는 보통 로그를 남기기 힘든 경우에 사용하면 이점을 얻을 수 있다.
대표 사례 3가지를 알아보자.
코드를 수정하고 재실행 하는 것이 부담되는 경우
대기업으로 갈수록 코드를 수정하고 재실행하는 것 자체가 부담스러운 프로젝트가 많다. 강연자분의 경험담을 적어보자면, 전체를 다시 빌드하는데 4시간, 로그 한줄 추가하고 빌드하는데 30분, 이걸 실행하는데 또 30분이 걸렸다고 한다. 이렇게 코드를 수정하기 부담되는 케이스가 첫번째.
버그가 발생한 곳이 내 코드가 아닌 경우
남이 만들어 놓은 코드를 마음대로 수정해서 볼 수 있으면 참 좋을텐데. 굉장히 찾기 번거롭거나, 심지어 라이브러리가 소스를 제공하지 않는 경우를 생각해보자. 이럴때 로그로 추적하기 매우 힘들기에 디버거가 도움이 된다.
버그가 어디에서 발생 한 것인지 모르는 경우
정말 최악의 경우다. 그렇다고 해서 프로그램의 모든곳에 로그를 박는건 사실 불가능하기에, 이럴때 디버거를 이용해 범위를 좁히며 추적하는 방식이 굉장히 유용하게 쓰인다.
앞서 디버거는 환경에 영향을 많이 받는 편이라 소개했는데, 실제 언어별 차이를 알아보자.
기본적으로 C#, Java, Kotlin이 제일 괜찮은 편에 속하고, C/C++ 같은 오래된 네이티브 언어들, 요즘 나온 네이티브 언어들, JS 순으로 내려간다. 특히 Javascript같은 경우 Vue, Angular처럼 Webapp을 쓰기 시작하면 디버거가 먹통 수준이 되어 거의 불가능하다며 따로 넣어두셨다.
💡 Very High와 High를 구분한 이유는, 디버거에서 별도의 언어를 동원하지 않고도 자기 언어 스스로 디버거의 기능을 확장할 수 있기 때문이라고 한다. C++의 경우 다른 언어를 동원하는 경우가 있다.
디버거 사용법을 배운다는거는, 굉장히 노력과 시간이 많이 들어가는 일이다.
만약 자신의 코드가 완벽해서 디버거를 쓸일이 없는 사람이 있다면, 다른 곳에 쓸 방법은 없을까?
💡 디버거는 기존 프로젝트를 분석할때 굉장히 유용하다!
대표적으로 2가지 케이스가 언급됐다.
요즘 언어가 가면갈수록 코드를 눈으로 읽기 힘들게 하는 언어적 기능들이 생겨나고 있다.
대표적으로 Async, Callback, Delegate, Abstract, Annotation(Decorator), etc...가 있겠다.
이런 경우 눈으로만 코드를 분석하기란 매우 어렵다. 이때 디버거라는 유능한 조수를 사용하면 코드를 하나씩 쫓아가며 프로그램 흐름을 쉽게 분석할 수 있다. 이런 이유로 디버거가 '프로젝트 분석'에 적합하다 볼 수 있겠다.
여기부터는 Java와 IntelliJ를 베이스로 디버거 기능에 대한 활용법을 소개했다. 이번 세미나의 핵심 부분으로, 디버거를 한 번이라도 사용했다면 알만한 기능부터 애매한 상황에서 쓸 수 있는 유용한 기능들까지 각각 어떤 상황에 적용하는게 좋을지 얻어갈 수 있는 파트다.
💡 보다 자세한 활용 예시가 궁금하다면 한빛미디어에서 공개한 세미나 VOD를 확인해보자!
기본적으로 모든 디버거에서 돌아가는 기능들이다.
아래는 대부분의 디버거에서 가능한데, 안되는 경우가 가끔있는 그런 기능들이다.
마지막으로 실제로 유용하게 쓰는 기능들을 소개해주셨다.
Runtime Code Patch: '이거 이렇게 바꾸면 될 것 같은데?'라고 생각할때 쓸 수 있는 기능.
→ 브레이크 걸린 상태에서 고치고 실행해 결과를 확인하자!
Thread Debug Control: 쓰레드가 돌고 있어 디버깅하기 굉장히 번거로울때 사용하는 기능.
→ 특정 쓰레드를 디버깅하거나, 모든 쓰레드가 멈췄을때의 상황을 보고 싶을때!
ex) Backend 디버깅 상황에서 Background 통신을 하는데, 디버깅을 걸어 프로그램을 멈춰둔 바람에 Timeout이 발생해 Connection이 끊어지는 경우.
Remote Debugging: remote debug를 설정해 원격으로 디버깅 하는 기능.
→ '내 컴에서 잘 되는데, 왜 실제 서버에 올리면 안돼?'의 경우에 해당 기능이 유용하다.
실제로 멀티 쓰레드를 돌리는 프로젝트에서 특정 쓰레드만 보고 싶었을때 다른 쓰레드가 끼어들어 원하는 결과를 못봐 다시 돌리며 확인했던 기억이 있는데,,, 차라리 이때 디버거를 좀 더 공부했다면 수월하지 않았을까 싶다.
지금까지 보여준 기능만 잘 사용해도 아주 효과적인 디버깅을 할 수 있지만,
추가적으로 Visual Studio에서만 되는 좀 더 특수한 기능도 소개해주셨다.
IntelliJ, Visual Studio 이런 툴들은 텍스트 에디터가 아닌, IDE다.
말 그대로 코딩도 할 수 있고, 컴파일, 디버깅, 배포도 할 수 있는 도구로, 이 유능한 조수의 기능을 하나씩 익히다보면 많은 문제를 어렵지 않게 해결할 수 있는 경우가 많다. '아 이거 좀 피곤한데?' 하는 것들은 누군가 플러그인을 만들어 해결해 놓은 경우가 많기도 하고!
특히 IDE 만든 회사들도 끊임없이 신규 기능을 넣어 업데이트 하기에, 패치노트를 보고 쓸만한 것들은 바로바로 활용해 생산성을 높여보도록 하자.
만약 이 내용들을 다 안다면? 마지막으로 디버깅 기법의 최고봉인 Dump 분석을 공부해보자!
Postmortem Debugging 이라고도 불리는 Dump 분석은 이미 상황이 종료된 다음에 분석하는 기법이다. 범용적이지도 않고, 환경마다 완전히 다른 기법을 요구하는게 특징이다. 까칠함이 디버거를 넘어서는 느낌이다...
OS 설정을 조정하면 프로그램이 죽을때 Core Dump라는걸 남기게 되는데, 이를 분석한다고 생각하면 된다. 물론 이때는 이미 프로그램이 종료가 됐기 때문에, 중간에 로그를 남기거나 추가적인 작업은 불가능하다.
💡 Example
사용자 앱이 배포됐는데 특정 폰에서 오류되는 경우를 떠올려보자.
이럴때 오류가 난 사람을 찾아가 "디버깅 코드 넣었으니 다시 실행해 로그 쌓아주세요"라고
말 할 순 없는 노릇이니, 이럴때 덤프 분석을 사용하면 굉장히 도움이 된다.
Dump 분석에는 OS별로 Windbg(윈도우), gdb(리눅스), lldb(애플)가 대표적이다. 물론 이외에도 다른 솔루션이 존재한다. Dump 디버거의 경우, 되게 사람 취향차이가 크기 때문에 취향에 맞는 도구를 찾아보자.
초반에 봤던 디버거 퀄리티 표를 통해 어떤 환경이 좋고 나쁜지를 들었는데, 아까 표 아래에 있는 것들은 불가능하다고 보는게 맞다고 하셨다. 강연자분이 파이썬으로 어렵게 Dump 분석을 했던 경험담을 소개해주셨는데, 파이썬의 경우 Dump 분석을 하게 되면 파이썬 코드가 보이는 것이 아니라 인터프리터 코드로 보여 하나씩 따라가며 추적하는 것 자체로 어려웠다고 한다.
이 다음은 Q&A로, 지금까지 진행했던 세미나들 중에 제일 많은 질문이 나왔다. 해당 세미나에 참여했던 참석자들의 질문 내역 일부를 아래에 적었으니, 해당 질문에 대한 답변이 궁금하다면 한빛미디어에서 공개한 영상 자료를 통해 살펴보자!
탐정에게 조수가 필요한 것 처럼, 개발자에게는 디버거가 필요하다.
다른 세미나에 비해 활용 예제가 강의의 절반 정도를 차지할 정도로, 각종 IDE에서 사용할 수 있는 디버거 기능을 자세히 배울 수 있던 시간이었다. 특히 내가 그동안 쓰던 디버거 기능은 극히 일부분이었단 사실을 알게됐다. 유능한 조수가 있다 하더라도 조수를 적절히 써먹지 못하면 무용지물이기에, 디버거를 제대로 활용해 개발 과정에서 발생하는 문제를 효과적으로 해결해보려 한다.
강연자분의 설명이 이해하기 쉬웠기에, 본인이 백엔드 개발자인데, 개발 생산성 향상을 위해 디버거를 사용하는 방법를 알아가고 싶다면 한 번쯤은 해당 세미나 영상을 보는게 어떨까!