μ§€λ‚œ SSL μΈμ¦μ„œμ™€ TLS μ˜€ν”„λ‘œλ“œλΌλŠ” 글을 톡해 HTTPS에 λŒ€ν•΄μ„œ μ‚΄νŽ΄λ³Έ 적이 μžˆμŠ΅λ‹ˆλ‹€. 이처럼 HTTPSλŠ” μ‚¬μš©μžμ˜ μš”μ²­μ΄ μ•ˆμ „ν•˜κ²Œ μ„œλ²„λ‘œ μ „λ‹¬λ˜λŠ” 것을 λͺ©μ μœΌλ‘œ λ„μž…ν•˜μ§€λ§Œ HTTP/2λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•¨λ„ μžˆμŠ΅λ‹ˆλ‹€. 일반 μ‚¬μš©μžμ˜ μ»΄ν“¨ν„°λ‚˜ λͺ¨λ°”일 λ””λ°”μ΄μŠ€μ— λŒ€ν•œ μ„±λŠ₯이 μ’‹μ•„μ§€λ©΄μ„œ TLS ν•Έλ“œμ‰μ΄ν‚Ήμ— λŒ€ν•œ λΉ„μš©μ€ 그닀지 크지 μ•ŠμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ HTTP 1.1μ—μ„œμ˜ Keep Alive λ„μž…μ€ 이미 연결쀑인 TCPλ₯Ό λ‹€μ‹œ μ‚¬μš©ν•˜λ―€λ‘œ μ–΄λŠμ •λ„μ˜ TLS ν•Έλ“œμ‰μ΄ν‚Ήμ— λŒ€ν•œ λΉ„μš©μ„ 쀄일 수 μžˆμ§€λ§Œ 수 λ§Žμ€ μš”μ²­μ΄ λ°œμƒν•˜λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œλŠ” 이미 응닡을 κΈ°λ‹€λ¦¬λŠ” μš”μ²­μ΄ λλ‚˜κΈ°λ₯Ό ν˜„μž¬ μš”μ²­μ΄ λŒ€κΈ°ν•΄μ•Όν•˜λŠ” 문제λ₯Ό 가지고 μžˆμŠ΅λ‹ˆλ‹€.

HTTP 1.1은 keep-alive 컀λ„₯μ…˜μ„ 톡해 μ—¬λŸ¬κ°œμ˜ TCP 연결을 일정 μ‹œκ°„ 열어놓고 μš”μ²­μ„ μ°¨λ‘€λŒ€λ‘œ μˆ˜ν–‰ν•˜κΈ° λ•Œλ¬Έμ— λΈŒλΌμš°μ €μ—μ„œλŠ” HTTP 1.1λ₯Ό μ‚¬μš©ν•  λ•Œ 도메인 λ‹Ή μ΅œλŒ€ μ—°κ²° 수λ₯Ό μ œν•œν•©λ‹ˆλ‹€.

HTTP/2

HTTP 1.1이 이미 μ—°κ²°λœ TCP 컀λ„₯μ…˜μ„ λ‹€μ‹œ μž¬μ‚¬μš©ν•œλ‹€λ©΄ HTTP2λŠ” 단일 TCP 연결을 μˆ˜ν–‰ν•˜κ³  수 λ§Žμ€ μš”μ²­μ„ 슀트림으둜 μ²˜λ¦¬ν•©λ‹ˆλ‹€. 그렇기에 κ½€ λ§Žμ€ μš”μ²­μ„ λ™μ‹œμ— μˆ˜ν–‰ν•΄λ„ λΈŒλΌμš°μ €λŠ” 이λ₯Ό μ œν•œν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ ν”„λ‘œλ―ΈμŠ€λ‘œ μ—¬λŸ¬κ°œ μš”μ²­μ„ λ™μ‹œμ— μˆ˜ν–‰ν•˜λ„λ‘ μ½”λ“œλ₯Ό μž‘μ„±ν•˜λ”λΌλ„ λ‹€λ₯Έ μš”μ²­μ΄ λλ‚˜κΈ°κΉŒμ§€ μš”μ²­μ΄ λŒ€κΈ°ν•˜λŠ” ν˜„μƒμ΄ μ€„μ–΄λ“€κ²Œλ˜λ©°, μ›ΉνŒ©μ„ 톡해 ν΄λΌμ΄μ–ΈνŠΈ UIλ₯Ό κ΅¬μ„±ν•˜λŠ” 에셋 νŒŒμΌλ“€μ„ μ—¬λŸ¬κ°œμ˜ μž‘μ€ μ‚¬μ΄μ¦ˆλ‘œ λ‚˜λˆ„λŠ” 청크λ₯Ό μˆ˜ν–‰ν•˜κ³  μ›Ή νŽ˜μ΄μ§€ λ‘œλ”© μ‹œ λΆ„ν• λœ 청크λ₯Ό λΉ λ₯΄κ²Œ 응닡받을 수 μžˆμŠ΅λ‹ˆλ‹€.

λΈŒλΌμš°μ €μ—μ„œ HTTP/2도 도메인 λ‹Ή TCP 연결을 μˆ˜ν–‰ν•©λ‹ˆλ‹€. 그리고 λŒ€λΆ€λΆ„μ˜ λΈŒλΌμš°μ €μ™€ μ„œλ²„μ—μ„œλŠ” HTTP/2 연결을 μœ„ν•΄ TLS μ‚¬μš©μ„ μš”κ΅¬ν•©λ‹ˆλ‹€.

ALPN

HTTP2.Pro μ‚¬μ΄νŠΈλ₯Ό μ‚¬μš©ν•΄μ„œ 넀이버와 μ˜€ν‚€ μ„œλΉ„μŠ€ μ£Όμ†Œλ₯Ό μž…λ ₯해보면 ALPN 지원 여뢀에 λŒ€ν•œ 정보가 ν‘œμ‹œλ©λ‹ˆλ‹€. ALPN은 TLS ν•Έλ“œμ‰μ΄ν¬λ₯Ό μˆ˜ν–‰ν•˜κ³  μ„œλ²„μ™€ ν΄λΌμ΄μ–ΈνŠΈκ°„ μ—°κ²°μ—μ„œ μ–΄λ–€ HTTP ν”„λ‘œν† μ½œμ„ μ‚¬μš©ν•  것인지λ₯Ό κ²°μ •ν•˜κΈ° μœ„ν•œ μ •μ±…μž…λ‹ˆλ‹€. μ•„λ§ˆμ‘΄ μ›Ή μ„œλΉ„μŠ€λŠ” NLBμ—μ„œλ„ TLS ALPN 정책을 μ§€μ›ν•˜κΈ°λ„ ν•˜μ£ .

HTTP/2 연결을 μš°μ„ μ μœΌλ‘œ μš”κ΅¬ν•˜κ³  ν΄λΌμ΄μ–ΈνŠΈκ°€ λΆˆκ°€λŠ₯ν•˜λ‹€λ©΄ HTTP 1.1둜 μ—°κ²°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Local CA with mkcert

μŠ€ν”„λ§ λΆ€νŠΈ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 뿐만 μ•„λ‹ˆλΌ μ—”μ§„μ—‘μŠ€μ—μ„œλ„ TLS ꡬ성을 μœ„ν•΄μ„œλŠ” μΈμ¦μ„œκ°€ ν•„μš”ν•©λ‹ˆλ‹€. κ·Έλž˜μ„œ μ§€λ‚œ SSL μΈμ¦μ„œ κΈ€μ—μ„œλŠ” 자체 μ„œλͺ… CA μΈμ¦μ„œ λ°œκΈ‰μ„ ν•œκ²ƒμ²˜λŸΌ 둜컬 개발 ν™˜κ²½μ„ μœ„ν•œ μΈμ¦μ„œλ₯Ό λ§Œλ“€κ³  μ μš©ν•˜λŠ” 과정을 κ³΅μœ ν–ˆμŠ΅λ‹ˆλ‹€. 이 과정듀은 생각보닀 κΉŒλ‹€λ‘­κ³  λΆˆνŽΈν•œ 뢀뢄이 λ§ŽμŠ΅λ‹ˆλ‹€. κ²°κ΅­ λΆˆνŽΈν•œ 것을 극히 μ‹«μ–΄ν•˜λŠ” κ°œλ°œμžλ“€μ€ mkcert라고 ν•˜λŠ” 둜컬 ν™˜κ²½μ„ μœ„ν•œ CA μΈμ¦μ„œλ₯Ό μžλ™μœΌλ‘œ μ‹ λ’° 기관에 λ“±λ‘ν•˜λŠ” 도ꡬλ₯Ό λ§Œλ“€μ–΄λƒ…λ‹ˆλ‹€.

PS C:\Users\Mambo\cert> mkcert -install
The local CA is now installed in the system trust store! ⚑️

PS C:\Users\Mambo\docker\nginx.conf> mkcert -ecdsa localhost 127.0.0.1 ::1 mambo.kr

Created a new certificate valid for the following names πŸ“œ
 - "localhost"
 - "127.0.0.1"
 - "::1"
 - "mambo.kr"

The certificate is at "./localhost+3.pem" and the key at "./localhost+3-key.pem" βœ…

It will expire on 22 May 2024 πŸ—“

κ°„λ‹¨ν•˜κ²Œ CA μΈμ¦μ„œλ₯Ό μ‹ λ’° 기관에 λ“±λ‘ν•˜κ³  둜컬 컴퓨터λ₯Ό μœ„ν•œ μΈμ¦μ„œλ₯Ό λ°œκΈ‰ν–ˆμŠ΅λ‹ˆλ‹€.
둜컬 컴퓨터λ₯Ό μœ„ν•œ μΈμ¦μ„œμ— λŒ€ν•œ μ‹ λ’° μΈμ¦μ„œλ₯Ό λ“±λ‘ν•œλ‹€λŠ” 점을 μžŠμ§€ λ§ˆμ„Έμš”.

둜컬 개발 ν™˜κ²½

일반적으둜 TLS ν•Έλ“œμ‰μ΄ν¬λ₯Ό μˆ˜ν–‰ν•˜λŠ” μ΄ν›„μ˜ νŠΈλž˜ν”½ μ „λ‹¬μ—λŠ” TLS 연결을 μˆ˜ν–‰ν•˜λ„λ‘ ν•˜μ§€ μ•Šλ„λ‘ κ΅¬μ„±ν•©λ‹ˆλ‹€. 일뢀 μ—”μ§€λ‹ˆμ–΄λ“€μ€ λͺ¨λ“  νŠΈλž˜ν”½ 전달에 TLS 연결을 ν•΄μ•Όν•œλ‹€κ³  λ§ν•©λ‹ˆλ‹€. μ–΄λŠμ •λ„μ˜ λ³΄μ•ˆμ μΈ ꡬ성을 ν•˜λŠλƒλŠ” μ‘°μ§μ—μ„œ κ²°μ •ν•΄μ•Όν•  μΌμž…λ‹ˆλ‹€. ν˜„μž¬ 쑰직은 μ•„λ§ˆμ‘΄ μ›Ή μ„œλΉ„μŠ€μ˜ λ‘œλ“œλ°ΈλŸ°μ„œμ—μ„œ TLS ν•Έλ“œμ‰μ΄ν¬λ₯Ό μˆ˜ν–‰ν•˜λ„λ‘ ν•˜κ³  내뢀적인 νŠΈλž˜ν”½ μ „λ‹¬μ—λŠ” TLSλ₯Ό μ‚¬μš©ν•˜μ—¬ νŒ¨ν‚·μ„ λ³΄ν˜Έν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

TLS μ˜€ν”„λ‘œλ“œ 및 λ¦¬λ²„μŠ€ ν”„λ‘μ‹œλ₯Ό μœ„ν•œ μ—”μ§„μ—‘μŠ€λ₯Ό κ΅¬μ„±ν•˜κ³  HTTP둜 μ‹€ν–‰λœ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— νŠΈλž˜ν”½μ„ μ „λ‹¬ν•˜λ©° HTTP/2λ₯Ό μ‚¬μš©ν•  수 있게 λ§Œλ“€κ² μŠ΅λ‹ˆλ‹€. 이미 μ‚¬μš©μ€‘μΈ μ—”μ§„μ—‘μŠ€κ°€ μ—†λ‹€λ©΄ 제 κΉƒν—ˆλΈŒ λ¦¬νŒŒμ§€ν† λ¦¬ nginx.conf의 μ½”λ“œλ₯Ό ν™œμš©ν•΄μ„œ 도컀 컴포즈둜 μ—”μ§„μ—‘μŠ€ μ»¨ν…Œμ΄λ„ˆλ₯Ό μ‹€ν–‰ν•˜μ…”λ„ μ’‹μŠ΅λ‹ˆλ‹€.

version: '3.8'
services: 
  nginx:
    image: nginx:1.21.3-alpine
    ports: 
      - 80:80
      - 443:443
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./localhost+3.pem:/etc/nginx/server.crt
      - ./localhost+3-key.pem:/etc/nginx/server.key
      - ./static:/etc/nginx/static
  app:
    image: amazoncorretto:11-alpine
    command: 'java -jar /etc/app.jar'
    volumes:
      - ./demo-0.0.1-SNAPSHOT.jar:/etc/app.jar

μ €λŠ” λ¦¬νŒŒμ§€ν† λ¦¬μ— μžˆλŠ” 사섀 μΈμ¦μ„œ λŒ€μ‹ μ— mkcertλ₯Ό 톡해 λ§Œλ“€μ–΄μ§„ μΈμ¦μ„œλ₯Ό μ‚¬μš©ν•˜λ„λ‘ λ³€κ²½ν–ˆμŠ΅λ‹ˆλ‹€.

λ¦¬νŒŒμ§€ν† λ¦¬μ— μ €μž₯된 μƒ˜ν”Œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ·ΈλŒ€λ‘œ μ‚¬μš©ν–ˆμ§€λ§Œ 둜컬 ν˜ΈμŠ€νŠΈμ—μ„œ μΈν…”λ¦¬μ œμ΄μ™€ 같은 개발 λ„κ΅¬λ‘œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ‹€ν–‰ν•˜μ…¨λ‹€λ©΄ nginx.conf 파일의 λ°±μ—”λ“œ μŠ€νŠΈλ¦Όμ— λŒ€ν•œ μ£Όμ†Œλ₯Ό host.docker.internal둜 λ³€κ²½ν•˜μ„Έμš”. μ»¨ν…Œμ΄λ„ˆλ‘œ μ‹€ν–‰λœ μ—”μ§„μ—‘μŠ€μ—μ„œ 둜컬 호슀트둜 νŠΈλž˜ν”½μ΄ μ „λ‹¬λ˜κ²Œ λ©λ‹ˆλ‹€.

TLS Handshake
HTTP/2

mkcertκ°€ μžλ™μœΌλ‘œ μ‹ λ’° κΈ°κ΄€ λͺ©λ‘μ— μžμ‹ μ˜ CA μΈμ¦μ„œλ₯Ό λ“±λ‘ν•˜μ˜€κΈ° λ•Œλ¬Έμ— λΈŒλΌμš°μ €λŠ” μΈμ¦μ„œλ₯Ό μ‹ λ’°ν•  수 μžˆλ‹€κ³  νŒλ‹¨ν–ˆκ³  HTTPS 연결이 μ •μƒμ μœΌλ‘œ μˆ˜ν–‰λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

이제 μ—¬λŸ¬λΆ„λ“€λ„ 둜컬 ν™˜κ²½μ—μ„œ κ°œλ°œν•˜μ‹€λ•Œ HTTPS와 그리고 HTTP 1.1이 μ•„λ‹Œ HTTP/2λ₯Ό μ‚¬μš©ν•΄λ³΄μ‹œκΈ° λ°”λžλ‹ˆλ‹€.

κ°μ‚¬ν•©λ‹ˆλ‹€.