2 minute read

빌드시 Debug와 Release 모드의 차이

자바를 쓰건 C++을 쓰건 뭐를 쓰건 빌드할 때 보면 Debug와 Release로 나눠 빌드하고 실행할 수 있다. 내가 알고 있었던 차이는 Debug모든 디버깅을 하기위한 것이고(당연..), Release가 더 코드를 최적화하고 디버그 관련 정보들을 빼기 때문에 용량도 더 적다, 모드에 따라서 코드 분기처를 할 수 있다는 것 정도였다. 왜 지금껏 이것에 대해 큰 의문을 가지지 않고 빌드해왔는지 의문이고 부끄럽기까지 하지만 이제서라도 차이를 공부하여본다.

Release는 코드 최적화를 하고 Debug에서는 하지 않는다

서두에 언급한 내용으로 이것은 내가 알고 있던 것이 맞았다. 여기서 코드 최적화란, 컴파일러가 내가 작성한 코드를 기계어로 번역할 때 더 나은 코드로 바꿔준다는 것이다.

예를 들어

int a = 0;
a++;
cout << a << endl;

이라는 코드를 작성하고 컴파일 했을 때, 디버그 모드에서는 위 코드처럼 변수 a의 공간을 할당하고 거기에 값을 저장하고, 1을 증가시킨 다음에 a를 출력한다면, 릴리즈 모드에서는 컴파일러가 공간 할당없이 그냥 냅다 1을 출력해버리는 식으로 코드를 최적화해서 속도를 향상시킬 수 있다. 아니 그러면 왜 디버그 모드를 사용하냐? 위 예시는 단순한 코드이기 때문에 에러가 발생해도 눈으로 바로 디버깅할 수 있다. 하지만 복잡한 코드에서는 과도한 코드 최적화시 작성한 코드와 실제 실행되는 명령 사이의 관계가 복잡해져 중단점이 제대로 안찍힐 수 있기 때문에 디버깅 툴을 이용한 디버깅이 어려워질 수 있다. 이게 무슨 말이나면, 위 예시 코드가 에러가 났는데 과도하게 최적화해버리면 a++에서 에러가 난건지 출력하다가 에러가 난건지 제대로 파악하기 어려워질 수 있다는 것이다.

Debug 모드에서는 컴파일 시 코드의 안정성을 위해 여러 가지 장치를 추가한다.

C++에서 초기화하지 않고 변수를 선언하면 초기에는 메모리에 쓰레기값이 들어가게 된다. 그런데 릴리즈 모드에서는 정체불명의 랜덤한 값들이 보이는 반면, 디버그 모드에서는 cc이런 식으로 특정 값으로 메모리 공간을 밀어버려 디버깅을 용이하게 도와준다.

또한 디버그 모드에서는 리터럴이 들어가는 공간, stack, heap 공간 사이에 여유 공간을 두어 공간 낭비를 하더라도 코드의 안정성을 확보하지만 릴리즈 모드에서는 이런 공간마저도 최적화한다. 이 때문에 디버그 모드에서는 에러가 나지 않던 코드가 릴리지 모드에서는 다른 공간을 침범하여 에러가 발생하는 일이 벌어질 수 있다. 예를 들어 포인터를 이용해 어떤 값을 변경하는 코드를 작성할 때 실수로 잘못된 공간의 값을 변경해버린다고 하자. 여유 공간의 쓰레기 값을 변경해버리면 문제가 되지 않지만, 힙 공간의 중요한 값을 변경해버리고 이게 에러도 안나버리면 디버깅하기 매우 어려울 것이다.

생성되는 실행 파일의 크기가 다르다

VC++을 기준으로 살펴보면 릴리즈 모드와 디버그 모드에서 사용하는 라이브러리에 차이가 있다. 디버그 모드에 사용하는 라이브러리에는 디버그에 용이한 기능들이 포함되어 있기 때문에 더 용량이 크고, 이를 함께 빌드하니 실행 파일의 용량이 더 커지게 된다.


위 차이를 종합적으로 생각해보면 단순히 운영에 배포할 때는 Release, 개발하고 테스트할 때는 Debug 모드로 빌드해야되는 것이 아니다. 목적에 맞게 빌드를 하면되고, 개발시 Debug 모드로 빌드하더라도 중간중간 Release 모드로도 빌드해보면서 테스트를 해봐야한다. Debug 모드로 개발하고 최종 테스트하고 Release 모드로 빌드하고 배포했을 때 문제가 생겨버리면 낭패일 수 있다.

참고

  • https://coding-factory.tistory.com/648