Node.js로 프로그램을 짜던 중 표준출력을 변경해야 할 필요가 있었다. 여기서 표준 출력이라는 것은 stdout이나 stderr로 출력되는 내용을 말하고 기본적으로는 Node.js에서 console로 출력하고 터미널에 메시지가 출력된다. 이는 console.log()를 사용하면 터미널에 출력된다고 생각하기 쉽지만 좀 더 적확히는 console.log()는 stdout으로 출력되고 console.error()는 stderr로 출력되는 것인데 stdout과 stderr가 터미널로 출력하는 것이다. 물론 일반적으로는 그냥 이 stdout과 stderr을 그대로 사용하고 로거를 따로 사용하거나 shell에서 파이프로 파일에 쓰이도록 하는 것이 더 바람직하다고 본다. 하지만 좀 특별한 용도로 소스내에서 stdout이나 stderr를 가로채서 임의로 조작해야할 필요가 있었다.
__defineGetter__ 사용하기
MDN에 따르면 __defineGetter__는 표준도 아니고 폐기된 API이지만 현재 Node.js에서 사용할 수 있다.(즉, 아직 V8이 지원한다.) 이 특이한 이름의 __defineGetter__는 객체의 프로퍼티를 함수에 바인딩해서 해당 프로퍼티가 조회될 때 바인딩된 함수가 호출되도록 하는데 stdout, stderr를 가로채는 방법을 검색하다 보면 이 방법이 많이 나온다.
앞부분에서 console.log와 console.error로 메시지를 출력하고 __defineGetter__를 이용해서 process 객체의 stdout과 stderr 프로퍼티에 새로운 함수를 바인딩했고 이 함수에서는 위에서 생성한 파일스트림을 각각 리턴하도록 했다. 그리고 마지막에서는 원래의 stdout, stderr로 다시 복구해 주었다.
위의 실행결과에서 보듯이 앞부분에서 출력한 메시지는 js파일 실행시 그대로 출력되었지만 stdout, stderr을 가로챈 뒤에 실행한 뒤에 출력한 console.log과 console.err는 터미널에 출력되는 대신 각각 파일에 출력되었다.
write 함수 오버라이드하기
__defineGetter__를 이용한 방법도 잘 동작하지만 표준이 아닌 __defineGetter__를 사용하는 부분이 약간 찝찝하다. stdout과 stderr 에는 실제 메시지를 출력하는 write 함수가 있는데 이 함수가 실제로 메시지를 출력하는 함수이므로 이 함수를 통째로 가로챌 수 있다.
앞에서 보았던 과정과 비슷하다. 달라진 점은 stdout과 stderr의 write함수를 백업한 뒤에 새로운 함수로 덮어쓰고 나중에 원래의 write함수로 복구해 준 것이다. write함수가 스트림이 아니라서 여기서는 pipe대신에 그냥 문자열을 받아서 파일에 쓰도록 했다.
물론 결과는 앞에와 동일하다.
Outsider님, 생뚱맞은 질문이 있는데요,
포스팅 본문에 주요 키워드들 (stdout, stderr 등...)에만 오렌지색 컬러를 예쁘게 입히셨는데, 저걸 다 수작업으로 하시진 않으셨을 것 같고..
어떤 식으로 컬러링 하신건지 여쭤봐도 될까요?
그리고 아마도 맥에서 포스팅 하셨을 것 같은데.. 포스팅에 사용하시는 별도 툴 같은게 있으시면 그것도 여쭤보고 싶어요~ 알려주세요~
실망시켜드려 죄송하지만 수작업입니다. ㅠㅠ
아주 오래전에는 블로그툴을 찾아본적도 있지만 그닥 맘에 드는게 없어서 그냥 웹에디터에서 주로 작성합니다. 긴 글은 그냥 에디터 혹은 마크다운 에디터에서 내용만 작성후에 블로그에 가져와서 스타일을 적용합니다.
개인적인 마음으로는 마크다운으로 작성하고 자동으로 스타일입히고 싶지만 과거글들도 있고 시간도 여의치 않아서 쉽사리 손을 못대고 있습니다.
와... 엄청난 정성입니다 ㅜㅜ)b
오늘 하늘도 울고 outsider님도 울고 저도 우는군요..ㅜㅜ
좀 귀찮기는 한데 또 습관되서 괜찮습니다. ㅎㅎ