최근 진행중인 프로젝트에서는 아래 그림처럼 하나의 EC2에 WAS, NginX, 그리고 Database를 함께 구성하고 있었다.
하지만 이렇게 구성하게 되면 문제가 발생할 수 있다는 것을 알게 되었고, DB를 따로 분리하기로 했다.
WAS와 DB를 동일한 EC2 인스턴스에 구성하게 되면, 서로 동일한 리소스를 공유하기 때문에 전체적인 성능이 저하될 수 있다.
예를 들어, DB 작업이 많을 경우 DB 프로세스가 CPU를 많이 점유하게 될텐데, WAS 프로세스는 그만큼 CPU 가용성이 떨어진다.
단일 장애점 문제란 시스템 구성 요소에 장애가 발생할 경우 전체 시스템이 중단되는 문제를 말한다.
만약 EC2 인스턴스에 장애가 발생한, WAS와 DB 모두 다운되어 전체 서비스가 중단될 것이다.
사실 AWS 자체에서 문제가 발생할 가능성은 거의 없으며, 혹여나 발생하더라도 AWS는 상황을 감지하여 대응하는 여러 매커니즘을 제공한다.
하지만 문제는 '나' 자신이다,,
아무것도 모르는 내가 EC2 인스턴스 관련 설정을 조금만 건드렸다가 문제가 발생하더라도, 절대 DB까지 영향이 미쳐서는 안 된다고 생각한다.
사실 위에서 살펴본 이유 외에도 확장성, 보안 등 여러 이유가 더 존재한다. 하지만 내가 이해할 수 없는 영역이기도 하고, 이 정도 이유만으로도 동일 인스턴스에 구성하는 것은 좋지 않다는 것을 알았기에 분리를 결정했다.
DB를 별도의 인프라에 구성하기로 결정했다면, 다음으로 어떤 방식으로 분리할지 선택해야 한다.
하나는 EC2 인스턴스를 하나 더 만들고 거기에 DBMS를 설치하는 방식이고, 다른 하나는 AWS에서 제공하는 RDS(Relational Database Service)를 사용하는 것이다.
MySQL과 Oracle 같은 RDBMS를 새로운 EC2 인스턴스에 설치하여 사용하면 OS, 네트워크, 권한 등 거의 모든 설정을 내 마음대로 즐길 수 있다. 즉, 높은 유연성을 제공한다.
비용도 RDS에 비해 낮기 때문에, 만약 학생이라 서버 비용에 부담이 된다면 EC2에 설치하는 것도 좋은 선택이 될 것이라 생각한다.
RDS는 AWS에서 제공하는 관계형 데이터베이스 관리 서비스로 운영, 확장 등 다양한 부분을 자동화하여 관리해준다.
RDS는 EC2에 비해 유연성이 떨어지고 비용도 높은 편이지만, 장애 조치 지원 등 높은 편리성을 제공한다.
두 방식의 차이가 잘 와닿지 않는다면 이렇게 생각해보자.
EC2는 내가 직접 음식을 요리하는 행위와 똑같고, RDS는 전문 요리사를 고용하는 것과 똑같다.
내가 직접 요리할 경우 저비용으로 내 입맛에 맞춰 자유롭게 할 수 있지만, 그만큼 상당한 기술과 시간이 필요하다.
반면 전문 요리사를 고용할 경우 나는 요리에 대한 걱정 없이 편하게 음식만 맛 보면 되겠지만, 입맛대로 조절하기 어려우며 상당한 비용이 든다.
이러한 장단점을 EC2와 RDS에 빗대면 이해하기 쉽다.
EC2에 DB를 직접 설치해서 사용할 경우 저비용으로 서버 및 DB에 대한 모든 권한과 OS, DB 엔진 구성을 자유롭게 선택할 수 있지만, 그만큼 상당한 지식과 시간이 필요하다.
반면 RDS를 사용할 경우 AWS에서 여러 편리한 기능을 제공함으로써 내가 들이는 시간을 대폭 줄일 수 있지만, 자유롭게 설정할 수 없으며 EC2보다 상대적으로 더 많은 비용이 들게 된다.
네트워크, OS, DB 등 다양한 설정을 내 입맛대로 구성하기에는 지금 내 지식과 시간으로는 어림도 없다.
차라리 여러 서비스를 제공하는 RDS를 사용함으로써, 성능 개선이나 개인 학습 등 현재 중요한 부분에 집중하는 것이 낫다고 판단했다.
또한, 프로젝트의 규모를 봤을 때 두 방식의 비용 차이가 크게 체감될 수준이 아니다.
이러한 이유로 나는 EC2 대신 RDS를 사용하기로 결정했다.
RDS를 사용하기로 결정한 뒤 바로 프로젝트에 적용해봤다.
RDS 인스턴스 생성 자체는 여러 블로그를 참고하며 쉽게 할 수 있지만, 주의할 점이 한 가지 있다.
바로 퍼블릭 액세스 관련 설정이다.

퍼블릭 액세스는 말 그대로 데이터베이스에 퍼블릭 IP 주소를 할당하여 어디서든 해당 DB에 접근할 수 있도록 하는 것이다.
문제는 이렇게 모두가 데이터에 접근할 수 있도록 훤히 열어놓는 것은 쉽게 공격을 받거나, 불필요한 트래픽이 증가한다는 것이다.
따라서 나는 퍼블릭 액세스를 허용하지 않음으로써, VPC 내부 네트워크를 통해서만 RDS 인스턴스에 접근하도록 했다.
VPC(Virtual Private Cloud)는 퍼블릭 클라우드 환경에서 사용할 수 있는 가상 네트워크를 말하며, 우리는 이 VPC를 적용하여 격리된 네트워크 환경을 구축하고 보안과 관리의 유연성을 높일 수 있다.
VPC에 대한 자세한 내용은 여기를 참고하자.
RDS 인스턴스 생성과 모든 설정을 끝내면 아키텍처는 다음과 같이 그려진다.
이처럼 RDS를 사용해 DB를 별도 인프라에 구성하면, EC2가 다운되어도 DB에는 영향을 미치지 않아 안정성을 높일 수 있게 된다.
나는 DB를 분리한 뒤 평소처럼 workbench로 DB 서버에 접근하려 했지만 가볍게 실패했다.
이는 아까 RDS 인스턴스를 생성할 때 퍼블릭 액세스를 막아두었기 때문이다. 생각해보면 퍼블릭 액세스를 허용하지 않는다는 것은 곧 VPC 외부로부터 접근을 막는다는 것이므로 실패하는게 당연하다.
따라서 우리는 동일한 VPC에 존재하는 EC2에 접근하여 EC2 권한으로 DB에 접근해야 한다.
EC2 권한으로 DB에 접근하는 방법에는 여러가지가 존재하는데, 나는 일반적으로 사용되는 SSH 터널링 방식으로 접근했다.
SSH 터널링(또는 SSH 포트포워딩)은 SSH 연결을 통해 터널을 생성하고, 터널을 통해 네트워크 서비스로 안전하게 접근하는 방법을 말한다.
SSH(Secure Shell)는 원격 호스트에 접속하기 위해 사용되는 보안 프로토콜이다.
EC2 인스턴스를 생성할 때 키페어를 생성하면
*.pem이라는 알 수 없는 파일이 다운로드 되었을 것이다. 이 파일에는 SSH가 적용되어 있기 때문에 우리가 외부의 위협으로부터 보호받으면서 원격으로 서버에 접속할 수 있었던 것이다.
SSH는 서버를 원격으로 제어해 클라이언트와 목표 시스템 사이에서 안전한 통신 터널을 제공한다.
클라이언트는 이 터널을 통해 목표 시스템에 접근할 수 있는데, 이 과정을 SSH 터널링이라고 한다.
즉, 지금 상황에서는 EC2 인스턴스가 중계 서버 역할을 수행하며, 우리가 DB에 안전하게 접근할 수 있도록 EC2 인스턴스가 3306 포트로 포워딩하는 것이다.
여기를 참고하면 SSH 터널링에 대해 더 자세하게 알 수 있다.
이제 본격적으로 SSH 터널링을 통해 DB에 접근해보자.

SSH 터널을 사용해 DB에 접근하겠다는 의미로 Connection Method를 Standard TCP/IP over SSH로 선택한다.
SSH Hostname에는 SSH 서버의 주소를 입력하면 되는데, 여기서 SSH 서버는 EC2 인스턴스를 가리킨다. 따라서 EC2 인스턴스의 IP 주소를 입력한다.
ex) x.x.x.x:22 (포트 번호는 생략 가능)
SSH Username과 SSH Password는 EC2 인스턴스 접속 계정과 비밀번호를 입력한다.
이때 비밀번호는 SSH Key File로 대체 가능하다.
SSH Key File은 SSH 서버에 접속하기 위한 key 파일을 의미한다. EC2 인스턴스 생성 시 다운로드 받은 *.pem 파일의 경로를 입력하자.
MySQL Hostname과 Port에는 우리가 접근하고자 하는 DB의 주소와 포트 번호를 입력한다.
Username, Password에는 MySQL 접속 계정과 비밀번호를 입력한다.