·networkhttp

HTTPS 개념과 적용 방법

웹 개발을 하다 보면 반드시 마주치게 되는 것이 HTTPS 설정입니다.

오늘은 HTTPS의 핵심인 공개키/개인키 개념부터 실제 통신 과정, 그리고 Nginx 설정법까지 정리해보겠습니다.

1. 공개키와 개인키

HTTPS를 이해하기 위해서는 먼저 공개키와 개인키의 개념을 알아야 합니다.

  • 공개키(public key)

    • 남들에게 마구 뿌려도 되는 키
    • 보통 server.crt, client.pem 같은 파일 형식을 가집니다.
  • 개인키(private key)

    • 나만 꽁꽁 숨겨둬야 하는 키입니다. 절대 유출되어서는 안 됩니다.
    • server.key 같은 형식을 가집니다.

이 두 키는 수학적으로 쌍을 이루고 있어, 공개키로 잠근 데이터는 오직 그와 쌍인 개인키로만 열 수 있다는 특징이 있습니다.

이해를 돕기 위해 다음과 같이 비유할 수 있습니다.

친구가 당신에게 비밀 편지를 보내고 싶어 합니다. 친구는 복도에 있는 당신의 **자물쇠(공개키)**를 가져와서 편지함을 잠급니다. 이제 이 편지함은 오직 **열쇠(개인키)**를 가진 당신만 열 수 있습니다. 배달 중에 도둑이 편지함을 훔쳐도 열쇠가 없으니 내용을 볼 수 없습니다.

2. TLS와 HTTPS

**TLS (Transport Layer Security)**는 위에서 설명한 공개키/개인키 방식을 이용하여, 데이터를 주고받는 통신 통로(Transport Layer) 자체를 암호화하는 프로토콜입니다.

  • HTTPS = HTTP + TLS

왜 우리는 HTTP가 아닌 HTTPS를 사용해야할까요?

우리가 흔히 쓰는 HTTP는 보안에 취약합니다. 예를 들어 로그인할 때 아이디와 비밀번호를 HTTP로 보내면, 해커가 패킷을 가로챘을 때 원본 값이 그대로 노출됩니다. 하지만 HTTPS는 이 값을 암호화해서 보내기 때문에 중간에 가로채더라도 내용을 알 수 없습니다.

3. HTTPS 적용 과정 (인증서 발급)

그렇다면 우리가 운영하는 서버에 HTTPS를 적용하려면 어떻게 해야 할까요? 일반적으로 다음과 같은 과정을 거쳐 인증서를 발급받습니다.

  1. 키 생성: 서버에서 개인키와 공개키 쌍을 생성하기
  2. CSR 생성: 생성한 공개키를 포함하여 **CSR(Certificate Signing Request)**을 만듭니다.
    • 주로 openssl 사용
  3. 인증 요청: 이 CSR을 신뢰할 수 있는 **CA(Certificate Authority, 인증 기관)**에 보냅니다.
  4. 인증서 발급: CA는 내가 진짜 그 서버의 주인인지 확인한 후, 서명이 담긴 **인증서(.crt)**를 발급해줍니다.

4. HTTPS 통신 과정 (Handshake)

이렇게 HTTPS가 적용된 내 서비스에 사용자가 접속하면, 어떤 일이 벌어질까요?

  1. 접속 요청: 사용자가 브라우저에서 A 서비스에 접속합니다.
  2. 공개키 전달: A 서버는 브라우저에게 자신의 **공개키(인증서)**를 보냅니다.
  3. 검증 및 대칭키 생성: 브라우저는 받은 인증서가 신뢰할 수 있는 CA에서 발급된 것인지 확인합니다. 확인이 끝나면, 브라우저는 앞으로의 통신에 사용할 **랜덤한 비밀번호(대칭키)**를 하나 생성합니다.
  4. 대칭키 암호화: 브라우저는 생성한 대칭키를 서버가 준 공개키로 잠가서(암호화해서) A 서버에 보냅니다.
  5. 대칭키 복호화: A 서버는 자신의 개인키로 이를 풀어서 대칭키를 얻어냅니다. (이제 브라우저와 서버는 둘 다 똑같은 대칭키를 공유하게 되었습니다!)
  6. 데이터 전송 (로그인): 사용자가 아이디/비밀번호를 입력하고 로그인을 시도합니다.
  7. 암호화 통신: 브라우저는 아이디/비밀번호를 아까 공유한 대칭키로 암호화해서 서버에 보냅니다.
  8. 데이터 처리: A 서버(보통 앞단의 Nginx 등)는 받은 데이터를 대칭키로 복호화하여 원본 데이터를 확인하고 애플리케이션 로직을 수행합니다.

왜 대칭키를 섞어서 쓸까?

공개키/개인키 방식은 보안성이 높지만 연산 비용이 비쌉니다. 따라서 접속 초기(Handshake)에만 공개키 방식을 사용하여 '대칭키'를 안전하게 교환하고, 실제 대용량 데이터를 주고받을 때는 속도가 빠른 '대칭키' 방식을 사용하는 하이브리드 방식을 채택하고 있습니다.

5. Nginx SSL 설정 예시

실무에서는 보통 Node.js나 Spring 같은 애플리케이션 앞단에 Nginx를 두어 SSL 처리를 위임(SSL Termination)합니다.

기본적인 nginx.conf 설정은 다음과 같습니다.

server {
    listen 443 ssl;  # 443포트(HTTPS) 활성화
    server_name my-service.com;

    # 1. CA로부터 발급받은 인증서 (공개키 정보 포함)
    ssl_certificate     /etc/nginx/ssl/server.crt;

    # 2. 서버에만 보관해야 하는 개인키 (절대 유출 금지)
    ssl_certificate_key /etc/nginx/ssl/server.key;

    location / {
        # 복호화된 요청을 뒷단 애플리케이션으로 전달
        proxy_pass http://localhost:8080;

        # 헤더 설정 (필요 시)
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

이 설정을 통해 Nginx가 암호화/복호화를 담당하게 되며, 뒷단의 서버는 비즈니스 로직에만 집중할 수 있게 됩니다.