📑 목차
에러는 떴는데, 무엇부터 봐야 원인이 빨리 좁혀지는가
장애가 발생하면 화면에는 “오류가 발생했다” 정도만 보이고, 실제 원인은 로그에 묻혀 있는 경우가 많다.
로그를 열어도 숫자 코드가 잔뜩 나오거나, 스택 트레이스가 길게 이어져서 어디를 읽어야 하는지 막히기 쉽다.
에러 코드와 스택 트레이스는 같은 장애를 다른 각도에서 설명하므로, 순서를 정해 읽으면 시간 낭비를 줄일 수 있다.
- 에러 코드가 알려주는 범위와 단서
- 스택 트레이스에서 “첫 원인”을 찾는 요령
- 둘을 함께 볼 때 원인 후보가 빠르게 줄어드는 이유
- 현장에서 자주 생기는 오해와 함정
- 로그에서 확인하고 재발을 줄이는 점검 절차
에러 코드는 “어떤 종류의 실패인가”를 분류하고, 스택 트레이스는 “어디서 실패했는가”를 가리킨다
핵심 개념 1: 에러 코드는 문제의 성격을 분류하는 표지판이다
정의: 에러 코드는 장애 상황을 일정한 규칙으로 분류하기 위해 부여되는 숫자 또는 문자열 식별자다.
핵심 특징: 코드만으로 정답이 나오지는 않지만, 실패의 범위를 빠르게 줄이는 데 도움이 된다. 예를 들어 HTTP 4xx와 5xx는 “클라이언트 요청 문제”인지 “서버 처리 문제”인지 방향을 갈라 준다.
- 내부 동작 원리: 시스템은 예외·오류가 발생하면 상태를 코드로 치환해 응답 또는 로그에 남긴다. 이때 같은 코드라도 “어느 계층에서 발생했는지”에 따라 의미가 달라질 수 있다.
- 범위: 코드의 범위는 계층별로 다르다. HTTP 상태 코드, 운영체제 오류 번호, 데이터베이스 오류 코드, 애플리케이션 자체 코드가 동시에 등장할 수 있다.
- 제약: 코드가 표준이라고 해도 구현체마다 추가 정보가 다르다. 같은 500이라도 실제 원인은 타임아웃, 예외, 설정 오류 등으로 넓게 퍼질 수 있다.
- 정리 필요성: 코드별로 의미가 문서화되지 않으면 운영자가 같은 문제를 매번 처음부터 추적하게 된다. 자주 발생하는 코드부터 내부 위키나 운영 문서로 정리하는 편이 효율적이다.
주의점: 코드가 “결과”만 말하는 경우가 많다. 504 같은 게이트웨이 타임아웃을 봤다고 해서, 항상 네트워크 문제로 단정하면 오진이 생길 수 있다.
주의점: 코드가 여러 개 섞여 있으면 우선순위를 잡아야 한다. 바깥쪽(프록시/게이트웨이) 코드와 안쪽(애플리케이션/DB) 코드 중 무엇이 먼저인지 타임스탬프와 요청 식별자로 확인해야 한다.

핵심 개념 2: 스택 트레이스는 실패 지점까지의 호출 경로를 기록한 지도다
정의: 스택 트레이스는 오류가 발생했을 때, 그 지점에 도달하기까지 함수(메서드) 호출이 어떤 순서로 쌓였는지를 보여 주는 기록이다.
핵심 특징: “어디서 터졌는가”를 코드 파일·함수·줄 번호로 좁혀 주므로, 수정 포인트를 찾는 데 직접적이다. 특히 같은 에러 코드가 반복될 때 스택 트레이스가 원인 분기를 갈라 준다.
- 내부 동작 원리: 프로그램은 실행 중 함수 호출이 발생할 때마다 호출 스택에 프레임을 쌓는다. 예외가 발생하면 스택의 현재 상태가 문자열 형태로 덤프되어 로그에 남는다.
- 범위: 스택 트레이스는 애플리케이션 내부 경로뿐 아니라 라이브러리, 프레임워크, 런타임 호출까지 포함할 수 있다. 따라서 “내 코드”와 “외부 코드”를 구분해 읽어야 한다.
- 제약: 로그 설정에 따라 스택 트레이스가 생략되거나 잘릴 수 있다. 또한 동일한 오류라도 스레드/비동기 처리 방식에 따라 호출 경로가 달라 보일 수 있다.
- 정리 필요성: 스택 트레이스가 길수록 핵심 프레임을 놓치기 쉽다. 반복 장애는 “자주 보는 프레임 패턴”을 정리해 두면 분석 속도가 올라간다.
주의점: 스택 트레이스의 맨 위가 항상 “진짜 원인”은 아니다. 상위에서 포착한 예외가 아래 원인을 감싸면서 메시지를 바꿀 수 있으므로, 근본 원인(caused by, root cause) 구간을 찾아야 한다.
주의점: 개인정보나 민감한 값이 스택 트레이스·에러 메시지에 섞일 수 있다. 로그에 남기는 메시지는 마스킹 규칙과 접근 권한 관리가 필요하다.
에러 코드는 분류를 빠르게 하고, 스택 트레이스는 수정 지점을 좁히는 역할을 한다.
둘 중 하나만 보면 “방향은 맞는데 디테일이 없는 추적” 또는 “디테일은 있는데 왜 그런지 모르는 추적”이 되기 쉽다.

비교와 선택 기준: 어떤 단서를 먼저 잡으면 낭비가 줄어드는가
장애 대응에서 가장 흔한 낭비는 “아무 로그나 길게 읽는 것”이다. 먼저 기준을 정하면 필요한 로그만 남긴 채 분석이 가능하다.
| 항목 | 에러 코드 | 스택 트레이스 |
|---|---|---|
| 무엇을 알려주는가 | 실패 유형과 범위(분류) | 실패 지점과 호출 경로(위치) |
| 처음 읽기 난이도 | 낮은 편(코드 의미만 알면 됨) | 높은 편(핵심 프레임 선별 필요) |
| 잘못 해석하기 쉬운 지점 | 코드 하나로 원인을 단정하는 실수 | 맨 위 프레임만 보고 결론 내리는 실수 |
| 유용한 상황 | 장애 분류, 대응 우선순위 결정 | 수정 지점 특정, 재발 방지용 근거 확보 |
표 제목: 에러 코드 vs 스택 트레이스 핵심 비교
어떤 상황이면 무엇을 먼저 보는가: YES/NO 체크리스트
- 질문: 사용자에게 즉시 보여지는 오류(HTTP 4xx/5xx 등)인가. YES: 에러 코드로 범위를 먼저 나누고 해당 시간대 로그를 좁힌다. NO: 내부 배치/워커 장애라면 스택 트레이스 중심으로 시작한다.
- 질문: 같은 오류가 대량으로 반복되는가. YES: 에러 코드와 발생 비율로 우선순위를 정한 뒤 대표 샘플의 스택 트레이스를 본다. NO: 단발성이라면 해당 요청의 스택 트레이스로 재현 가능성을 먼저 확인한다.
- 질문: 외부 의존(API, 메시징, 결제 등)이 있는 흐름인가. YES: 타임아웃/권한/제한 관련 코드를 확인하고, 스택 트레이스에서 외부 호출 지점을 찾는다. NO: 내부 로직·데이터 문제 가능성이 높으므로 스택 트레이스의 원인 구간을 우선 본다.
- 질문: 수정 후 검증이 필요한가. YES: 스택 트레이스로 수정 지점을 특정하고, 같은 에러 코드가 줄었는지 지표로 확인한다. NO: 임시 조치만 필요하다면 에러 코드 기반으로 우회·차단 같은 대응이 가능하다.
- 질문: 로그가 너무 길고 노이즈가 많은가. YES: 요청 식별자와 에러 코드로 필터링한 뒤 스택 트레이스를 읽는다. NO: 스택 트레이스부터 읽고 필요한 코드 범위를 정리한다.
실전 예시: “결제 완료 후 주문 생성이 실패”할 때 로그로 원인을 좁히는 순서
문제: 사용자는 결제를 완료했는데 주문 목록에 주문이 생성되지 않았다고 문의한다. 관리자 화면에는 간헐적으로 500 오류가 기록된다.
왜 발생: 결제는 외부 서비스에서 성공했지만, 내부 주문 생성 단계에서 예외가 발생했거나, 결제 결과를 저장하는 과정에서 데이터 제약 조건에 걸렸거나, 외부 결과를 조회하는 요청이 타임아웃으로 끊겼을 수 있다.
어떤 선택이 적합: 먼저 에러 코드로 “실패 유형”을 나눈다. 500 계열이라면 서버 내부 예외 가능성이 크므로, 해당 시간대의 요청 식별자를 기준으로 스택 트레이스를 찾아 “실패 지점”을 고정한다.
잘못 쓰면 어떤 문제: 500만 보고 서버 증설 같은 조치를 먼저 하면, 실제 원인이 데이터 값 누락이나 외부 호출 제한일 때 문제를 해결하지 못한다. 반대로 스택 트레이스만 길게 읽다가 타임스탬프·요청 식별자 매칭을 놓치면 다른 사건의 로그를 붙잡게 된다.
확인/해결: 같은 사건의 로그를 한 묶음으로 모아, 코드(분류)와 트레이스(위치)를 함께 연결한 뒤 수정·검증으로 넘어가는 흐름이 필요하다.
확인하는 방법: 시간대 고정부터 요청 단위로 묶어 읽는다
- 사용자 문의 시각 또는 모니터링 알림 시각을 기준으로 분석 구간을 정한다(예: 10:12~10:20).
- 해당 구간의 서버 로그 또는 로그 수집 도구에서 오류 레벨 로그만 먼저 필터링한다.
- 에러 코드가 있다면 코드로 1차 분류한다(예: 500, 502, 504 또는 애플리케이션 코드).
- 같은 시각대에 반복되는 코드가 있는지 확인하고, 대표 사례 1~2건을 선택한다.
- 대표 사례에서 요청 식별자(요청 ID, 트랜잭션 ID, 코릴레이션 ID)를 찾아 같은 식별자로 이어진 로그를 한 덩어리로 모은다.
- 해당 덩어리에서 스택 트레이스를 찾고, 예외 종류와 원인 구간(caused by 등)을 확인해 실제 실패 지점을 고정한다.
- 실패 지점이 외부 호출이라면 타임아웃·권한·호출 제한 여부를 확인하고, 내부 로직이라면 입력 값·데이터 제약·널 처리 같은 조건을 점검한다.
- 수정 또는 설정 변경 후 같은 에러 코드 발생률이 줄었는지, 동일 흐름에서 재현이 멈췄는지 확인한다.
원인 후보를 빠르게 줄이는 읽기 요령 3가지
첫째, “가장 먼저 나타난 오류”를 찾는 편이 유리하다. 뒤에 나타난 오류는 앞선 실패의 연쇄 결과인 경우가 많다.
둘째, 스택 트레이스에서는 프레임 전체를 읽기보다 “내 코드가 처음 등장하는 지점”과 “원인 구간”을 우선 잡는 편이 효율적이다.
셋째, 같은 코드가 반복될 때는 공통점과 차이점을 동시에 본다. 공통점은 재발 조건이고, 차이점은 분기 조건일 가능성이 높다.
결론
에러 코드는 장애를 분류해 범위를 줄이고, 스택 트레이스는 실패 지점을 특정해 수정 방향을 만든다.
시간대와 요청 식별자로 로그를 묶은 뒤, 코드와 트레이스를 함께 연결하면 분석 속도가 올라간다.
반복 장애는 코드 의미와 트레이스 패턴을 문서로 정리하면 재발 시 대응 시간이 줄어든다.
- 다음에 읽으면 좋은 연계 주제: 로그 레벨과 구조화 로그로 “필터 가능한 로그” 만들기
- 다음에 읽으면 좋은 연계 주제: 알림 임계치와 에러율 지표로 장애를 조기 감지하는 방법
FAQ
에러 코드만으로 원인을 확정해도 되는가
확정하기 어렵다. 에러 코드는 분류에 유리하지만 원인 범위가 넓은 경우가 많다. 같은 코드 안에서 스택 트레이스로 실패 지점을 확인하는 절차가 필요하다.
스택 트레이스가 너무 길 때 어디부터 봐야 하는가
원인 구간(caused by 등)이 있다면 그 부분을 먼저 보고, 그 다음 “내 코드가 처음 등장하는 프레임”을 찾는 편이 효율적이다. 맨 위 프레임만 보고 결론 내리면 오진이 생기기 쉽다.
로그가 없거나 스택 트레이스가 잘려 있으면 어떻게 해야 하는가
로그 보관 기간과 출력 설정을 점검해야 한다. 필요한 오류에서 예외 정보가 빠지는 설정이라면 로그 정책을 조정하고, 요청 식별자와 핵심 필드를 남기는 형태로 개선하는 편이 재발 대응에 도움이 된다.
'전산학' 카테고리의 다른 글
| 스로틀링과 서킷 브레이커: 외부 시스템 장애가 내 서비스까지 망치지 않게 막는 기술 (0) | 2025.12.28 |
|---|---|
| 메시지 큐(Message Queue) 기초: 서비스 간에 일을 안전하게 넘기는 비동기 통신 (0) | 2025.12.27 |
| 배치 처리와 실시간 처리: 한 번에 몰아서 할 것인가, 바로바로 처리할 것인가 (0) | 2025.12.27 |
| 로그기반 복제와 마스터–슬레이브 구조: 전산학 데이터베이스를 안전하게 분산하는 방법 (0) | 2025.12.27 |
| 정규화와 비정규화: 데이터 중복을 줄이면서도 성능을 지키는 테이블 설계 (0) | 2025.12.26 |