자바로 개발을 하게 되면 필수인 IDE가 있습니다. 바로 인텔리제이인데요.
그 중에서도 인텔리제이의 Debugger Mode를 다 한번쯤 사용해본 경험이 있으실 겁니다.
Debugger Mode를 쓸 때 저는 Breaking Point와 Step Over 버튼만 무지성으로 사용하곤 했었습니다.
테코톡에서 디버그 라는 주제를 준비를 하면서 인텔리제이 디버거에 대해서도 잘 사용하고자 글을 작성하게 되었습니다!
기본적인 개념들은 알고 있다! 흥미로운 디버깅 기능을 알고 싶어!라는 분들은 여기로 이동해주세요 !
디버깅 툴을 알아보기 전에 알아두어야 할 Run/debug configurations
디버깅을 시작하기 전에 알아두어야 할 인텔리제이의 기능이 있습니다.
바로 Run/debug configurations 인데요. 말 그대로, 각 구성은 실행할 항목과 사용해야 하는 매개변수, 환경을 정의하는데 사용할 properties로 이루어져있습니다.
인텔리제이는 해당 구성을 통하여 코드를 실행, 테스트, 디버깅합니다. Run/debug configuration의 종류에는 임시 구성과 영구 구성이라는 2가지가 존재합니다.
임시 구성
임시 구성은 영구 구성이 없는 클래스를 실행하는 경우에 생성되는 구성입니다.
실행 가능한 main 함수가 있는 파일에는 위처럼 실행, 디버그 등을 할 수 있는 툴바가 활성화되는데, 이때 해당 버튼을 눌러 실행할 경우,
실행할 수 있도록 최소한의 환경이 자동으로 구성됩니다.
임시 구성은 최대 5개까지만 가능하며, 초과할 경우 이전의 구성은 삭제되거나 설정을 통해 가능한 구성 제한 갯수를 늘려야 합니다.
영구 구성
영구 구성은 당연히 영구적으로 남아있는 구성을 말합니다ㅎㅎ 일시 구성을 저장하거나 생성 버튼을 통해 저장할 수 있습니다.
저는 프로젝트 시에 로컬과 개발 환경을 분리한 상황에서, application-local.yml이라는 로컬 환경의 profile을 따로 만들지 않고 인텔리제이의 구성의 properties로 영구 구성을 설정해두어 사용하기도 했습니다.
Run/debug configurations에 대해 더 자세히 알고 싶으시다면 아래의 튜토리얼을 참고하시면 좋을 것 같습니다. 😁
http://jetbrains.com/help/idea/run-debug-configuration.html#config-folders
자 다시 본론으로 돌아와서, 디버깅 모드에 대해 본격적으로 알아봅시다
Debugging 시작하기
Debugging Session 시작
디버깅 모드를 사용하기 위해 디버깅 세션을 시작해야 합니다.
개발자가 다른 설정을 하지 않는 이상 디버깅 세션은 실행 환경에서와 동일한 run/debug configuration으로 작동합니다.
디버깅 세션이 시작되면 세션마다 아래와 같이 디버거 도구들로 구성된 창(Debug Tool Window)을 확인할 수 있습니다.
Debug Tool Window 구성 보기
인텔리제이 디버깅 도구 창은 Frames, Variable, Watch, Console, Thread, Memory, OverHead로 이루어져있습니다.
주요하게 다루는 몇가지 도구에 대해 알아봅시다.
기초편이니만큼 Frames, Variable, Console, Thread 탭만 짚고 넘어가겠습니다.
Frames Tab
디버깅 중인 프로그램의 상태는 프레임으로 표시되며, Frames 탭에는 현재의 Frame Stack이 표시됩니다.
메서드가 호출될 때마다 새 Frame이 Stack의 맨 위에 추가됩니다.
디폴트로 IntelliJ IDEA는 프레임워크 및 라이브러리 호출에 해당하는 프레임을 숨기게 설정이 되어있기 때문에, 프레임워크 및 라이브러리 호출이 궁금하다면 아래의 버튼을 클릭해야 합니다.
그래서 Frames은 뭔데?
Frame은 활성화된(실행 중인) 메서드 를 나타냅니다.
각 Frame에는 함수의 지역 변수와, 호출된 메서드, 메서드 인자 및 표현식 평가를 가능하게 하는 코드 컨텍스트가 저장됩니다.
예를 들어 프로그램이 실행될 경우, Main 메서드부터 다른 메서드들을 차례로 호출하게 되는데요.
이런 각 메서드 호출에 대한 정보를 Frame이라는 것으로 저장하게 되는 것이죠.
중요한 것은 메서드 실행이 완료되면 해당 프레임이 스택에서 제거됩니다. (이 사실을 꼭 기억해주세요!!)
Variable Tab
이름에서 알 수 있듯, 이 탭에서는 선택한 프레임 또는 쓰레드의 변수 목록이 표시됩니다.
이 탭에서는 변수 범위와 수명에 유의해야 합니다.
목록에 변수가 없으면 현재 실행 시점의 현재 프레임에서 변수가 범위를 벗어났다는 의미이기도 합니다.
다음 기능: Stepping 알아보기
디버깅을 하기 위해 알아야 할, 아주아주 중요한 인텔리제이의 기능이 있습니다.
바로 Stepping, 즉 단계별 실행은 프로그램의 단계별 실행을 제어하는 프로세스를 말합니다.
제가 가장 많이 사용한 기능도 Stepping 중 하나인데요.
아마 많은 분들이 인텔리제이로 디버깅한다! 고 하면 해당 버튼들을 사용해서 하고 있으실 겁니다.
Stepping은 크게 Step Over, Step Into, Step Out, Reset Frame가 있습니다
Step Over
현재 코드에서 단계 별로 이동하는 기능입니다.
현재 코드 라인에 메서드를 호출하는 경우라도 내부로 들어가는 것이 아닌, 다음 라인으로 바로 이동합니다.
위와 같이 5번 라인에 중단점이 있고, 이 상황에서 Step Over 버튼을 누른다면
count 메서드가 아닌 바로 다음 라인인 6번 줄로 이동합니다.
Step Into
Step Into 역시 단계 별로 이동하는 기능입니다.
그러나 Step Over와 달리, 실행될 메서드의 내부로 이동하는 기능입니다.
똑같이 5번 라인에서 Step Into 버튼을 누를 경우 호출된 count() 내부로 이동하게 됩니다.
메서드가 "제대로 동작하고 있다" 라는 확신이 들지 않을 경우 사용하면 좋을 것 같습니다.
+) Smart Step Into
만약 한 라인에 여러 메서드가 있는 경우라면, 인텔리제이는 Smart Step Into를 제공합니다.
Smart Step Into는 여러 메서드들 중에서도 어떤 메서드로 이동할 것인지 클릭을 통해 지정할 수 있는 기능입니다.
Step Out
해당 기능은 현재 메서드에서 벗어나 호출자 메서드로 이동해줍니다.
위 Step Into에서 count() 로 들어왔는데, 또다시 Step Over를 클릭하게 된다면 10번이나 눌러야 합니다.
이때 Step Out을 클릭하게 되면 이 반복을 건너뛰고 자신을 다시 호출시킨 메서드로 이동하게 됩니다.
+)
그런데 주의할 점이 하나 있습니다.
for, while 문 안에 중단점이 찍혀있는 경우, Step Out 버튼을 눌러도 구문이 계속 실행됩니다.
호출자가 안에 있기 때문에 당연히 계속 실행이 되겠죠..??
Run to cursor
run to cursor는 말 그대로 커서가 있는 위치까지 실행 후 커서가 있는 라인에서 중지하는 기능입니다. 간단하게 커서에 임시 중단점이 있는 것처럼 실행하는 모드입니다.
여기서 주의해야할 점이 하나 더 있습니다.
위 사진에서는 커서가 7번 줄에 있고 run to cursor을 누른 라인부터 커서까지에는 중단점이 없기 때문에 7번라인으로 바로 이동합니다.
그런데 만약 커서의 위치 이전인 6번에 중단점이 있다면, 커서의 위치가 아닌 6번에서 중단됩니다.
다시 말하지만 run to cursor는 커서에 임시 중단점이 있는 것처럼 실행하는 모드입니다.
Reset frame
마지막 프레임을 실행 취소하고 스택의 이전 프레임을 복원해주는 기능입니다.
앞서 프레임 설명 시, 메서드 실행이 완료되면 해당 프레임이 스택에서 제거된다라고 했습니다.
Step Over를 반복해서 클릭하다가 중요한 부분을 놓쳤다면, 이 버튼을 클릭하면 좋겠죠?
많은 크루들이 인텔리제이에는 되돌리기 기능이 없는지 궁금해 했었는데요. !결론부터 말하자면 없습니다!
그러나 이 기능을 사용해서 마지막 프레임을 되돌린다면 직전 프레임을 다시 확인할 수 있으니, 이 기능을 활용하면 좋을 것 같습니다.
되돌릴 수 없다며 근데 다시 확인할 수 있다고? 뭔 소리야?
오해하면 안될 중요한 것이 있습니다.
이 옵션은 로컬 변수만 되돌릴 수 있습니다. 정적 변수 및 인스턴스 변수의 값을 되돌리지 않으므로 전체 프로그램 상태를 복원하지 않습니다.
다시 들어도 이게 무슨 말인가 싶죠..?
예를 들어 위와 같은 프로그램이 있습니다.
중단점이 있는 6번에서 step into를 통해 change() 메서드로 들어간다면 Frame Stack에서 change에 대한 프레임이 생기는 것을 볼 수 있습니다.
아직 change가 실행 완료된 것이 아니라 전역변수인 num은 0입니다.
이 상태에서 Step Over를 실행하게 된다면 num가 바뀝니다.
그런데 여기서 change 메서드가 실행 전인 상태로 되돌리고 싶습니다.
Reset Frame 버튼을 통해서 change 프레임을 제거하면
다시 호출부가 있는 6번라인으로 돌아옵니다.
하지만 change 메서드가 정적 변수인 num에 대해 적용한 변경은 되돌릴 수 없습니다. 여전히 10이 되는 것이죠.
따라서 Reset Frame을 사용할 때, 메서드 실행 전으로 시간을 되돌리는 것은 아니라, 프레임을 되돌려 실행되었던 프레임의 정보를 다시 볼 수 있다라는 것을 주의하시길 바랍니다.
이제까지의 내용으로 아마 어느정도는 자주 보았던 또는 예상했던 기능들을 사용하는 데에는 무리가 없을 것 같습니다.
하지만 Stepping에 이어 흥미로운 기능 몇 가지가 더 있어 소개하고자 합니다.
글이 너무 길어져 다음 글에 이어 작성하도록 하겠습니다. (맛있는 거 많다 ~)
* 이 글 내용은 JetBrains의 인텔리제이 디버깅 문서와 직접 작성한 예제로 구성하였습니다.
'우아한테크코스 6기 > 3단계' 카테고리의 다른 글
NoResourceFoundException 에 대해 알아보자 (0) | 2024.08.11 |
---|---|
팀 로깅 전략 구상기 (0) | 2024.08.05 |
Intellij Debugger, 어디까지 알고 사용하고 있나요? - 신기한 기능편 (2) | 2024.07.20 |
Java Annotation Processor 와 Lombok (feat. AST) (0) | 2024.07.18 |
팀 코드잽 1차 데모데이 회고 (0) | 2024.07.18 |