Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

『이펙티브 디버깅』 - 디버깅 지옥에서 탈출하는 66가지 전략과 기법

5,744 views

Published on

『이펙티브 디버깅』 디버깅 지옥에서 탈출하는 66가지 전략과 기법
디오미디스 스피넬리스 지음 | 남기혁 옮김 | 한빛미디어 | 24,000원

★ 소프트웨어의 완성은 디버깅!
이 책은 경험이 풍부한 개발자를 대상으로 소프트웨어를 완성하는 마지막 기술을 가르친다. 저자는 35년 경험에서 깨우친 일반 원칙, 높은 수준의 전략, 구체적인 기술에 관한 조언, 효율 높은 도구, 창의적인 기법, 효과적인 디버깅과 관련된 행동 특성을 제시한다. 저자가 제안하는 66개의 전문 기법을 통해 디버깅 역량을 확장하고, 각 문제 상황에 맞는 최상의 접근법을 선택할 수 있을 것이다.

★ 주요 내용
다양한 소프트웨어 장애를 해결하는 높은 수준의 전략과 방법
프로그래밍, 컴파일, 실행 시 적용할 구체적인 기법
디버거를 최대한 활용하는 방법
믿고 투자해도 좋은 범용 기술과 도구
막다른 길과 복잡한 미궁에서 탈출하는 첨단 아이디어와 기법
디버깅하기 쉬운 프로그램을 만들기 위한 조언
멀티스레딩, 비동기, 임베디드 코드 디버깅에 특화된 접근법
향상된 소프트웨어 설계, 구축, 관리를 통한 버그 회피법

Published in: Software
  • Sex in your area is here: ❤❤❤ http://bit.ly/2F7hN3u ❤❤❤
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Dating direct: ❤❤❤ http://bit.ly/2F7hN3u ❤❤❤
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Hello! Get Your Professional Job-Winning Resume Here - Check our website! https://vk.cc/818RFv
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

『이펙티브 디버깅』 - 디버깅 지옥에서 탈출하는 66가지 전략과 기법

  1. 1. 『이펙티브 디버깅』 디버깅 지옥에서 탈출하는 66가지 전략과 기법 디오미디스 스피넬리스 지음 남기혁 옮김 한빛미디어
  2. 2. 실력 있는 전문가라면 어떤 오류가 발생하더라도 신속히 문제를 파악해서 근본 원인을 해결할 줄 알아야 한다. 이러한 능력과 기술이 바로 디버깅의 핵심이며 이 책에서 다루고자 하는 주제다. 이 책은 경험이 풍부한 개발자를 대상으로 집필했다. 여기서 소개하는 내용을 제대로 이해하려면 다양한 프로그래밍 언어로 작성된 예제 코드를 읽을 줄 알고 고급 GUI 및 명령줄 기반의 프로그래밍 도구도 사용할 줄 알아야 한다. 이 책은 범용적인 기법부터 시작해서 점차 구체적인 기법을 소개하는 방식으로 설명한다. 먼저 다양한 소프트웨어 및 시스템 오류를 해결하는 데 도움되는 전 략(1장), 방법론(2장), 도구와 기법(3장)부터 설명한다. 그런 다음 디버깅 작업에 실제로 적용할 수 있는 기법들을 단계별로 소개한다. 4장에서는 디버거를 사용 하는 과정에 적용할 수 있는 기법을, 5장에서는 프로그램을 작성하는 과정에 필 요한 기법을, 6장에서는 소프트웨어를 컴파일하는 과정에 필요한 기법을, 7장 에서는 시스템을 실행하는 과정에 적용할 기법을, 8장에서는 멀티스레드 및 동 시성 코드에 관련된 까다로운 버그들을 잡는 데 특화된 도구와 기법을 소개한다 . … 서문 중에서 …
  3. 3. 『이펙티브 디버깅』의 본문 중 각 아이템의 ‘기억할 사항’만 추려 정리했습니다. 자세한 설명과 코드 예제는 책을 참고하세요.
  4. 4. 1장 고차원 전략 본격적으로 문제 해결에 들어가기 전에 전략을 잘 세워야 한다. 그래야 최소 한의 노력으로 문제를 성공적으로 해결할 수 있다. 선택한 전략이 작업에 적 합하지 않다면 즉시 차선책으로 전환해야 한다.
  5. 5. 아이템 1: 모든 문제를 이슈 추적 시스템으로 관리하기 모든 문제를 이슈 추적 시스템으로 처리한다. 이슈를 작성할 때 문제를 재현하는 방법을 정확하 고, 간결하고, 관련된 사항을 모두 담아서, 구체적인 예제와 함께 기록한다. 이슈의 심각한 정도와 우선순위를 정해서 이에 맞 게 작업 일정을 짠다. 이슈 추적 시스템을 통해 작업 현황을 문서화한다.
  6. 6. 아이템 2: 검색어를 구체적으로 표현하기 발생한 에러에 대한 해결책을 웹에서 검색할 때 에 러 메시지를 큰따옴표로 묶어서 입력한다. 스택익스체인지 사이트에 올라온 답변을 참고한다. 위 두 방법으로 해결하지 못했다면 직접 질문을 올 리거나 버그 리포팅 시스템에 이슈를 등록한다.
  7. 7. 아이템 3: 선행 조건과 후행 조건 만족 여부 확인하기 루틴의 선행 조건과 후행 조건을 주의 깊게 검사한 다.
  8. 8. 아이템 4: 문제 발생 지점부터 버그를 추적하거나, 프로그램 시작 지점부터 버그를 찾아나가기 프로그램이 갑자기 종료하거나, 아무런 응답 없이 멈추거나, 에러 메시지가 출력될 때와 같이 문제가 명확히 드러날 때는 상향식 방식으로 원인을 찾는 다. 성능과 보안, 신뢰성 등과 같이 문제가 명확하게 드 러나지 않을 때는 하향식 방식으로 원인을 찾는다.
  9. 9. 아이템 5: 정상 시스템과 비정상 시스템의 차이점 분석하기 정상 시스템과 오류가 발생한 시스템을 비교하여 문제의 원인을 찾는다. 코드, 입력 값, 함수를 호출할 때 전달한 인수, 환경 변수, 서비스, 동적 라이브러리 등을 비롯한 시스템 동작에 영향을 미치는 요인을 모두 고려한다.
  10. 10. 아이템 6: 소프트웨어에서 제공하는 디버깅 기능 활용하기 문제가 발생한 소프트웨어에서 자체적으로 디버깅 기능을 제공하는지 확인한다. 디버깅 기능을 제공 한다면 이를 활용하여 문제를 분석한다.
  11. 11. 아이템 7: 빌드 및 실행 환경을 다양하게 구성하기 컴파일 환경과 실행 플랫폼을 다양하게 구성하면 다양한 시각으로 디버깅 작업을 수행할 수 있다. 난해한 알고리즘에 관련된 문제는 고수준 언어로 구현하여 해결한다.
  12. 12. 아이템 8: 가장 중요한 문제에 집중하기 모든 문제를 해결할 필요는 없다. 우선순위가 낮은 이슈를 해결하는 작업은 우선순위 가 높은 작업을 해결하는 데 필요한 시간을 빼앗을 수 있다.
  13. 13. 2장 범용적인 디버깅 기법 디버깅 방법은 시스템의 기반 기술과 개발 플랫폼에 따라 다르다. 그러나 몇 가지 기법은 다양한 환경에서 공통적으로 사용할 수 있다.
  14. 14. 아이템 9: 성공적인 디버깅을 위한 마음가짐 모든 문제는 찾아서 고칠 수 있다고 믿는다. 디버깅 작업에 필요한 시간을 충분히 확보한다. 작업에 최대한 집중할 수 있도록 환경을 마련한다. 힘든 문제를 해결할 때는 효과적인 수면을 취한다. 포기하지 않는다. 디버깅 환경, 도구, 기법을 익히는 데 꾸준히 노력한다.
  15. 15. 아이템 10: 효율적으로 문제 상황 재현하기 문제 상황을 재현할 수 있다면 디버깅 작업이 쉬워 진다. 문제를 재현할 수 있는 예제를 최대한 간결하고 독 립적으로 실행할 수 있는 형태로 만든다. 반복적으로 실행할 수 있는 환경을 구축한다. 버전 관리 시스템을 활용하여 소프트웨어에 버전을 지정해서 원하는 버전을 언제든지 불러올 수 있도 록 구성한다.
  16. 16. 아이템 11: 코드 수정 후 결과 확인까지의 시간 최소화하기 수정한 코드의 결과를 확인하는 데 걸리는 시간을 최소화하여 효율을 높인다. 빠르게 빌드하고 배치하는 프로세스를 마련한다. 오류가 발생하면 최대한 빠르게 멈추게 한다.
  17. 17. 아이템 12: 복잡한 테스트 시나리오 자동화하기 복잡한 테스트 케이스를 실행하는 작업은 스크립트 언어를 이용하여 자동화한다.
  18. 18. 아이템 13: 디버깅 데이터를 한눈에 볼 수 있는 환경 구축하기 많은 데이터를 한눈에 볼 수 있다면 작업에 좀 더 집 중할 수 있고 데이터의 패턴이나 상관관계를 파악 하기도 쉽다. 화면 공간을 최대한 넓게 확보한다. 변경할 일이 거의 없는 데이터는 프린터로 출력해 서 본다.
  19. 19. 아이템 14: 소프트웨어 업데이트 고려하기 디버깅에 들어가기 앞서 환경을 최신 버전으로 업 데이트한다. 업데이트에 너무 큰 기대는 하지 않는다. 서드파티 모듈에서 버그가 발생할 수 있다는 점도 염두에 둔다.
  20. 20. 아이템 15: 서드파티 소스 코드 분석을 통해 문제 해결하기 작성하는 소프트웨어에서 사용하는 서드파티 모듈 에 대한 소스 코드를 확보한다. 서드파티 API에 문제가 발생하거나 알 수 없는 에 러 메시지가 출력되면 서드파티 소스 코드를 분석 한다. 서드파티 라이브러리를 디버깅 버전으로 빌드해서 사용한다. 다른 대안이 없을 경우에만 서드파티 코드를 직접 수정한다.
  21. 21. 아이템 16: 전문 모니터링 및 테스팅 장비 활용하기 로직, 버스, 프로토콜 분석기를 활용하면 하드웨어 수준에서 발생하는 문제를 정확히 분석할 수 있다. 하드웨어에 관련된 문제를 분석할 때는 적절한 장 치를 직접 제작하는 것도 도움된다. 네트워크 패킷을 모니터링할 때는 와이어샤크나 이 더넷 허브, 매니지드 스위치, 또는 명령줄 기반의 패 킷 수집 프로그램을 활용한다.
  22. 22. 아이템 17: 오류의 효과 극대화하기 의심스런 실행 경로를 인위적으로 따라가게 만든다 . 분석하려는 문제 현상이 눈에 잘 띄도록 그 효과를 극대화한다. 소프트웨어의 실행 영역이 정상 범위를 벗어나도록 스트레스를 준다. 모든 작업을 버전 관리 시스템의 별도 가지(브랜치) 에서 수행한다.
  23. 23. 아이템 18: 원격 디버깅 환경 구축하기 하드웨어에 밀접한 문제에 대한 디버깅 작업을 자신이 사용 하는 컴퓨터의 화면과 키보드로 작업할 수 있도록 장치 에뮬 레이터를 설치한다. 임베디드 소프트웨어를 디버깅할 때는 자신이 사용하는 개 발 머신에서 제공하는 도구를 활용할 수 있게 해주는 쐐기 모듈을 활용한다. 고객의 PC에 발생한 문제를 해결할 때는 원격에서 접속할 수 있는 환경을 구축한다. 서버에 대한 디버깅 작업을 원격에서 수행할 수 있도록I P 기 반 KVM 스위치를 설치한다.
  24. 24. 3장 범용 도구를 활용한 기법 특정한 영역에 특화된 디버깅 도구를 사용하는 것이 훨씬 편리하고 효율적이지만 범용 도구를 활용하는 것도 나름대로 장점이 있다. 여러 언어와 플랫폼으로 구성된 시스템에 서 문제가 발생했을 때 당장 활용할 수 있기 때문이다. 이 장에서 소개하는 범용 도구들 은 오래 전 유닉스를 주로 사용하던 시절에 나온 것이지만 지금까지도 GNU/리눅스와 윈 도우, macOS 등과 같은 다양한 시스템에서 사용할 수 있다. 이러한 도구들이 제공하는 유연성, 효율성, 범용성만 감안하더라도 사용법을 익히는 데 시간을 투자할 만한 가치가 있다. 이 장에서는 독자들이 유닉스 명령줄과 정규표현식에 대한 기초는 갖추고 있다고 가정 하고, 곧바로 여러 가지 도구를 디버깅 작업에 활용하는 기법을 소개한다.
  25. 25. 아이템 22: 유닉스 명령줄 도구로 디버깅 데이터 분석하기 텍스트 형태의 레코드를 가져오고, 선택하고, 처리 하고, 정리하는 유닉스 명령을 이용하여 디버깅 데 이터를 분석한다. 여러 가지 유닉스 명령을 파이프라인으로 조합하는 방식으로 복잡한 분석 작업을 간단히 처리할 수 있 다.
  26. 26. 아이템 23: 명령줄 도구 옵션과 관용 표현 활용하기 grep에서 제공하는 다양한 옵션을 활용하면 탐색 범위를 줄일 수 있다. 프로그램의 에러 메시지를 분석할 때는 표준 에러 를 리다이렉션한다. 로그 파일에 추가되는 내용을 모니터링하고 싶다면 t ail -f 명령을 활용한다.
  27. 27. 아이템 24: 코드 편집기로 디버깅 데이터 탐색하기 철자가 틀린 식별자를 찾을 때는 편집기에서 제공 하는 검색 기능을 활용한다. 차이점이 눈에 띄도록 텍스트 파일을 적절히 수정 한다. 로그 파일을 좀 더 읽기 좋도록 적절히 수정한다.
  28. 28. 아이템 25: 작업 환경 최적화하기 사용하는 도구를 적절히 설정하여 생산성을 향상시 킨다. 여러 호스트에 걸쳐 작업할 때는 디버깅 환경에 대 한 설정 파일을 버전 관리 시스템을 통해 관리한다.
  29. 29. 아이템 26: 버전 관리 시스템으로 버그 원인과 히스토리 추적하기 버전 관리 시스템에 기록된 파일의 변경 내역을 분 석하면 버그가 언제 어떻게 생겼는지 알아낼 수 있 다. 버전 관리 시스템을 활용하여 정상적인 버전과 버 그가 있는 버전을 비교한다.
  30. 30. 아이템 27: 독립적인 프로세스로 구성된 시스템에서 모니터링 도구 사용하기 모니터링 환경을 구축하여 개발하고자 하는 서비스 에 관련된 모든 부분의 상태를 지속적으로 확인한 다. 장애가 발생하는 즉시 알림을 보내도록 설정하면 에러가 나타난 상태에서 디버깅 작업을 수행할 수 있다. 오류 발생 내역을 분석하면 문제의 원인을 정확히 찾아내는 데 도움되는 패턴을 도출할 수 있다.
  31. 31. 4장 디버거 활용법 디버거는 소프트웨어의 실행 과정을 상세하게 분석하기 위한 특수한 용도로 사용하는 도구로, 현존하는 소프트웨어 중에서도 디버거만큼 CPU와 OS로부 터 특별한 기능을 지원받으면서 시스템을 종횡무진하는 것은 없다. 그만큼 디 버거는 전문가들이 인정하는 특별한 가치를 갖고 있다. 하지만 효과적으로 활 용하는 방법을 모르면 디버거가 제공하는 여러 혜택을 제대로 누릴 수 없다. 따라서 이 장에서 설명하는 기술을 꼼꼼히 읽고 적용하기 바란다. 그중에서 현재 자신이 사용하는 언어와 환경에 맞지 않거나 이미 알고 있는 기술은 지 나쳐도 좋다.
  32. 32. 아이템 28: 디버깅 버전으로 컴파일하기 디버깅 정보가 원하는 수준으로 포함되도록 디버깅 옵션을 설정한다. 디버깅할 때 소스 코드와 생성된 코드가 잘 매칭되 게 하려면 코드 최적화 옵션을 끈다.
  33. 33. 아이템 29: 한 단계씩 코드 실행하기 코드를 한 단계씩 실행하는 방식으로 프로그램의 실행 흐름과 상태를 자세히 살펴본다. 건너뛰기 기능을 사용하여 관련 없는 부분은 걸러 내서 디버깅 속도를 높인다. 건너뛰기로 진행하다가 자세히 검토할 부분을 발견 하면 중단점을 지정해서 다시 실행한 뒤, 해당 부분 은 한 단계씩 실행하는 방식으로 문제를 탐색할 영 역을 좁혀나간다.
  34. 34. 아이템 30: 코드와 데이터 중단점 활용하기 코드 중단점을 이용하여 분석하려는 코드 영역을 좁혀나간 다. 관심 없는 부분은 건너뛰도록 중단점을 추가한다. 비정상적으로 종료하는 오류를 디버깅할 때는 예외나 종료 루틴에 중단점을 지정한다. 프로그램이 뻗어버릴 때는 디버거를 통해 프로그램의 실행 을 중단시킨 뒤 문제를 해결한다. 값이 이상하게 변하는 변수를 분석할 때는 데이터 중단점을 활용한다.
  35. 35. 아이템 31: 리버스 디버깅 리버스 디버깅 기능을 잘 익혀둔다.
  36. 36. 아이템 32: 루틴 사이의 호출 흐름 추적하기 프로그램의 스택을 통해 현재 상태를 이해할 수 있 다. 코드에 문제가 발생하면 스택의 내용이 꼬일 수 있 다.
  37. 37. 아이템 33: 변수와 표현식의 값을 분석하여 에러 찾기 주요 표현식의 값을 확인한다. 알고리즘을 실행하는 동안 표현식의 값을 지속적으 로 표시하도록 디버거를 설정한다. 루틴의 지역변수의 값의 추이를 따라가는 방식으로 루틴의 로직을 분석한다. 이해하기 힘든 복잡한 자료 구조에 대해서는 데이 터 시각화 도구를 활용한다.
  38. 38. 아이템 34: 실행 중인 프로세스에 디버거 연동하기 이미 실행 상태에 있는 프로세스에 디버거를 연결 하여 디버깅한다. 자원이 부족한 장치에서 실행되는 애플리케이션을 디버깅할 때는 원격 머신에 디버깅 환경을 구축한 다.
  39. 39. 아이템 35: 코어 덤프 다루기 충돌이 발생하거나 아무 반응 없이 뻗어버린 애플 리케이션을 디버깅할 때 메모리 덤프를 활용한다. 설치된 고객 애플리케이션을 디버깅할 때 충돌 리 포트 시스템을 활용한다.
  40. 40. 아이템 36: 디버깅 도구 조율하기 그래픽 인터페이스를 갖춘 디버거를 사용한다. 히스토리를 저장하고 원하는 키보드 바인딩을 사용 하도록 gdb를 설정한다. 자주 사용하는 명령을 gdb 스크립트에 저장한다. 입력한 명령을 기록해두기 위해 gdb 안에서 프로그 램을 빌드한다.
  41. 41. 아이템 37: 어셈블리 코드와 메모리 값 확인하기 코드의 동작을 제대로 이해하려면 디스어셈블된 기 계어 명령을 살펴보는 것이 좋다. 레지스터 eax나 r0은 함수의 반환 값을 담는 데 사 용된다. 데이터가 저장된 방식을 제대로 이해하려면 내부 표현 방식을 확인해야 한다.
  42. 42. 5장 프로그래밍 기법 개발 과정에서 발생하는 오류는 대부분 자신이 작성하던 소프트웨어의 코드 로부터 나온 것이다. 이러한 오류를 찾기 위한 한 가지 방법은 작성한 코드를 다른 사람이나 도구의 도움을 받아 꼼꼼하게 분석하는 것이다.
  43. 43. 아이템 38: 의심스런 코드를 검토하고 손으로 실행해보기 코드를 작성할 때 흔히 저지르는 실수를 하지 않았는지 살펴본다. 코드가 정확하게 동작하는지 직접 손으로 실행해서 확 인한다. 복잡한 자료구조는 그림으로 쉽게 표현한다. 복잡한 코드를 쉽게 표현할 때는 종이나 화이트보드의 공간을 넉넉히 확보하고 색깔도 적절히 활용한다. 실제 물체를 활용하면 문제에 좀 더 집중할 수 있다.
  44. 44. 아이템 39: 동료 검토하기 자신이 작성한 코드를 고무 오리에게 설명한다. 동료 검토를 비롯한 코드 리뷰 과정을 거친다. 다양한 개체가 엮인 코드에서 발생한 오류를 디버 깅할 때는 역할 놀이 방식을 적용한다.
  45. 45. 아이템 40: 디버깅 기능 추가하기 작성하는 프로그램에 디버그 모드로 진입하는 옵션을 추가한다. 프로그램의 상태를 조작하고, 연산의 수행 과정을 로그 로 남기고, 런타임 복잡도를 줄이고, 사용자 인터페이스 내비게이션 과정을 건너뛰고, 복잡한 자료구조를 화면 에 표시하는 명령을 추가한다. 임베디드 장치나 서버를 디버깅할 수 있도록 명령줄 인 터페이스, 웹 인터페이스, 시리얼 인터페이스 등을 제공 한다. 외부 오류 상황을 재현할 수 있는 디버그 모드 명령을 추가한다.
  46. 46. 아이템 41: 로그 남기기 로그를 남기는 문장을 추가하여 지속적으로 관리할 수 있는 형태의 디버깅 인프라스트럭처를 구축한다 . 로깅 프레임워크를 처음부터 새로 만들지 말고 가 급적 기존에 나와 있는 것을 활용한다. 로그로 남기고 싶은 주제와 세부 사항을 로깅 프레 임워크에서 적절히 설정한다.
  47. 47. 아이템 42: 단위 테스트 사용하기 단위 테스트를 통해 의심 가는 루틴을 검색하여 오 류가 발생한 지점을 정확히 찾아낸다. 단위 테스트 작업의 효율을 높이도록, 적절한 단위 테스팅 프레임워크를 골라서 프로그램에 단위 테스 트를 수행하는 코드를 추가하고, 자동으로 단위 테 스트를 수행하도록 설정한다.
  48. 48. 아이템 43: 어서션 사용하기 단위 테스트에 어서션을 가미하면 오류가 발생한 지점을 더욱 정확히 찾아낼 수 있다. 복잡한 알고리즘을 디버깅할 때 어서션을 활용하여 선행 조건과 불변 속성과 후행 조건을 검사한다. 문서화를 위해 어서션을 사용하면 코드를 이해하기 쉬워지기 때문에 나중에 문제가 발생하여 디버깅하 거나 테스트할 때 도움된다.
  49. 49. 아이템 44: 코드를 바꿔보면서 검증하기 코드에 나온 값이 정확한지 확인하기 위해 다른 값 으로 직접 변경해본다. 어떤 방식으로 코드를 작성해야 할지에 대한 가이 드를 찾을 수 없다면 직접 여러 방법으로 구현해서 비교한다.
  50. 50. 아이템 45: 정상적인 코드와 문제가 발생한 코드의 차이점 줄이기 오류를 발생시킨 요소를 찾으려면 정상 작동하는 예제와 일치할 때까지 코드를 점진적으로 가지치기 하거나, 반대로 정상 작동하는 예제가 오류가 발생 한 코드와 비슷해질 때까지 수정하는 방식으로 진 행한다.
  51. 51. 아이템 46: 의심스런 코드 간소화하기 코드에 존재하는 오류가 더욱 잘 드러나도록, 커다 란 코드 블록 덩어리를 잘 선별하여 가지치기한다. 코드의 실행 상태를 살펴보거나 테스트하기 쉽도록 복잡한 문장이나 함수를 잘게 쪼갠다. 복잡하고 버그가 많은 알고리즘을 좀 더 간결한 알 고리즘으로 대체하는 방법을 찾아본다.
  52. 52. 아이템 47: 의심스런 코드를 다른 언어로 작성해보기 더 이상 오류를 해결하기 힘들 때는 코드에서 발생 할 수 있는 오류를 최대한 줄일 수 있도록 좀 더 표 현력이 뛰어난 언어로 다시 작성해본다. 풍부한 디버깅 기능을 활용할 수 있도록 프로그래 밍 환경을 개선한 뒤 오류가 있는 코드를 여기서 실 행해본다. 제대로 작동하는 대체 구현을 확보했다면 이를 직 접 활용하거나 기존 코드의 오류를 찾아내기 위한 참고용으로 활용한다.
  53. 53. 아이템 48: 의심스런 코드의 가독성과 구조 향상시키기 에러 패턴이 눈에 띄기 쉽도록 코드의 포맷을 일관 성 있게 맞춘다. 잘못 작성되거나 쓸데없이 복잡한 코드 속에 숨어 있는 버그가 드러나도록 코드를 리팩토링한다.
  54. 54. 아이템 49: 버그의 증상이 아닌 원인 고치기 절대로 코드의 증상만 피해가는 방식으로 수정하지 말고 근본 원인을 찾아서 고친다. 특수한 경우에 대한 문제만 해결하지 말고 가능하 면 복잡한 경우의 수를 일반화한다.
  55. 55. 6장 컴파일 시간 기법 소스 코드를 CPU나 JVM과 같은 가상 머신에서 실행할 수 있도록 바이트 형 태로 변환하는 과정을 들여다보면 나중에 프로그램이 실행할 때 발생할 수 있 는 현상과 실행 결과를 예측할 수 있다. 이러한 컴파일 시간 기법을 활용하면 프로그램에 존재하는 오류를 좀 더 쉽게 찾아낼 수 있다.
  56. 56. 아이템 50: 생성된 코드 확인하기 컴파일러에서 생성한 코드를 살펴보면 컴파일 및 실행 시간에 발생한 문제가 소스 코드의 어느 부분 에 관련이 있는지 찾아낼 수 있다. 컴파일러로 생성된 코드를 좀 더 읽기 좋게 표현하 려면 컴파일러에 적절한 옵션을 지정하거나, 특수 한 도구를 사용한다.
  57. 57. 아이템 51: 정적 분석 도구 활용하기 정적 프로그램 분석 도구를 활용하면 컴파일러 경 고 메시지로 찾지 못한 잠재적인 버그를 발견할 수 있다. 프로그램에 존재하는 버그를 분석하기 좋도록 컴파 일러 옵션을 적절히 설정한다. 빌드 과정과 지속적인 통합 과정에 최소한 한 개 이 상의 정적 프로그램 분석 도구를 거치도록 설정한 다.
  58. 58. 아이템 52: 빌드 결과와 실행 동작이 항상 일정하도록 설정하기 소프트웨어를 실행할 때마다 항상 일정한 결과를 생성하게 하려면 빌드 옵션을 적절히 설정한다.
  59. 59. 아이템 53: 라이브러리에서 제공하는 디버깅 및 검사 기능 설정하기 현재 개발 환경의 컴파일러와 라이브러리에서 제공 하는 런타임 디버깅 기능을 찾아서 적극 활용한다. 현재 환경에서 제공되는 런타임 디버깅 기능이 없 다면 이를 제공하는 서드파티 라이브러리를 사용하 도록 설정한다.
  60. 60. 7장 실행 시간 기법 프로그램의 참모습은 실행 시간에 드러난다. 프로그램이 실행하는 동안에는 프로그램의 정확성, CPU 및 메모리 사용량, 사용하는 라이브러리나 운영체제 , 하드웨어에 관련된 버그를 비롯한 다양한 속성을 볼 수 있다. 하지만 이러한 속성은 눈 깜짝할 사이에 나타났다가 사라진다. 프로그램은 1초에 수백만 개 의 명령어가 순식간에 실행되기 때문이다. 그래서 실행 시간에 드러내는 현상 을 포착하는 것은 굉장히 까다롭고 번거롭고 정확하게 잡아내기도 힘들다. 프 로그램의 작동 과정을 실행 시간에 들여다보면서 버그를 찾아내려면 테스트 도구나 모니터링 도구, 로그 기록 도구 등을 활용해야 한다.
  61. 61. 아이템 54: 테스트 케이스를 작성하여 오류 찾기 제대로 작성된 최소한의 테스트 케이스를 통해 오 류가 발생하는 지점과 해결책을 찾을 수 있다. 사용한 테스트 케이스는 단위 테스트나 회귀 테스 트 형태로 소프트웨어에 추가한다.
  62. 62. 아이템 55: 오류가 발생한 즉시 프로그램 중단하기 디버깅 작업을 수행할 때 오류의 징조가 보이자마 자 프로그램을 중단하도록 설정한다.
  63. 63. 아이템 56: 애플리케이션 로그 파일 분석하기 오류가 발생한 애플리케이션의 로그 파일부터 분석 한다. 오류의 원인이 드러날 정도로 애플리케이션 로그 출력의 상세한 정도를 높인다. 해결하려는 문제만 드러나도록 로그 파일의 출력 범위를 설정하거나 로그에 나온 내용을 필터링한다 .
  64. 64. 아이템 57: 시스템 및 프로세스 연산에 대한 프로파일 분석하기 성능에 관련된 문제를 분석할 때는 CPU와 I/O, 메 모리에 대한 사용량과 포화도를 살펴본다. 프로세스의 CPU 및 메모리 사용 현황에 대한 프로 파일을 분석하여 성능에 관련된 문제를 발생하는 코드 영역의 범위를 좁혀나간다.
  65. 65. 아이템 58: 실행 흐름 추적하기 시스템 함수나 라이브러리 호출의 실행 흐름을 추 적하는 도구를 사용하면 소스 코드를 직접 건드리 지 않고도 프로그램의 동작을 관찰할 수 있다. 윈도우 시스템이라면 윈도우 성능 툴킷, 리눅스라 면 SystemTap, macOS나 솔라리스, FreeBSD를 사 용한다면 DTrace 도구의 사용법을 익혀서 이를 활 용한다.
  66. 66. 아이템 59: 동적 프로그램 분석 도구 활용하기 동적 프로그램 분석 도구를 사용하면 코드를 실제 로 실행할 때 발생하는 문제를 찾을 수 있다.
  67. 67. 8장 멀티스레드 코드 디버깅 CPU 제조사는 이제 여러 개의 코어를 장착한 CPU를 만들어서 개발자에게 잘 써보라고 던져주는 수준에 이르렀다. 이러한 멀티코어 CPU를 이용하면 서로 독립적으로 수행되는 여러 개의 스레드를 훨씬 빠르게 실행할 수 있다. 하지 만 이로 인해 멀티스레드를 사용하는 프로그램의 동작을 예측하기 힘들어졌 다. 프로그램을 실행할 때마다 각각의 스레드가 동작하는 순서가 약간씩 달라 져서 디버깅하려는 현상이 일정하게 나타나지 않기 때문이다. 따라서 이 책의 다른 장에서 소개한 기법 중 상당수는 그대로 적용할 수 없다. 다행히 이러한 문제를 해결할 수 있도록 여러 가지 도구와 기술이 나와 있다.
  68. 68. 아이템 60: 사후 디버깅으로 교착 상태 분석하기 교착 상태를 디버깅할 때는 교착 상태에 빠진 시점 의 프로그램 상태(스냅샷)를 구한 뒤, 스레드나 코 드 흐름에서 자원을 기다리는 코드 지점을 찾아낸 다.
  69. 69. 아이템 61: 프로그램의 실행 흐름을 기록한 뒤 재생하기 발생 빈도가 낮은 동시성 오류를 찾을 때는 오류가 발생하는 상황을 기록하고, 그 내용을 분석해서, 기 록된 데이터를 다시 디버거로 재생하는 방식으로 작업한다.
  70. 70. 아이템 62: 전문 도구로 교착 상태와 경쟁 상태 찾기 정적 분석 도구를 이용하여 멀티스레드 프로그램에 존재하는 동기화 및 잠금 관련 에러를 걸러낸다. 동적 분석 도구를 이용하여 멀티스레드 프로그램에 서 API를 잘못 사용하는 부분, 교착 상태나 데이터 경쟁 현상이 발생할 가능성이 있는 부분이 있는지 검사한다.
  71. 71. 아이템 63: 예측할 수 없는 부분을 분리하거나 제거하기 코드에서 동시에 실행되는 부분을 따로 분리한다. 그러면 각 영역에 가장 적합한 디버깅 도구와 기법 을 적용하기 쉽다. 예측하기 힘든 부분을 모의 객체로 분리하거나 예 측할 수 있는 형태로 바꾸는 기법으로 테스팅 및 디 버깅용 환경을 구성한다. 그러면 코드를 반복해서 실행해볼 수 있다.
  72. 72. 아이템 64: 자원 경쟁으로 인해 발생한 성능 확장성 문제 분석하기 멀티스레드 프로그램에서 성능에 대한 확장성 문제 가 발생하면 프로파일링 도구를 이용하여 자원 경 쟁이 발생하는지 확인한다.
  73. 73. 아이템 65: 성능 카운터를 이용하여 거짓 공유 발생 지점 찾기 거짓 공유 문제를 분석하기 위해 성능 카운터를 모 니터링할 때는 프로파일링 도구에서 제공하는 기능 을 활용한다.
  74. 74. 아이템 66: 고수준 추상화를 사용하도록 코드 다시 작성하기 동시성 관련 오류가 발생할 가능성이 높은 부분은 특수한 프로그래밍 언어와 프로세스, 도구, 프레임 워크, 라이브러리에서 제공하는 고수준의 구문을 최대한 활용하도록 새로 작성한다.

×