[PY-007][중급] 예외를 나누고 필요한 로그 남기기 > IT 기술 공유

본문 바로가기
사이트 내 전체검색

IT 기술 공유

[PY-007][중급] 예외를 나누고 필요한 로그 남기기

페이지 정보

profile_image
작성자 기술팀장
댓글 0건 조회 151회 작성일 26-09-02 11:35

본문

[이번 수업]
실행 중 문제를 무조건 숨기거나 프로그램을 바로 끝내면 원인을 찾기 어렵습니다. 이번에는 Python 예외를 처리 가능한 문제와 예상 밖 문제로 나누고, 필요한 사건만 알맞은 수준으로 기록합니다.

[선수지식]
PY-004의 함수, PY-006의 파일·데이터 처리와 TOOL-007의 실행 흐름 관찰을 알고 Python 파일을 실행할 수 있어야 합니다.

[학습목표]
1. `try`, `except`, `else`, `finally`의 실행 조건을 설명한다.
2. 처리할 수 있는 구체적인 예외만 선택한다.
3. DEBUG·INFO·WARNING·ERROR 로그 수준을 상황에 맞게 고른다.

[핵심개념]
예외(exception)는 문법은 맞지만 실행 중 작업을 완료할 수 없을 때 전달되는 객체입니다. `try`에는 실패할 수 있는 최소 코드만 넣습니다. `except`는 처리할 예외 형식을 고르고, `else`는 예외가 없을 때만 실행됩니다. `finally`는 성공 여부와 관계없이 마지막에 실행되어 자원 정리에 알맞습니다. 파일처럼 정리 규칙이 있는 자원은 가능하면 `with` 문을 우선 사용합니다.

모든 문제를 `except Exception:`으로 잡고 지나가면 프로그래밍 오류까지 숨길 수 있습니다. 숫자 대신 문자가 들어오는 상황처럼 복구 방법이 분명할 때 `ValueError`를 처리하세요. 처리할 수 없는 예외는 다시 `raise`하거나 상위 계층에 전달합니다. 여러 계층에서 같은 예외를 반복 기록하지 않도록 처리와 기록의 책임도 정합니다.

로깅(logging)은 실행 중 사건을 기록하는 일입니다. DEBUG는 상세 진단, INFO는 정상 진행의 중요한 사건, WARNING은 계속 실행할 수 있지만 살펴볼 상황, ERROR는 작업 실패에 사용합니다. 사용자 안내는 화면 메시지이고 조사 기록은 로거의 역할입니다. 예외 처리는 흐름을 결정하고 로그는 사실을 남기므로 서로 대신할 수 없습니다.

[따라하기]
아래 내용을 exception_demo.py로 저장합니다. 원본 입력값은 기록하지 않고 예외 형식만 남깁니다.

```python
import logging
import sys

logging.basicConfig(
    level=logging.INFO,
    format="%(levelname)s:%(message)s",
    stream=sys.stdout,
)
logger = logging.getLogger(__name__)

def parse_quantity(text):
    try:
        quantity = int(text)
        if quantity < 1:
            raise ValueError("수량은 1 이상이어야 합니다")
    except (TypeError, ValueError) as error:
        logger.warning("수량 입력 거부: %s", type(error).__name__)
        return None
    else:
        logger.info("수량 확인 완료")
        return quantity
    finally:
        logger.debug("수량 검사 종료")

for raw in ["3", "0", "세 개"]:
    print(f"{raw!r} -> {parse_quantity(raw)}")
```

macOS·Linux에서는 `python3 exception_demo.py`, Windows PowerShell에서는 보통 `python exception_demo.py`로 실행합니다. 예상 결과는 다음과 같습니다.

```text
INFO:수량 확인 완료
'3' -> 3
WARNING:수량 입력 거부: ValueError
'0' -> None
WARNING:수량 입력 거부: ValueError
'세 개' -> None
```

`int()` 변환과 범위 검증에서 생기는 `TypeError`, `ValueError`만 처리했습니다. 정상 입력은 `else`, 모든 입력은 `finally`를 거칩니다. 현재 수준이 INFO라 DEBUG 메시지는 보이지 않습니다. `level=logging.DEBUG`로 바꾸면 각 검사 종료도 출력됩니다. 로그 함수의 `%s` 자리표시자는 메시지와 값을 분리해 전달합니다.

[흔한 실수]
- `except:` 뒤에 `pass`만 써서 실패를 성공처럼 보이게 한다.
- `try` 범위를 크게 잡아 관계없는 코드의 예외까지 같은 문제로 처리한다.
- 같은 예외를 여러 계층에서 중복 기록한다.
- 모든 사건을 ERROR로 기록해 장애와 평범한 입력 오류를 섞는다.

[보안 주의]
비밀번호, 접근 토큰, 세션 식별자, 개인정보, 전체 요청 본문을 로그에 남기지 마세요. 외부 입력을 기록해야 한다면 줄바꿈 같은 제어 문자를 정리하고 길이를 제한해 로그 위조와 과다 기록을 막습니다. 로그 파일은 최소 권한으로 보호하고 크기 제한과 순환 정책을 둡니다. 본인 소유의 로컬 환경과 가짜 입력만 사용합니다.

[직접 해볼 과제]
입력 목록에 `None`과 `"7"`을 추가하고 로그를 예측하세요. 로그 수준을 DEBUG로 바꾸어 `finally`가 다섯 입력 모두에서 실행되는지도 확인합니다.

[확인문제]
1. 성공했을 때만 실행할 코드는 어느 절에 두나요?
2. 모든 예외를 무조건 잡고 지나가면 왜 위험한가요?
3. 사용자 안내 메시지와 조사용 로그는 어떤 차이가 있나요?

[다음 학습]
다음 JSTS-007에서는 TypeScript 타입 시스템으로 잘못된 값의 일부를 실행 전에 발견합니다.

[공식 참고 자료]
- Python 오류와 예외: https://docs.python.org/3/tutorial/errors.html
- Python 로깅 사용법: https://docs.python.org/3/howto/logging.html
- OWASP 로깅 보안 지침: https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html

댓글목록

등록된 댓글이 없습니다.

회원로그인

회원가입

사이트 정보

회사명 : 회사명 / 대표 : 대표자명
주소 : OO도 OO시 OO구 OO동 123-45
사업자 등록번호 : 123-45-67890
전화 : 02-123-4567 팩스 : 02-123-4568
통신판매업신고번호 : 제 OO구 - 123호
개인정보관리책임자 : 정보책임자명

접속자집계

오늘
4,801
어제
6,862
최대
16,772
전체
770,752
Copyright © 소유하신 도메인. All rights reserved.