InIT을 진행하면서 개발서버는 AWS EC2 t2.micro를 사용하여 SpringBoot를 올린 적이 있었다. 이렇게만 올리면 별 상관이 없겠지만, 문제는 CI/CD도 한다는 점이다. 그러다 보니 서버가 자꾸 죽는 현상이 발생했다.
이유는 cpu의 사용량이 급격하게 늘어났고, 메모리의 사용량이 1G를 넘는다는 점!
일단 우리 프로젝트는 프로젝트 팀 한분의 회사에서 지원받고 있기에 크레딧이 항상남아서 t2.small로 바꾸어서 해결했다. 하지만 이건 절대로 해결했다고 볼 수 없기에 세부적인 문제를 찾아서 그에 대한 해결방안을 찾아보기로 했다.
일단 기본적으로 개발 서버가 Memory를 얼마나 쓰는지도 확인하고 SpringBoot가 얼마나 Memory를 잡아먹는지에 대해서 알아야 했다. 현재 바꾼 t2.small 기준으로 확인한 결과, 400M정도로 스프링이 돌아가고, 캐시 메모리가 900M, 기본적으로 200M정도가 더 돌아간다고 확인할 수 있었다.
그럼 여기서 Used Memory가 1G 이상 쓰인다는 것을 확인할 수 있다. 하지만 Cached Memory는 메모리를 회수할 수 있고, Swap Memory도 있으니까 느려도 돌아가긴 할 것이다. 여기서 더 서버 상황이 악화될 부분은 무엇일까? 여러 Requests가 왕창 쏟아지는 상황이나 CI/CD를 돌리는 상황일 것이라 가정했고, 확인해 보았다.
Request를 ShellScript를 작성해서 다른 EC2에서 curl 요청을 한 번에 대충 2000개 정도 쏟아보았다. 10M정도 증가하기 때문에 개발서버에 누군가 엄청난 DDos 공격을 하지않는 이상 큰 문제가 없어보였다.
두 번째로 CI/CD를 돌릴 때, 얼마나 Memory가 사용될지 확인해보았다. CI/CD를 돌리면 돌릴 수록 buff/cache 메모리가 상승하는 것을 볼 수 있었다. 즉, CI/CD를 돌릴 때, Gradle은 캐시메모리에 저장 및 사용하게 된다. 캐시메모리를 빼고 남은 메모리는 136M인 것을 볼 수 있다.
자, 그렇다면 t2.micro는 어떻게 이걸 사용하게 될까? 캐시할 수 있는 메모리가 없으므로 메모리 스왑을 이용하게 된다. 그렇게 되면 남은 캐시메모리는 KiB Swap으로 들어가게 되고, Swap Memory는 디스크를 메모리로 사용하는 것이기 때문에 RAM보다 엄청 느리다. 느린 것도 문제지만, Swap Memory를 높게 설정안하고 낮게 설정하면 메모리가 터지게 되는 것이다.
그렇기 때문에 메모리가 터지지 않게 만드는 방법이 필요하다. 첫 번째는 우리가 선택한 방법, 서버 스펙을 늘리는 것이다. 두 번째는 Swap Memory를 늘리는 것이다. 밑의 AWS 공식 링크를 보면 Swap Memory를 늘리는 방법이 있고, 현재 디스크 용량을 잘 확인하여 Memory를 늘리면 된다.
https://aws.amazon.com/ko/premiumsupport/knowledge-center/ec2-memory-swap-file/
AWS EC2 t2.micro 기본 스펙은 1G Ram, 8G Storage이다. 그러므로 FreeTier의 한계인 30G Storage로 늘리고, Swap Memory를 2G까지 늘린다면 t2.micro로 CI/CD를 사용하는 SpringBoot를 쓸 수 있다.
사실 그냥 지나칠 수도 있는 문제였다고 생각한다. t2.small로 스펙을 올리자마자 해결된 문제였기 때문이다. 하지만 나중에 t2.small에서도 똑같은 문제가 발생하고 나아가 t2.medium에서도 문제가 발생해, 그 때도 계속 스펙을 올릴 것이라고 생각하면 엄청난 비용이 발생한다. 그냥 '메모리가 부족하니까 스펙올리면 되지~~'라고 생각한다면 왜 굳이 개발자에게 비싼 돈을 주고 고용하는 걸까...? 개발자의 역할은 비용최소화의 역할도 한다고 생각하기 때문에 사이드 프로젝트에서 좋은 경험한 것 같다는 생각이 든다.