3-Tier Architecture 직접 구성해보기

송선권·2024년 7월 19일

인프라 스터디

목록 보기
2/7
post-thumbnail

주제

3티어 아키텍처를 학습하고 직접 구성해본다.

3티어 아키텍처(3-Tier Architectrue)란?

x티어 아키텍처란 논리적/물리적 컴퓨팅 계층을 구성하는 소프트웨어 애플리케이션 아키텍처다. 특히 3티어 아키텍처는 수십 년간 클라이언트-서버 애플리케이션에서 보편적으로 사용되는 아키텍처다.

1티어 아키텍처


하나의 물리적인 서버에 3가지 기능(프레젠테이션, 비즈니스 로직, 데이터)을 전부 구성한다. 서버를 변경해야 하는 경우 모든 구성을 변경해야 한다.

2티어 아키텍처


서버를 클라이언트 계층과 데이터 계층으로 분리하여 운영한다. 클라이언트 계층에서 요청을 받아 로직을 수행하고 데이터 접근이 필요한 경우 데이터 계층의 데이터베이스를 사용한다.

3티어 아키텍처


서버를 클라이언트 계층(프레젠테이션 계층), 비즈니스 로직 계층(애플리케이션 계층), 데이터 계층으로 분리하여 운영한다. 각각의 계층에서 변화가 일어나더라도 서로 영향을 받지 않고 독립적으로 운영된다.

구성할 환경 설계

목표


우분투 하나를 올리고 nginx와 클라이언트 정적 파일, 스프링 부트, MySQL을 넣어 3티어 아키텍처 서버를 구축하고자 한다. 물리적으로는 1티어이지만 논리적으로는 3티어라고 할 수 있다.

실제 결과물


진행하기에 앞서 결과물을 먼저 짚고 넘어가겠다. 정적 파일에서 애플리케이션의 api를 호출하도록 작성해야 한다. 하지만 api를 호출하는 정적 파일을 작성하기에는 관련 지식이 부족하여 시간이 많이 들기에 애플리케이션에서 뷰 파일을 제공하도록 구성했다. 결과적으로 2티어 아키텍처가 되어버렸지만(..) 정적 파일을 구성하고 NginX에서 정적 파일 방향으로 중계해주는 로직만 추가하면 3티어 아키텍처가 완성된다.

1. Ubuntu 구축

별도 클라우드나 기기 없이 서버를 구축하고자 맥에 도커를 사용해 우분투를 띄우기로 했다.
맥은 arm 기반이지만 보편적으로 사용되는 서버는 amd64 기반의 우분투이기에 amd64 아키텍처로 지정하여 우분투를 올렸다.

참고 자료) Apple MAC M1에서 linux/amd64로 docker 빌드하기

우분투 도커 이미지에는 동작을 위한 최소한의 프로그램만 설치되어 있다. 때문에 도커로 우분투를 올려 사용하게 되면 "이게 왜 안돼?"같은 상황이 많이 발생하지만 침착하게 필요한 프로그램들을 직접 설치해주면 된다.

도커 기반 우분투이기에 다른 점

이후 진행하는 환경 구성 과정에서 ufw 방화벽을 개방해주어야 할 수 있는데, 도커 기반 우분투에서는 ufw 방화벽을 정상적으로 사용할 수 없기 때문에 관련 과정을 생략했다.

systemctl도 사용할 수 없다. 대신 service를 사용하면 된다.
ex) service mysql start

sudo도 사용할 수 없는데, 이미 root로 접속되기 때문에 sudo를 생략하고 명령어를 작성하면 된다.

2. 데이터 계층 구성

MySQL 설치

sudo apt update
sudo apt install mysql-server

사용자 권한 설정

만약 우분투에서 구동중인 MySQL을 외부(ex. MySQL Workbench)에서 접근하고자 한다면 사용자 권한을 설정해줘야 한다. 관련한 내용은 참고 자료를 확인하자.

참고 자료) MySQL의 계정 생성 및 권한 부여 방법

3. Spring Boot 구성

원래는 비즈니스 로직 계층을 담당해야 하지만 2티어 계층 구조가 되면서 클라이언트 계층을 담당하게 된 Spring Boot를 구성해보자.

Spring boot는 별도로 의존 프로그램을 설치하지 않아도 된다. 대신 빌드를 위한 jdk만 설치해두면 되는데, 프로젝트에 맞는 jdk를 설치해줘야 한다.

여기서는 빌드 명령어를 gradle 기준으로 설명한다.

# jdk 설치
sudo apt update
sudo apt install openjdk-17-jdk
java --version

# git 저장소에서 프로젝트 가져오기
git clone [repository url]

# 프로젝트 빌드 (프로젝트 경로로 들어가서 진행)
./gradlew clean build -x test
# 프로젝트 실행
cd build/libs/
nohup java -jar [빌드된 jar 파일명] &

프로젝트 실행 로그는 별도로 설정하지 않으면 프로젝트를 실행한 경로의 nohup.out에 기록된다.

프로젝트 코드가 수정될 때마다 매 번 직접 빌드 명령어를 입력하기 번거롭다면 빌드 과정을 쉘 파일로 만들어 간소화할 수 있다. 관련 정보는 참고 자료를 참조하자.

참고 자료) Ubuntu에 SpringBoot 프로젝트 배포하기(Maven, Gradle)

4. NginX 구성

api 서버 요청으로 들어온 도메인은 Spring Boot로, 웹페이지 접속 요청으로 들어온 도메인은 정적 페이지로 연결시켜주기 위해 NginX를 구성한다. (이 결과물에서는 둘을 구분하지 못했지만 구분한다면 3티어 아키텍처가 된다.)

NginX란?
트래픽이 많은 웹사이트의 서버(WAS)를 도와주는 비동기 이벤트 기반구조의 웹 서버(Web Server) 프로그램이다.
공식문서에서는 "NGINX는 고성능, 확장성, 고가용성 웹서버, 역방향 프록시 서버 및 웹 가속기(HTTP 로드밸런서, 콘텐츠 캐시 등의 기능 결합)이다." 라고 소개하고 있다.

출처) NginX란?

# NginX 설치
sudo apt update
sudo apt install nginx

# NginX 테스트
nginx -t

# NginX 경로: /etc/nginx/

nginx에서 중계할 파일 또는 프로그램에 대해 설정을 해줘야 한다.

# 설정 파일 경로
# /etc/nginx/sites-enabled/default or other
# /etc/nginx/nginx.conf

# 설정 예시 - 정적 파일
server {
    listen 80;
    server_name example.com;

    root /var/www/html;
    index index.html index.htm;

    location / {
        try_files $uri $uri/ =404;
    }
}

# 설정 예시 - 애플리케이션
server {
	listen 80;
	server_name api.example.com;

	location / {
		# 애플리케이션이 동작중인 포트 번호로 연결
		proxy_pass http://localhost:8080;
	}
}

여기까지만 하면 기본적인 3티어 아키텍처 서버 구성은 끝난다. 요청이 들어오면 NginX에서 받아 클라이언트 계층의 정적 파일로 넘겨주고, 이를 통해 클라이언트에서 다시 api 요청을 보낸다면 NginX에서 비즈니스 로직 계층의 애플리케이션으로 요청을 넘겨준다. 그리고 애플리케이션에서는 데이터 계층의 데이터베이스에 접근하여 데이터를 관리한다.

이 이후는 개인 컴퓨터를 서버로 올리기 위한 부가적인 설정에 대해 다룬다.

5. 도메인 연결

포트 개방

완성된 서버를 외부에서 접속하려면 우선 서버가 올라가있는 포트를 외부에서 접근할 수 있도록 개방해야 한다.

현재 서버는 도커 컨테이너로 올라가 있기 때문에 로컬 환경의 포트 번호와 매핑이 필요하다. 하지만 안타깝게도 실행중인 컨테이너의 포트 변경은 불가능하다. 대신 컨테이너를 이미지로 떠서 다시 컨테이너로 올리며 포트 설정을 해주는 방법으로 해결할 수 있다. 관련한 방법은 참고 자료를 참조하자.

참고 자료) 기존 컨테이너의 포트 변경하기, Docker 포트 바인딩

로컬 포트와 컨테이너 속 서버의 매핑을 마쳤다면 외부에서 로컬 환경에 접속할 수 있도록 개방해줘야 한다. 사용중인 공유기 설정 페이지로 진입하여 서버로 올릴 포트 번호를 열어준다(포트포워딩).

기본적으로 HTTP 요청은 80 포트로, HTTPS 요청은 443 포트로 지정되어 있다.
HTTP와 HTTPS의 포트 번호 유래가 궁금하다면 아래 게시글을 참고하자.
HTTP:80, HTTPS:443. 왜 80, 443번일까? 이유는?

도메인 구매

아이피 주소가 아니라 일반적인 도메인(example.com) 형태의 주소를 통해 접근하도록 하려면 도메인을 구매하여 PC IP와 연결해줘야 한다. 내도메인.한국에서 무료로 도메인을 등록할 수 있는데, 회원가입 후 원하는 도메인을 골라 IP연결(A)로 PC의 외부 IP를 기입해주면 된다.

위의 과정을 마치면 그럴듯한 도메인을 가진 서버가 구축되어 외부에서도 접속이 가능해진다.

6. SSL 설정

certbot 구성

지금 구성으로는 서버 접속은 가능하지만 https://로 접속을 시도하면 실패한다. 이는 SSL/TLS 인증서가 없기 때문이고 이 인증서는 인증 기관으로부터 별도로 발급받아야 한다. 여기서는 무료로 인증서를 발급받을 수 있는 certbot을 사용한다.

# certbot 설치
sudo apt update
sudo apt install python3-certbot-nginx

# SSL/TLS 인증서 발급
sudo certbot --nginx -d example.com -d www.example.com

인증서 발급을 마치고 nginx 설정 파일에 다시 들어가보면 certbot이 자동으로 설정을 수정해둔 것을 확인할 수 있다.

인증서 자동 갱신

이렇게 certbot으로 발급받은 Let's Encrypt 인증서는 90일 후에 만료되기 때문에 자동 갱신 설정을 해두는 것이 좋다. 여기서는 crontab을 사용한다.

crontab -e

# crontab에 아래 내용 추가
# 의미: 매일 오전 2시에 인증서를 갱신한다.
0 2 * * * /usr/bin/certbot renew --quiet

참고 자료

3계층 아키텍처란? | IBM
3계층 구조 (3 Tier Architecture)
Apple MAC M1에서 linux/amd64로 docker 빌드하기
우분투에 MySQL 설치하기
MySQL의 계정 생성 및 권한 부여 방법
NginX란?
Ubuntu Nginx 설치
기존 컨테이너의 포트 변경하기
Docker 포트 바인딩
HTTP:80, HTTPS:443. 왜 80, 443번일까? 이유는?

0개의 댓글