FrontEnd/React

[FrontEnd/React] 리액트에서 개발 로그 만들기

수빈2022 2024. 5. 13. 21:54

들어가기 앞서..

 

로그 레벨을 분리해서 관리하는 게 익숙하지 않아, 생각없이 로그를 지워가면서 개발을 진행하고 있었습니다. 문득, 나중에 다시 코드에 로그를 추가해 가면서 추적할 생각을 하니 암담하더군요. 개발 로그가 왜 필요한지 몸으로 깨우쳤습니다.

 

이번 포스팅은 리액트에서 어떻게 개발 로그를 만드는지를 다루면서 개발 로그에 대한 중요성을 잊지 않고자 작성한 내용입니다.

 

제가 이해한 대로 정리한 거라 틀린 게 있다면 댓글로 피드백 부탁드립니다. :)


목차


    1. 개발 로그의 필요성

    1.1. 로그의 필요성

    로그는 어디에서 어떤 이유로 문제가 발생하여 프로그램에 장애/이슈 등이 발생했는지 파악하기 위해 꼭 필요합니다. 로그가 없다면 모든 소스 코드를 전부 읽어야 되기 때문입니다.

     

    잘 만들어진 로그는 문제를 빠르고 편하게 추적할 수 있게 만들어 줍니다.

    1.2. 운영 환경에서 console.log()의 문제

    일반적으로 자바스크립트에서 로그는 Console.log()를 이용하지만 이 함수는 환경과 관계 없이 콘솔에 로그를 출력하기 때문에, 배포하기 전에 모두 지워주어야 합니다. 그러면 운영 도중 문제가 발생하면 어떻게 해결해야 될까요? 새로운 로그를 만들고, 테스트하고, 배포 전에 로그 코드 다 지워주는 걸 매번 반복해야 될까요?

     

    그래서 운영할 환경과 개발하는 환경에서의 로그를 분리시켜 주어야 합니다.

    1.3. 환경 별로 로그를 분리했을 때의 장점

    개발 로그 함수를 만들어 이용한다면, 프로덕션 환경에서는 불필요한 로그를 피하고, 개발 환경에서는 디버깅 및 개발을 용이하게 할 수 있습니다. 또한, 실제 프로덕션 환경(운영 환경)에서는 로그를 서버에 기록하는 등의 방법을 사용하여 중요한 정보를 안전하게 보관할 수도 있습니다.

     

    아래 사진은, 로그를 개발 수준(Level)으로 관리하고 있는 환경입니다. 동일한 동작을 하더라도 한쪽은 로그가 전혀 남지 않는 모습입니다.

    개발 환경에서 다양한 로그가 찍히고 있는 모습
    프로덕션 환경에서는 에러 로그가 보이지 않는 모습


    2. 개발 로그 작성하기

    2.1. 개요

    자바스크립트의 콘솔에 출력되는 정보를 개발 로그로 남기기 위해 console.log(), console.error() 대신 개발 로그에 사용할 함수를 만들어서 사용해야 됩니다.

     

    아래 예시코드는 console.error()를 대체할 개발 로그에 대한 내용입니다. 전체 코드는 포스팅 맨 아래 적어두었습니다.

    2.2. 예시 코드와 동작 원리

    구현 방법

     

    에러에 대한 개발 로그

    JS의 console.error()를 활용했지만 조건문을 추가한 덕분에, 개발 환경에서만 콘솔에 로그가 출력되고, 프로덕션 환경에서는 아무런 동작도 하지 않습니다.

     

    조건문에 사용된 process.env.NODE_ENV 값은 개발 환경과 프로덕션 환경을 구분하기 위해 사용하는 값입니다.

    동작 원리

    Node.js 환경에서 제공하는 process.env를 통해서 NODE_ENV 값을 'development'와 동일한지 비교하는 코드입니다. Node.js는 process.env라는 내장 자바스크립트 객체를 사용해서 환경 변수에 접근할 수 있습니다. 그러므로 errMsg() 함수가 제대로 동작하기 위해선 NODE_ENV라는 이름의 환경 변수를 직접 설정해 주어야 됩니다.


    3. NODE_ENV을 환경 변수로 등록하기

    환경 변수를 등록하는 방법은 2가지가 있습니다. 환경 변수 파일을 만들어서 NODE_ENV를 관리하거나, 스크립트가 실행될 때마다 NODE_ENV값을 등록되도록 package.json에 인라인으로 작성하는 방법이 있습니다. 

    3.1. 환경 변수 파일로 환경 변수 관리하기

    구현 방법

    1) 패키지 관리자를 이용해 dotenv 모듈을 설치합니다.
    2) .env 파일에 NODE_ENV 변수와 값을 추가해 줍니다.
    3) require('dotenv').config()로 환경 변수를 전부 로드합니다.
    4) process.env를 통해 NODE_ENV를 접근합니다.

     

    저는 사용하는 환경 변수가 NODE_ENV 외에는 없기 때문에, 파일 관리하는 게 싫어서 직접 해 보지는 않았습니다. 예시 코드는 아래의 '컴공 K'님의 포시팅을 참고해 주세요.

    [Node.js] 환경 변수(env) 관리하기 (tistory.com)

    동작 원리

    dotenv 모듈은 Node.js에서 환경 변수를 파일 기반으로 관리하기 위한 모듈입니다. dotenv 모듈은 .env 파일을 통해 환경 변수를 간단하게 관리할 수 있습니다.

    더보기

    🗨️ dotenv과 같은 모듈은 또 뭐가 있나요?

    dotenv 모듈과 같이 환경 변수를 파일로 관리하는 걸로는, config 모듈과 cross-env 모듈 등이 있습니다.

    • config 모듈은 config 파일을 통해서 환경 변수와 설정을 관리하기 위해 사용되며 개발자들에게 가장 친숙한 파일입니다. config 파일은 JSON, XML, JavaScript, 등 다양한 형식의 설정 파일을 관리할 수 있습니다
    • cross-env 모듈도 마찬가지로 환경 변수를 설정합니다. dotenv과 다르게 MacOS, Windows, Linux, Unix 등의 서로 다른 운영 체제 간의 환경 변수 설정의 일관성을 갖기 위해 사용합니다.

    Node.js에서 제공하는 process 객체는, Node.js의 프로세스에 대한 정보에 접근하고 제어할 수 있는 다양한 함수를 포함합니다. process 객체는 전역 객체라서 require() 없이 어디서든 불러올 수 있습니다. 하지만 .env 파일은 개발자가 직접 추가한 파일이므로 환경 변수를 사용하려는 파일에서 require()로 환경 변수를 불러와야 process 객체가 접근할 수 있습니다.

     

    require() 함수에 대한 내용이 궁금하시다면, 'Song-YunMin' 님의 포스팅을 참고해 주세요.

    [Javascript] require() 간단 동작 원리 및 module.export 와 export의 차이 (velog.io)

    3.2. package.json에서 인라인으로 환경 변수 추가하기

    구현 방법

    package.json에서 스크립트의 start 부분을 아래처럼 수정한 뒤, 일반적인 함수를 이용하는 것처럼 위에서 만든 함수를 import 해서 사용하시면 됩니다. 사진을 참고해 주세요.

    // package.json
    ...
    "start": "set NODE_ENV=development && react-scripts start",
    ...

    package.json 수정

    (좌) package.json 파일 수정 전 (우) 개발 서버가 가동될 때 NODE_ENV 환경 변수가 등록되도록 인라인으로 추가

    함수 호출

    개발 에러 로그 함수를 import해서 사용하는 간단한 구조

    실행 결과

    로컬에서 에러 로그가 출력되고 있는 모습
    build하여 배포한 서버에서는 에러 로그가 보이지 않는 모습

    동작 원리

    예시로 든 프로젝트는 npm에 의해 package.json이 관리되고 있습니다. 그래서 npm start 스크립트를 수정해서 Node.js가 개발 서버를 실행시키기 전, 환경 변수를 등록하도록 스크립트를 수정했습니다.

    1) package.json에는 npm에서 사용할 수 있는 스크립트 명령어로, "start"가 정의되어져 있습니다.
    2) react-scripts start는 리액트 서버를 실행시키는 스크립트로, 로컬에 server.js로 실행할 경우 node server.js를 정의하시면 됩니다.
    3) 따라서, npm start를 입력하면 NODE_ENV 환경변수에 "development" 값이 등록된 후, 리액트가 개발 서버를 가동하게 됩니다.
    더보기

    🗨️ 로컬 서버와 개발 서버는 뭐가 다른가요?

    사용 목적과 실행 위치에 따라 서버 분류를 나눈 것 뿐입니다.

    • 로컬 서버는 개인용 컴퓨터에 설치되어, 해당 컴퓨터에서만 접근할 수 있는 서버를 말합니다. 보통 localhost:[포트번호]로 실행되는 것들이 로컬 서버입니다.
    • 개발 서버는 개발을 위한 서버로, 운영 환경의 다양한 상황이 배제된 개발을 위한 서버를 말합니다. 보통 서버는 개발 서버, 테스트 서버, 운영 서버로 나누어 부릅니다. 운영 서버는 실제 운영 환경에서 사용하는 서버를 말하고, 테스트 서버는 운영 서버와 거의 유사하게 구성된 서버를 말합니다. 개발 서버는 개발만을 위한 서버로, 운영 환경과는 많이 다를 수 있습니다.

    NODE_ENV 는 노드의 환경 변수라는 의미로 만들었습니다. 이 이름을 많은 개발자들이 사용하는 환경 변수명인지는 모르겠지만 보통 개발 환경은 'development' 또는 'dev'로 설정하고, 프로덕션 환경에서는 'production', 'prod'로 설정합니다. NODE_ENV 값을 설정함으로써 코드에서는 해당 환경에 따라 다른 동작을 할 수 있습니다.


    4. 개발 로그 예시 코드

    // devLog.js
    /** ******************************************************
     * 파일명   : devLog
     * 파일설명 : 개발 환경에서만 콘솔 로그 출력 함수
     ****************************************************** */
    
    /** ******************************************************
     * 함수명   : msg
     * 함수설명 : 로그 출력
     * 
     * @param {string} ...messages - 콘솔에 출력할 메시지들
     ****************************************************** */
    function msg(...messages) {
      if (process.env.NODE_ENV === 'development') {
        console.log(...messages);
      }
    }
    /** ******************************************************
     * 함수명   : errMsg
     * 함수설명 : 에러 로그 출력
     * 
     * @param {string} message
     * @param {Error | unknown} error
     ****************************************************** */
    function errMsg(message, error) {
      if (process.env.NODE_ENV === 'development') {
        console.error(message, error);
      }
    }
    
    export default {
      msg,
      errMsg,
    }

     

    JS의 try-catch에서 넘어오는 Exception은 unknow 타입입니다. 그래서 devLog.js를 .tsx에서 이용하기 위해선 JSDoc에 unknow 타입도 지정해 주어야 됩니다.

    JSDoc에 unknown 타입을 지정하지 않을 경우 .tsx 파일의 try-catch문에서 오류 발생


    감사합니다. :)