본문 바로가기
Programming

[Spring , React] mkcert를 이용한 localhost ssl 인증서 구성

by Pendine 2025. 11. 18.
728x90
반응형

localhost ssl 인증서 관련문제

요청 오류 원인

로컬호스트 ssl 인증서 사용으로 인한 문제
ssl 인증서가 유효하지 않다는 이유로 크롬브라우저에서 인증서 오류로 백엔드에 요청을 보내지 않고 오류처리.
오류 발생시 크롬 브라우저로 백엔드 주소 (https://localhost:8080)로%EB%A1%9C) 직접 접속해서
안전 관련 경고 무시 처리 이후,
프론트 엔드의 요청이 정상적으로 전달됨.

큰 문제가 없으나,
가끔 발생하는 해야 하는 캐시 삭제 이후 매번 해줘야 하는 번거로움으로 인해 해결을 목표로 함.

해결 방법

해결방법 1. 실제 SSL 인증서를 구매 또는 무료 발급

실서비스 도메인에서는 실제 인증서가 필요.

가장 추천:

  • Let’s Encrypt → 무료, 자동 갱신 가능
  • 비용 없음
  • nginx·Apache·Spring Boot와 연동 쉬움

💡 하지만 localhost에는 절대 발급 불가능
공인 인증서는 “인터넷에서 접근 가능한 실제 도메인”이 필요.

해결방법 2. 로컬 신뢰 저장소에 인증서를 등록

"브라우저가 신뢰하도록 만들기"

편법으로 가능.

방법.

  1. self-signed 인증서를 .crt 또는 .pem으로 추출
  2. OS 시스템 키체인(Keychain, Certificate Manager 등)에 등록
  3. “신뢰함(Trust)” 옵션 활성화
    이렇게 하면 브라우저 전체에서 ERR_CERT_AUTHORITY_INVALID가 사라짐.

문제점:

  • 시스템 전체에 영향을 줌
  • 인증서 갱신 시 또 등록해야 함
  • 로컬 개발자 1명일 땐 되지만, 협업 환경에서는 비추천

해결방법 3. 로컬용 "가짜 CA"를 만들어서 그 CA를 시스템 신뢰 저장소에 등록하기

가장 ‘정석적인 개발환경 세팅’.

사용 도구:

  • mkcert (로컬 환경 HTTPS 개발을 위해 가장 널리 씀)mkcert의 원리:
  • 로컬 컴퓨터에 “신뢰된 가짜 CA”를 자동으로 생성하고 설치해줌
  • 그 “가짜 CA”로 HTTPS 인증서를 생성 → 브라우저에서 완전 신뢰됨

장점

✔ ERR_CERT_AUTHORITY_INVALID 완벽 해결
✔ 브라우저에 따로 들어가서 “무시하고 계속하기” 안 해도 됨
✔ 개발 환경 전용이라 보안 문제 없음
✔ 협업자에게도 가짜 CA만 배포하면 동일하게 사용 가능

해결 시도 방법 : mkcert 사용

mkcert를 쓰면:

  • 로컬에 “신뢰된 가짜 CA”가 설치됨
  • 이 가짜 CA가 발급하는 인증서는 100% 신뢰됨
  • localhost, 127.0.0.1, 192.168.x.x 등 어떤 도메인도 OK
  • 프론트 + 백엔드 모두 HTTPS 정상 작동
  • ERR_CERT_AUTHORITY_INVALID 문제 완전 사라짐
mkcert localhost 127.0.0.1 ::1

그러면 localhost.pem, localhost-key.pem 생성됨.

Spring Boot에서 SSL 하나로 해결됨.
✔ 한 번만 하면 끝
✔ 매번 클릭할 필요 없음
✔ 도메인 달라도 OK
✔ 개발 환경에서 가장 흔하게 쓰는 방식

mkcert 사용하기 위한 전제조건

mkcert를 윈도우에서 사용하기 위해 설치해야함

윈도우

Windows에서는 Chocolatey를 사용하세요

choco install mkcert

또는 Scoop을 사용하세요

scoop bucket add extras
scoop install mkcert

또는 소스에서 빌드하거나(Go 1.10 이상 필요) 미리 빌드된 바이너리를 사용하세요 .
권한 문제가 발생하는 경우 mkcert관리자 권한으로 실행해 보세요.

미리 빌드된 바이너리 (버전 : v1.4.4 윈도우 amd )를 사용 할 예정.

  1. 빌드된 바이너리를 다운로드 받은 경로 에서 cmd 실행
  2. mkcert -install
PS C:\Users\PC\Downloads> .\mkcert-v1.4.4-windows-amd64.exe  -key-file key.pem -cert-file cert.pem
Note: the local CA is not installed in the system trust store.
Run "mkcert -install" for certificates to be trusted automatically ⚠️
Usage of mkcert:

        $ mkcert -install
        Install the local CA in the system trust store.

        $ mkcert example.org
        Generate "example.org.pem" and "example.org-key.pem".

        $ mkcert example.com myapp.dev localhost 127.0.0.1 ::1
        Generate "example.com+4.pem" and "example.com+4-key.pem".

        $ mkcert "*.example.it"
        Generate "_wildcard.example.it.pem" and "_wildcard.example.it-key.pem".

        $ mkcert -uninstall
        Uninstall the local CA (but do not delete it).

For more options, run "mkcert -help".
PS C:\Users\PC\Downloads> .\mkcert-v1.4.4-windows-amd64.exe -install
The local CA is now installed in the system trust store! ⚡️

PS C:\Users\PC\Downloads>

이거 실행하고 무슨 알림창 뜬거 읽어보고 예 버튼 클릭했는데
이걸로 로컬 CA 구성된 것 같음
확인해보고싶은데, 브라우저에서 무시하고 계속. 버튼이 나오도록 구성을 다시 해봐야할것같음.
이러면 CA다시 해제하고, 브라우저에서 무시하고 계속 버튼이 나오는지 확인한뒤
다시 CA구성을 해보고 확인 해봐야함.

  1. 로컬 CA 구성제거
PS C:\Users\PC\Downloads> .\mkcert-v1.4.4-windows-amd64.exe -uninstall
The local CA is now uninstalled from the system trust store(s)! 👋
  1. 크롬 경고 띄우기
    크롬 브라우저의 왼쪽 상단에 주의 요망 버튼 클릭, 쿠키 및 사이트 데이터 클릭, 기기 내 사이트 데이터 클릭. 휴지통모양 아이콘 클릭.
  2. 로컬 CA 구성 및 인증서 발급
    (인증서 발급시 사용한 호스트 정보에서만 사용 가능.
    발급한 인증서는 실행한 경로에서 localhost+2.pem, localhost+2-key.pem 로 나옴)
PS C:\Users\PC\Downloads> .\mkcert-v1.4.4-windows-amd64.exe -install
The local CA is already installed in the system trust store! 👍

PS C:\Users\PC\Downloads> .\mkcert-v1.4.4-windows-amd64.exe localhost 127.0.0.1 ::1

Created a new certificate valid for the following names 📜
 - "localhost"
 - "127.0.0.1"
 - "::1"

The certificate is at "./localhost+2.pem" and the key at "./localhost+2-key.pem" ✅

It will expire on 18 February 2028 🗓

PS C:\Users\PC\Downloads>
  1. OpenSSL로 PKCS12 변환. (발급한 인증서 파일이 있는 위치에서)
    Git Bash 실행:
openssl pkcs12 -export \   
        -in localhost+2.pem \
        -inkey localhost+2-key.pem \   
        -out localhost.p12 \   
        -name "localhost" \   
        -password pass:123456
  • -in : 인증서
  • -inkey : 개인키
  • -out : 생성될 p12 파일
  • -name : 엔트리 이름 (보통 localhost)
    • P12 파일 내부의 엔트리에 붙이는 별명.
    • 나중에 스프링부트 `application.yml` 설정에서 `key-alias: localhost`라고 적어줄 때 사용합니다. (이 이름이 다르면 스프링이 파일 안에서 인증서를 못 찾고 에러를 냅니다.)
  • -password pass: : 키스토어 비밀번호 (Spring Boot에서 사용)
    • P12 파일 자체를 잠그는 비밀번호.
    • 스프링부트 설정의 `key-store-password` 항목에 들어갈 값.

-password 안에 입력할 수 있는 내용

  • pass:123456 → 비밀번호를 직접 지정
  • 다른 형식도 있음:
    • env:ENV_VAR → 환경변수 값 사용
    • file:파일경로 → 파일 안의 값 사용
  • password 라는 옵션은 비밀번호를 어디서 가져올지 설정하는역할이고, 다양한 방법으로 어디서 어떻게 참조할지 지정하는것임.
사용 방식
옵션 형식 의미 PKCS12 내부 비밀번호
pass:문자열 문자열 그대로 비밀번호 사용 문자열 그대로 들어감
env:ENV_VAR 환경변수에서 읽어서 비밀번호 사용 ENV_VAR 값이 들어감
file:파일경로 파일 안 내용 읽어서 비밀번호 사용 파일 안 문자열이 들어감

즉, 최종 PKCS12에 저장되는 비밀번호는 항상 문자열임.

pass:1234 → PKCS12 내부 비밀번호는 1234
env:MY_PASS → PKCS12 내부 비밀번호는 MY_PASS 환경변수 값
file:pwd.txt → PKCS12 내부 비밀번호는 pwd.txt 안 내용

구성 폴더 위치 파일 형식 필요 파일 사용시 비밀번호 필요 여부
프론트 프로젝트 루트폴더 내에 원하는 폴더 생성 .pem ~-key.pem, ~.pem X
resource 폴더 내에 원하는 폴더 생성 .p12 .p12 Y

프론트엔드 ssl 구성

#vite.config.ts

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: [
      ~
    ],
  },
  server: {
    ~
    https: {
      key: fs.readFileSync('./certs/localhost+2-key.pem'),
      cert: fs.readFileSync('./certs/localhost+2.pem'),
    },
    // port: 3000,
  },
  css: {
    preprocessorOptions: {
        ~
    },
  },
})

백엔드 ssl 구성

#application.yml
server:  
  servlet:  
    encoding:  
      force-response: true  
  #  port: 8443  
  port: 8080  
  ssl:  
    enabled: true  
    key-store: classpath:keystore/localhost.p12  
    key-store-password: 123456  
    key-store-type: PKCS12

결과

모든 서버 종료 후
백엔드
https://localhost:8080 주소 접속시 인증서 오류 해결.
프론트엔드
인증서 오류 해결.

728x90
반응형

댓글