본문 바로가기

Studying/Python

9. logging(로깅) - (1)

python을 공부하면서 생소한 logging에 대한 개념이 등장했다. 

 

얼핏 봤을 땐, 'print문을 대체하는 방법인가?' 라고 생각을 했지만 구글링을 하면 할수록, 더 많은 내용을 담고 있다는 것을 알았고 제대로 공부하면 좋겠다고 생각했다. 

 

그렇다면 logging에 대해 공부해보자.


우리는 보통 코드를 작성할 때, 어느 부분에서 오류가 발생했는지 확인하기 위해 알림 또는 책갈피를 작성하곤한다. 

 

이를 logging(로깅)이라 한다. 

 

로깅은 현재 프로그램이 어떤 상태를 가지고 있는지 외부출력을 하게 만들어서 개발자가 눈으로 직접 확인하는 것이다. 

 

보통 우리는 아래와 같이 print 문을 통해 콘솔로 출력하는 방식을 편하게 사용한다. 

 

예) print("get method called.")
     print("여기서 오류 발생")

 

이렇게 되면 코드의 양이 방대하게 증가하고, 문제가 발생했을 때 로깅 시간이 너무 많이 걸리는 불편함이 발생하고,

 

다양한 방식으로 로깅을 할 수 없다. 

 

그럴 떄 우리는 logging 모듈을 사용할 수 있다. 

 

logging 모듈은 기본 라이브러리에 포함되어 있기 때문에, 설치하지 않고, import해오기만 하면 된다. 

 

여기서 log level(로그 레벨)에 대해 간단히 알고 넘어가자. 

 

로그는 그 중요도에 따라 서로 다른 레벨을 가지게 되고, 이 중요도에 따라 로그를 관리할 수 있다. 

 

level value when to use
DEBUG 10 (주로 문제 해결을 할 때 필요한)자세한 정보
INFO 20 작업이 정상적으로 작동하고 있다는 확인 메세지
WARNING 30 예상하지 못한 일이 발생하거나, 발생 가능한 문제점을 명시(작업은 정상적으로 진행)
ERROR 40 프로그램이 함수를 실행하지 못 할 정도의 심각한 문제
CRITICAL 50 프로그램이 동작할 수 없을 정도의 심각한 문제

 

만약, 모든 로깅이 level 구분없이 출력된다면, 수많은 정보를 출력하게 되어 프로그램 성능에 부담이 갈 것이다. 

 

따라서 설정을 통해 level로 구분을 지어, 출력의 제한선을 정하고 그 윗 단계를 출력하도록 정했다. 

 

python에서 기본으로 설정된 로그 레벨은 'WARNING'이다. 

 

즉, 'WARNING' 단계보다 높은 'ERROR'과 'CRITICAL' 이 출력이 되고, 낮은 레벨인 'DEBUG'와 'INFO'는 출력되지 않는다.

 

이제 여기서 로깅을 실질적으로 사용하는 방법을 살펴보자. 

 

위 그림은 가장 기본적인 로깅 모듈 활용 방법 전체를 나타낸 것이다. 

 

단순히 logging.error("ERROR!!") 라는 식으로 error 함수를 직접 호출해서 사용할 수도 있지만,

 

특정 로거를 만들어 사용하는 것이 보편적이다. 

 

먼저 내가 만들 로거의 이름과 레벨을 설정한다. 

 

logging.getLogger( )에 사용할 이름을 str로 넣는데, 기본값은 root logger이다. 

 

root logger는 모든 logger의 부모와 같은 존재로, 다른 모든 logger는 설정을 변화시키지 않으며, root logger의 자식이다. root logger를 바로 사용할 수도 있지만 기능과 목적에 따라 다른 logger들을 생성하는 것이 낫다.

- 다음 게시물에서 다뤄보자

 

레벨 설정단계에서 INFO 자리에 출력할 내용을 생각하여 설정하면 된다. 

 

저렇게 레벨을 설정하기만 하면 오직 콘솔에서만 출력할 수 있기 때문에 이를 handler를 통해 설정해준다. 

 

handler(핸들러)는 로그 메세지를 지정한 위치에 전달(dispatch)하는 역할을 수행한다.

 

addHandler 메소드를 통해 어떤 핸들러를 추가할 수 있다. 

 

핸들러의 종류는 15개 정도가 있는데 가장 대표적인 것은 StreamHandler와 FileHandler이다. 

 

이는 각각 stream(콘솔) 과 file(파일)에 메시지를 전달하는 역할을 한다. 

 

이렇게 핸들러를 설정하면, 출력 방법을 설정해야한다. 

 

출력 방법을 설정하는 것을 fomatter라 한다. 

 

formatter에서 사용하는 속성들은 여러가지가 있지만 대표적인 것은 위 4개이다. 

 

위의 속성과 그 외의 값은 아래 표를 참고하자. 

 

속성 format 설명
asctime %(asctime)s 인간이 읽을 수 있는 시간 표시
created %(created)f logRecord가 만들어진 시간
filename %(filename)s pathname의 file 이름 부분
funcName %(funcName)s logging call을 포함하는 function 이름
levelname %levelname)s 메세지의 Text logging level
lineno %(lineno)d logging call이 발생한 코드의 line 숫자
module %(module)s filename의 모듈 이름 부분
message %(message)s 메세지
name %(name)s logger의 이름

formatter의 속성을 설정했으면 이를 핸들러에 추가해주는 것도 잊지말자. 

 

이제 로깅할 내용을 info 레벨로 출력해보자. 

 

결과 화면은 아래와 같다. 

 

자, 여기까지가 기본적인 로깅 구현에 대한 방법이다. 

 

다음 게시물에서 로거에 대한 좀더 깊은 이야기를 해보자.