로컬 개발에 HTTPS 사용

대부분의 경우 http://localhost는 개발 목적으로 HTTPS처럼 작동합니다. 하지만 커스텀 호스트 이름이나 브라우저 간 보안 쿠키 사용과 같은 일부 특수한 경우에는 프로덕션에서 사이트가 작동하는 방식을 정확하게 나타내기 위해 개발 사이트가 HTTPS처럼 작동하도록 명시적으로 설정해야 합니다. 프로덕션 웹사이트에서 HTTPS를 사용하지 않는 경우 HTTPS로 전환하는 것을 우선순위로 삼으세요.

이 페이지에서는 HTTPS를 사용하여 로컬에서 사이트를 실행하는 방법을 설명합니다.

간단한 안내는 mkcert 빠른 참조를 참고하세요.**

mkcert를 사용하여 HTTPS로 로컬에서 사이트 실행 (권장)

로컬 개발 사이트에서 HTTPS를 사용하고 https://localhost 또는 https://mysite.example(커스텀 호스트 이름)에 액세스하려면 기기와 브라우저가 신뢰하는 항목(신뢰할 수 있는 인증 기관(CA)이라고 함)에서 서명한 TLS 인증서가 필요합니다. 브라우저는 HTTPS 연결을 만들기 전에 개발 서버의 인증서가 신뢰할 수 있는 CA에 의해 서명되었는지 확인합니다.

교차 플랫폼 CA인 mkcert를 사용하여 인증서를 만들고 서명하는 것이 좋습니다. 다른 유용한 옵션은 HTTPS를 사용하여 로컬에서 사이트 실행: 기타 옵션을 참고하세요.

많은 운영체제에는 인증서를 만들기 위한 라이브러리(예: openssl)가 포함되어 있습니다. 하지만 mkcert보다 복잡하고 안정성이 떨어지며 크로스 플랫폼이 아니므로 대규모 개발자팀에서 액세스하기가 더 어렵습니다.

설정

  1. mkcert를 설치합니다 (한 번만).

    안내에 따라 운영체제에 mkcert를 설치합니다. 예를 들어 macOS에서는 다음과 같습니다.

    brew install mkcert
    brew install nss # if you use Firefox
    
  2. 로컬 루트 CA에 mkcert를 추가합니다.

    터미널에서 다음 명령어를 실행합니다.

    mkcert -install
    

    이렇게 하면 로컬 인증 기관 (CA)이 생성됩니다. mkcert로 생성된 로컬 CA는 기기에서 로컬로만 신뢰됩니다.

  3. mkcert에서 서명한 사이트의 인증서를 생성합니다.

    터미널에서 사이트의 루트 디렉터리 또는 인증서를 보관할 디렉터리로 이동합니다.

    그런 후 다음을 실행합니다.

    mkcert localhost
    

    mysite.example과 같은 커스텀 호스트 이름을 사용하는 경우 다음을 실행합니다.

    mkcert mysite.example
    

    이 명령어는 다음 두 가지 작업을 수행합니다.

    • 지정한 호스트 이름의 인증서를 생성합니다.
    • mkcert가 인증서에 서명하도록 허용합니다.

    이제 인증서가 준비되었으며 브라우저가 로컬에서 신뢰하는 인증 기관에서 서명했습니다.

  4. 방금 만든 TLS 인증서 HTTPS를 사용하도록 서버를 구성합니다.

    자세한 방법은 서버에 따라 다릅니다. 몇 가지 예를 들면 다음과 같습니다.

    👩🏻‍💻 노드 사용:

    server.js({PATH/TO/CERTIFICATE...} 및 {PORT} 대체):

    const https = require('https');
    const fs = require('fs');
    const options = {
      key: fs.readFileSync('{PATH/TO/CERTIFICATE-KEY-FILENAME}.pem'),
      cert: fs.readFileSync('{PATH/TO/CERTIFICATE-FILENAME}.pem'),
    };
    https
      .createServer(options, function (req, res) {
        // server code
      })
      .listen({PORT});
    

    👩🏻‍💻 http-server 사용:

    다음과 같이 서버를 시작합니다({PATH/TO/CERTIFICATE...} 대체).

    http-server -S -C {PATH/TO/CERTIFICATE-FILENAME}.pem -K {PATH/TO/CERTIFICATE-KEY-FILENAME}.pem
    

    -S는 HTTPS로 서버를 실행하고, -C는 인증서를 설정하고, -K는 키를 설정합니다.

    👩🏻‍💻 React 개발 서버 사용:

    다음과 같이 package.json를 수정하고 {PATH/TO/CERTIFICATE...}를 바꿉니다.

    "scripts": {
    "start": "HTTPS=true SSL_CRT_FILE={PATH/TO/CERTIFICATE-FILENAME}.pem SSL_KEY_FILE={PATH/TO/CERTIFICATE-KEY-FILENAME}.pem react-scripts start"
    

    예를 들어 사이트의 루트 디렉터리에 localhost의 인증서를 만든 경우 다음을 실행합니다.

    |-- my-react-app
        |-- package.json
        |-- localhost.pem
        |-- localhost-key.pem
        |--...
    

    그러면 start 스크립트가 다음과 같이 표시됩니다.

    "scripts": {
        "start": "HTTPS=true SSL_CRT_FILE=localhost.pem SSL_KEY_FILE=localhost-key.pem react-scripts start"
    

    👩🏻‍💻 기타 예시:

  5. 브라우저에서 https://localhost 또는 https://mysite.example을 열어 HTTPS를 사용하여 로컬에서 사이트를 실행하고 있는지 다시 확인합니다. 브라우저가 mkcert를 로컬 인증 기관으로 신뢰하므로 브라우저 경고가 표시되지 않습니다.

mkcert 빠른 참조

mkcert 빠른 참조

HTTPS로 로컬 개발 사이트를 실행하려면 다음 단계를 따르세요.

  1. mkcert를 설정합니다.

    아직 설치하지 않았다면 mkcert를 설치합니다(예: macOS).

    brew install mkcert

    Windows 및 Linux 안내는 mkcert 설치를 참고하세요.

    그런 다음 로컬 인증 기관을 만듭니다.

    mkcert -install
  2. 신뢰할 수 있는 인증서를 만듭니다.

    mkcert {YOUR HOSTNAME e.g. localhost or mysite.example}

    이렇게 하면 mkcert가 자동으로 서명하는 유효한 인증서가 생성됩니다.

  3. HTTPS 및 2단계에서 만든 인증서를 사용하도록 개발 서버를 구성합니다.

이제 경고 없이 브라우저에서 https://{YOUR HOSTNAME}에 액세스할 수 있습니다.

</div>

HTTPS를 사용하여 로컬에서 사이트 실행: 기타 옵션

다음은 인증서를 설정하는 다른 방법입니다. 이러한 방법은 일반적으로 mkcert를 사용하는 것보다 더 복잡하거나 위험합니다.

자체 서명 인증서

mkcert와 같은 로컬 인증 기관을 사용하지 않고 대신 인증서에 직접 서명할 수도 있습니다. 이 방식에는 몇 가지 단점이 있습니다.

  • 브라우저는 사용자를 인증 기관으로 신뢰하지 않으므로 수동으로 우회해야 하는 경고를 표시합니다. Chrome에서 #allow-insecure-localhost 플래그를 사용하여 localhost에서 이 경고를 자동으로 우회할 수 있습니다.
  • 안전하지 않은 네트워크에서 작업하는 경우 이는 안전하지 않습니다.
  • mkcert와 같은 로컬 CA를 사용하는 것보다 반드시 더 쉽거나 빠르지는 않습니다.
  • 자체 서명 인증서는 신뢰할 수 있는 인증서와 정확히 동일한 방식으로 작동하지 않습니다.
  • 브라우저 컨텍스트에서 이 기법을 사용하지 않는 경우 서버의 인증서 확인을 사용 중지해야 합니다. 프로덕션에서 다시 사용 설정하는 것을 잊으면 보안 문제가 발생합니다.
자체 서명 인증서를 사용할 때 브라우저에 표시되는 경고의 스크린샷
자체 서명 인증서를 사용할 때 브라우저에 표시되는 경고

인증서를 지정하지 않으면 React 및 Vue 개발 서버 HTTPS 옵션이 내부적으로 자체 서명 인증서를 만듭니다. 이 방법은 빠르지만 자체 서명 인증서의 다른 문제와 동일한 브라우저 경고가 표시됩니다. 다행히 프런트엔드 프레임워크의 기본 제공 HTTPS 옵션을 사용하고 mkcert 등을 사용하여 만든 로컬에서 신뢰할 수 있는 인증서를 지정할 수 있습니다. 자세한 내용은 React를 사용한 mkcert 예를 참고하세요.

브라우저에서 자체 서명 인증서를 신뢰하지 않는 이유는 무엇인가요?

HTTPS를 사용하여 브라우저에서 로컬로 실행 중인 사이트를 열면 브라우저가 로컬 개발 서버의 인증서를 확인합니다. 인증서에 직접 서명한 것을 확인하면 신뢰할 수 있는 인증 기관으로 등록되어 있는지 확인합니다. 그렇지 않기 때문에 브라우저에서 인증서를 신뢰할 수 없으며 연결이 안전하지 않다는 경고가 표시됩니다. 계속 진행하면 HTTPS 연결이 생성되지만, 이로 인한 위험은 사용자가 감수해야 합니다.

브라우저가 자체 서명 인증서를 신뢰하지 않는 이유를 보여주는 다이어그램
브라우저가 자체 서명 인증서를 신뢰하지 않는 이유

일반 인증 기관에서 서명한 인증서

공식 CA에서 서명한 인증서를 사용할 수도 있습니다. 이로 인해 다음과 같은 문제가 발생합니다.

  • mkcert와 같은 로컬 CA 기술을 사용할 때보다 설정 작업이 더 많습니다.
  • 관리하는 유효한 도메인 이름을 사용해야 합니다. 즉, 다음에는 공식 CA를 사용할 수 없습니다.
    • localhost 및 기타 예약된 도메인 이름(예: example 또는 test)
    • 내가 관리하지 않는 도메인 이름
    • 최상위 도메인이 잘못되었습니다. 자세한 내용은 유효한 최상위 도메인 목록을 참고하세요.

리버스 프록시

HTTPS를 사용하여 로컬에서 실행되는 사이트에 액세스하는 또 다른 옵션은 ngrok과 같은 리버스 프록시를 사용하는 것입니다. 이 방식에는 다음과 같은 위험이 있습니다.

  • 리버스 프록시 URL을 공유하는 모든 사용자가 로컬 개발 사이트에 액세스할 수 있습니다. 이는 고객에게 프로젝트를 시연하는 데 유용할 수 있지만 승인되지 않은 사용자가 민감한 정보를 공유할 수도 있습니다.
  • 일부 리버스 프록시 서비스는 사용량에 따라 요금을 청구하므로 가격이 서비스 선택의 요인이 될 수 있습니다.
  • 브라우저의 새로운 보안 조치는 이러한 도구의 작동 방식에 영향을 미칠 수 있습니다.

Chrome에서 mysite.example과 같은 커스텀 호스트 이름을 사용하는 경우 플래그를 사용하여 브라우저가 mysite.example을 안전한 것으로 간주하도록 할 수 있습니다. 다음과 같은 이유로 이렇게 하지 마세요.

  • mysite.example이 항상 로컬 주소로 확인되는지 100% 확신할 수 있어야 합니다. 그렇지 않으면 프로덕션 사용자 인증 정보가 유출될 위험이 있습니다.
  • 이 플래그는 Chrome에서만 작동하므로 브라우저 간에 디버그할 수 없습니다.

모든 검토자와 참여자, 특히 Ryan Sleevi, Filippo Valsorda, Milica Mihajlija, Rowan Merewood의 기여와 의견에 감사드립니다. 🙌