오늘 배운 것

오늘 작업할 예정인 이슈들은 다음과 같다. 

1. 어제 작업하면서 알았던 인박스 뷰에서의 서브투두 날짜설정 이슈

2. prod와 dev로 개발환경 분리하기

3. prod 개발환경 실행시키기

 

1번은 팀원들이 모두 도착한 뒤에 논의가 가능하기 때문에 2번과 3번을 먼저 처리할 예정이다. 

 

기존의 onestep_be/settings.py의 파일의 내용을 전부 onestep_be/settings/base.py 파일을 만들어서 복사해준 뒤, 같은 디렉토리에 dev.py와 prod.py라는 파일을 만들었다. base.py 파일에는 dev와 prod 환경에서 공통적으로 사용하는 속성들을 모두 정의해 주고, 나머지 다른 설정을 dev랑 prod에만 해 볼 예정이다. 

 

또한 manage.py 및 asgi.py, wsgi.py에서 기본으로 장고의 세팅 파일을 어떤 파일로 참조할지 지정해주는 로직이 있다. 기본 값은 'onestep_be.settings' 였는데 이제는 파일의 경로가 변경되었으므로 'onestep_be.settings.dev' 경로로 바꿔주었더니 잘 동작하였다. 아래처럼 어떤 settings 파일을 사용할지를 이 코드에서 연결해주는 것 같아서 값을 바꿔주었다. 

 

이러면 python manage.py runserver 명령어를 입력했을 때는 DJANGO_SETTINGS_MODULE 변수에 기본값으로 할당된 dev 환경이 실행된다. 만약 runserver 명령어로 prod 환경을 실행시키고 싶다면, 명령어에 환경변수 값으로 prod 환경 파일의 경로를 넣어주면 된다. 

기본값 dev
prod 환경으로도 실행 가능

 

그리고 생각해보니 일반 개발환경에서는 python manage.py runserver가 실행되어야 하고, 나머지 경우에는 프로덕션 환경을 사용해야 한다. 그러므로 도커파일의 커맨드도 prod 환경으로 실행되는 커맨드로 바꿔주어야 하겠다. 그런데 또 생각해보니 개발서버는 dev 환경을 사용해야하고 프로덕션 서버는 prod 환경을 사용해야 한다. 그러면 도커파일의 커맨드도 각 브랜치별로 달라야 하는데... 이게 가능한가 싶기도 하다. 

 

그래서 또 생각해보니 굳이 dev 서버의 debug 모드를 true로 배포해야 할 필요가 있나 싶었다. 어차피 dev 서버를 호출하는 것도 프론트엔드의 앱일 텐데, 그러면 html로 디테일한 웹 메시지를 보여준다해도 어차피 api 통신 환경에서는 못 보기 때문이다. 혹시나 싶어 장고 공식문서의 settings DEBUG 속성을 찾아보았는데, DEBUG 속성을 true로 했을 때는 크게 두 가지 차이점이 있다고 한다: 

1. 에러가 발생했을 때 페이지로 오류의 구체적인 원인과 trace 등을 보여준다. 

2. 장고 서버에서 실행되는 모든 SQL 쿼리를 서버가 기억하고 있다. 이는 에러 트래킹을 하는 데는 유리하지만, 프로덕션 서버에서 사용할 경우 메모리를 많이 사용할 수 있다. 

 

아무튼 찾아보았는데 별 이상이 없어서, 도커파일에서 사용하는 커맨드를 기존의 python manage.py runserver에서 python manage.py runserver --settings=onestep_be.settings.prod로 바꿔 주었다. 


이제 프로덕션 환경에서 사용할 RDS를 생성해 주었다. 그 다음으로 AWS secrets manager에 방금 생성한 RDS의 퍼블릭 엔드포인트 주소와 사용자 이름 및 비밀번호를 넣어주어서 장고 서버에서 해당 값에 접근할 수 있도록 해 주면 된다. 그런데 이 작업을 하다보니 문제점이 생각났다. 처음엔 dev 서버와 prod 서버에서 모두 production 설정을 참조하면 되겠다고 막연히 생각했는데, 생각해보니 dev 서버에서는 개발 RDS DB를, prod 서버에서는 프로덕션 RDS DB를 참조해야 했다... 즉 이러나 저러나 dev 서버와 prod 서버는 다른 환경을 참조해야 하는 것이다. 

 

 

GPT에게 도움 요청을 해 보았다. GPT는 github action에서 사용하는 yml 파일에서 ECS 클러스터에서 사용할 태스크를 동적으로 정의하고, 그 과정에서 ECS 태스크의 환경변수로 DJANGO_SETTINGS_MODULE의 값으로 개발서버는 onestep_be.settings.dev를, 프로덕션 서버는 onestep_be.settings.prod를 값으로 주는 방법을 제시했다. 지금으로써는 이게 최선이지 않을까 싶어 이 방법을 적용해 보기로 했다. 

 

또한 yml 파일을 보니 프로덕션 RDS DB의 정보 말고도 추가로 필요한 정보가 있었다. 예를 들면 프로덕션 서버를 배포할 때 이미지를 올릴 ECR 레포지토리의 이름, ECS 클러스터의 이름 및 ECS 서비스의 이름이 필요해 보였다. 참고로 이 변수들은 AWS secrets manager 뿐만 아니라 github actions에도 secret으로 정의해야 yml 파일에서 인식할 수 있을 것 같았다. 이것들도 별도로 생성해준 뒤 yml 파일을 다시 작성해 보았다. 

 

그리고 생각해보니 개발환경과 프로덕션에서 사용하는 환경 변수가 다른데, 이걸 아예 별도의 보안 암호 이름을 두고 분리해야 하지 않을까 싶었다. 그래야 개발환경과 프로덕션 환경이 더 명확히 분리될 것 같았다. 그래서 기존의 개발환경에서 사용하던 onestep/dev는 그대로 두고, 프로덕션에서 사용하기 위해 onestep/prod 보안 암호를 생성해 주었다. 

 

그리고 production 세팅을 사용하도록 명령어에 값을 넣어준 뒤 runserver를 실행해 보았는데, 다음과 같은 에러가 났다. 아마 RDS DB에 접근하려는 database가 없기 때문인 것 같아서, RDS에 터미널을 통해 접속한 뒤 원하는 이름의 database를 생성해 주었다. 

 

다시 실행해 보니 잘 동작한다!

 

이제 다시 돌아가서 프로덕션 서버에서 사용할 ECS 레포지토리와 ECS 클러스터, ECS 태스크 정의를 생성해 주고, 로드밸런서를 생성해 주자. 그리고 ECS 서비스 설정을 마친 다음, 이 중에서 필요한 값들을 github action secret에 할당해 주자. 

 

main 브랜치(프로덕션 서버에 반영될 코드 내용)의 코드를 도커 이미지로 push할 ECR 레포지토리를 우선 만들어줬다.

 

그리고 해당 클러스터의 서비스에서 사용될 태스크 정의를 새로 만들어줬다. 

 

그리고 바로 ECS 서비스를 만드려고 했는데, 생각해보니 서비스를 만들려면 별도의 로드밸런서가 필요했고 로드밸런서를 생성하려면 별도의 대상 그룹이 필요했다. 그래서 대상 그룹부터 만들어주려고 했다. 

 

평화롭게 잘 만들어가던 중, VPC 서브넷의 IPv4 주소를 입력하라는 창이 떴다. 그래서 VPC 서비스로 가 보았다. 'VPC 서브넷의 IPv4 주소'가 무엇인지 모르겠어서 GPT에게 질문해보았다. 

 

GPT는 서브넷의 CIDR 블록에 있는 주소를 입력하라고 해서, 해당 주소를 입력해 주었다. 그렇게 대상 그룹을 생성하고, 로드밸런서를 생성하고, 서비스를 순차적으로 생성했다. 지금은 ECR 레포지토리에 올라온 도커 이미지가 아예 없어서 아마 ECS 서비스가 태스크를 실행할 수 없을 것이다. 

 

그리고 github action secrets에 관련 파일도 올려두었다. 기존에 개발환경에서 사용하는 관련 변수들 뒤에 _PROD를 붙여서 해당 변수들은 프로덕션 환경에서 사용하게끔 yaml 파일도 작성했다. 

이런 값들이 들어있다

 

처음엔 잘 돌아가나 싶더니 뭔가 이상했다. 10분이 지나고 ECS의 서비스를 확인해 봤는데 태스크가 실행되고 있지 않았다. 

 

혹시나 싶어 ECR에 도커 이미지가 올라왔나 확인해봤는데 올라오지 않았다. 아무래도 yaml 파일에서 ECR 레포지토리에 이미지를 업로드하는 과정에서 뭔가가 오류가 있는 듯 하다. 이 오류는 집에 가서 정신이 멀쩡해지면 다시 해결해 보겠다. 


오류가 아니었다! 집에 와서 확인해보니, 21분 만에(...) develop 브랜치에 있는 내용이 ECR을 거쳐 ECS를 통해 배포되었다... 근데 이게 과연 성공이라고 말할 수 있을지 모르겠다. 지금은 무중단 배포도 아닌 걸로 알고 있는데 2초도 아니고 20분이 붕 뜬다..? 지금 배포되는 방식이 중단 배포인지 무중단 배포인지 알아보고, 중단 배포라면 무중단 배포 방법을 알아보아야겠다. 

21분 실화냐

암튼 이 과정이 완료되고 나서, 기대에 부푼 마음으로 main 브랜치의 workflow를 실행시켜 보았다. 여기서는 에러가 났다. 로그를 보니 ECS 서비스 안의 컨테이너 이름이 yaml 파일과 일치하지 않은 것 같았다. 

 

알고보니 yaml 파일에 오류가 난 task 부분의 container name이 개발 서버에서 사용하는 컨테이너 이름으로 되어 있어서 바꿔줬다. 

 

다시 띄워보니 성공했다!

 

ECS 클러스터>서비스>태스크>네트워크의 ENI 정보>퍼블릭 DNS로 접속하니, 접속이 잘 되었다.

 

그런데 로드밸런서에 설정해 놓은 health check url로 들어가니 swagger가 나오지 않고 다음과 같은 django login 창이 떴다. 

 

현재 개발서버의 똑같은 URL로 들어가면 swagger 화면이 잘 나오기 때문에, 이는 prod와 dev의 환경 중 일부 값이 다른 것이 원인인 것 같다. 어쩌면 DEBUG 옵션일 수도 있겠다. 어쨌건 서버는 잘 뜨니 이 문제도 추후 확인해 보면 좋겠다. 

 

 궁금한 점

1. 이렇게 환경변수를 명령어로 할당하는 것 말고 다른 방식으로도 필요할 때만 prod 환경 설정을 사용하는 방법이 있을지 궁금하다. 

2. 로드 밸런서를 생성할 때 VPC와 서브넷과 로드밸런서가 구체적으로 어떤 관계가 있는 것인지 잘 모르겠다. 

3. DEBUG=False 옵션과 /swagger UI에서 django login 화면이 뜨는 것이 관련이 있는지 궁금하다. 없다면 어떤 원인일지도 궁금하다. 

+ Recent posts