오늘은 서비스에 어떻게 https를 적용하였는지 알아볼 계획입니다. https가 뭐고 인증서가 뭐고 하나도 모르는 상황에서 시작하고, AWS 또한 익숙지 않고 다루어본 적이 없어서 정말 오랫동안 삽질하고 헤맸던 기억이 나네요.

https

우선 https를 적용하게 된 배경은 아래와 같습니다.

스크린샷 2019-08-31 오후 10.53.38.png
테스트 서버로 구현되어있던 서버를 이번에 실질적인 배포용 서버로 바꾸면서 새로운 서버에는 https를 적용해야 했습니다. 크롬에서는 https를 지원하지 않으면 경고메시지를 띄우기 때문에 UX 측면에서 무척 좋지 않았기 때문이죠.

그리고 그 뒤에 상사님은 간단하게 https를 적용하기 위한 글을 두 개 공유해주셨습니다. 그리고 저는 새로운 서버에 적용하기 위한 https를 테스트 서버에 적용하게 됩니다.

스크린샷 2019-08-31 오후 10.53.52.png

(저는 해야했습니다...)

certbot, Let's Encrypt, 첫번째 삽질

강사님이 주신 자료는 이곳이었습니다. 저는 글에서 알려주는 것처럼 certbot을 내려받고, SSL 인증서를 획득하고, 적용한 뒤(certbot이 친절하게도 NGINX 에도 알아서 적용해주더군요.) 페이지로 접속했습니다. 그런데, 없는 페이지라는 화면이 떠올랐습니다. 시키는 대로 다 하고 방화벽도 이리저리 건드려보았지만, 전혀 해결되지 않았습니다.
여러 가지를 시도해보던 저는 NGINX를 지우고 다시 설치해서 같은 과정을 반복했습니다. 그리고 또다시 같은 결과를 보게 되었습니다.
계속해서 인터넷을 둘러보던 도중에 '크롬의 이전 기록을 모두 제거해보세요.'라는 글을 보게 되었고, 한번 지워보았습니다. 그러자 에러 문구가 바뀌었습니다. https로 주소는 바뀌었는데, 계속해서 http로 접속을 하려 해서 벌어진 일이었죠.

글로 설명하니 무척 짧지만, 정말 오랫동안 삽질했던 기억이 있습니다.

두번째 삽질

문구가 바뀐 에러는 지속되었습니다. 크롬의 개발자도구에서 네트워크 탭을 열어보니 요청은 시도하지만, 결과물을 받아오지 못하는 것을 볼 수 있었습니다. https에 대한 요청에 서버가 응답하지 못하는 것이었죠. 다행히도 이 부분에 대해 NGINX 설정을 찬찬히 확인하다가 listen 443 인부분을 보고, 그 부분을 키워드로 삼아 여러 글을 찾다 보니 'https에 대한 요청을 AWS에서 받아오려면 443 포트를 열어놔야 해요~' 라는 글을 읽고, AWS 인바운드 규칙에 443 포트를 추가해 주어 해결했습니다.

주소창 왼쪽에 자물쇠 모양이 뜨며 저희 서비스 페이지가 열릴 때의 그 쾌감이란….

세번째 삽질

서비스 페이지가 열리긴 열렸는데, API 요청을 보내니 에러가 발생했습니다.
Mixed Content: The page at 'https:(요청 보내는 주소) ' was loaded over HTTPS, but requested an insecure script 'http:(요청받는 주소) '. This request has been blocked; the content must be served over HTTPS.
대강 'https에서는 https 요청만 가능해'라는 뜻이었습니다. 막막했습니다. '서버도 https로 만들어야 하나?' 라는 생각도 하게 되었습니다. 이리저리 구글링하던 도중 이곳 을 발견하게 되었습니다. 댓글에 보시면, 'https로 만들어진 NGINX 서버를 거쳐 들어가라'라는 조언이 있습니다. 그 부분을 참고하여, NGINX 코드를 이렇게 작성하였습니다.

server {
  server_name # 서버 이름
  location / {
    root   /var/www/{build된 폴더 이름};
    index  index.html index.html;
    try_files $uri $uri/ /index.html;
  }
  # Certbot을 통하여 만들어진 ssl관련 코드

  location /graphql { # {클라이언트주소}/graphql요청이 오면 아래의 주소로 요청보내기
    proxy_pass http://{서버주소}:{포트Num}/graphql;
  }

  location /auth/github { # 위와 마찬가지
    proxy_pass http://{서버주소}:{포트Num}/auth/github;
  }

}
server {
  listen {포트};
  server_name # 서버이름;
    return 404; # managed by Certbot
}

저는 graphQL 기술을 사용하고 있고, 따로 요청하는 부분은 OAuth의 요청밖에 없으니 이렇게 작성하였고, 테스트 배포 서버에서 제대로 동작하였습니다. 기쁨에 가득 차서 배포 사실을 알렸고, 다음 주에 실질적인 배포 서버를 제작하여, 다시 배포하기로 하였죠.

그리고 production서버에 배포하니, 에러가 발생했습니다.

네번째 삽질

이 삽질은 제가 정말 경험이 부족하고 아무것도 모른다는 것을 다시 한번 깨닫게 해 준 삽질이었습니다. 실 배포 서버는 오직 80, 433, ssh전용포트 만을 열어놓기 때문에 제가 지정해놓은 포트로는 연결을 받지 못해서 에러가 발생하였습니다.
퇴근시간이 지나고, 약속 장소로 가서 상대방과 만나는 와중에도 계속해서 생각하다가 '왜 요청을 다시 서버 쪽으로 보냈지? 로컬 내부에서 보내면 되지 않나?' 하는 생각이 들어 카페에서 커피를 마시는 와중에 그렇게 수정하였고, 결과는 성공적이었습니다.(다시 한번 그때 만나고 있던 Gram에게 감사를..)

server {
  server_name # 서버이름
  location / {
    root   /var/www/{build된 폴더 이름};
    index  index.html index.html;
    try_files $uri $uri/ /index.html;
  }
  # Certbot을 통하여 만들어진 ssl관련 코드

  location /graphql {
    proxy_pass http://localhost:3000/graphql;
  }

  location /auth/github {
    proxy_pass http://localhost:3000/auth/github;
  }
}
server {
  listen 80;
  server_name # 서버이름;
  return 301 https://$host$request_uri; # manage by Certbot
  #http요청은 리다이렉트
}

location 쪽을 보시면 {서버 이름}:{포트 Num}이었던 부분이 localhost:3000로 변경되어있습니다. NGINX내부에서 로컬에 열려있는 서버에 연결시킨 것입니다. (참고로 pm2를 이용하여 EC2 내부 로컬에서 3000 포트로 서버를 열어둔 상태였습니다.)

마무리

이렇게, 길고 험난했던 약 4일간의 삽질이 마무리되었습니다. 제가 한 방법이 좋으니 이렇게 해라!라는 글을 쓰고 싶지 않았습니다. 저는 이렇게 했고, 만약 저와 같은 삽질을 하고 계신 분이 있다면 참고하실 수 있는 글을 작성하고 싶었습니다. 아마도 더 좋은 방법이 있고, 제 코드는 개선할 여지가 많다고 생각합니다. 🙇‍♂️ 혹시 틀리거나 잘못된 부분, '왜 이딴 식으로 한 거지?' 같은 질문이 있으시다면 꼭 댓글로 남겨주시길 바랍니다. 이번 글도 끝까지 읽어주셔서 감사합니다.