Lsiron

배포란? VM? Docker? kubernetes? 본문

개발일지/NUDDUCK

배포란? VM? Docker? kubernetes?

Lsiron 2024. 10. 21. 05:01

프로젝트를 마무리 함에 있어 마지막 관문이였던 배포.

 

엘리스에서 VM 활용 매뉴얼을 주면서 배포를 할 수 있도록 했는데, 이는 어떻게 작용하며 이 VM을 사용함에 있어 장단점은 무엇일까?

 

또한 현업에서는 Docker와 Kubernetes를 사용하는데 이유는 무엇일까? 한번 파헤쳐보자! 

VM?

먼저, VM은 하드웨어 수준에서 가상화를 통해 운영체제를 포함한 전체 시스템을 가상으로 실행하는 기술이다.

 

물리적인 컴퓨터(호스트)에서 다수의 가상 머신(게스트)을 구동할 수 있으며, 각 VM은 자체 운영체제와 애플리케이션을 실행할 수 있다. 따라서 외부에서 특정 IP 주소나 도메인을 통해 이 VM에서 구동 중인 애플리케이션에 접근할 수 있다.

 

엘리스에서 제공한 VM 활용 매뉴얼은, ssh를 통해 가상 머신에 접속하고, 필요한 패키지를 설치하는 절차를 안내했고, 이 과정을 통해, 우리는 리눅스 환경의 가상서버 에서 애플리케이션을 배포하고 실행할 수 있었다.

 

즉, VM에 ssh로 접속할 때 비밀번호 인증 방식을 사용하여 접속한 후 과정은 아래와 같았다. ( 키 인증 방식 아님 )

1. Nest.js 설치

  • ssh를 통해 접속한 리눅스 VM에서 Node.js 환경을 설정하고, Nest.js 애플리케이션을 설치.

2. Git에서 파일 가져오기:

  • Git을 사용하여, GitLab에서 프로젝트 파일을 클론.

3. Nest.js 빌드:

  • Nest.js 애플리케이션을 빌드.

4. React 빌드:

  • React 애플리케이션을 정적 파일로 빌드.

5. PM2로 Nest.js 서버 실행:

  • PM2 라이브러리로, Nest.js 서버를 백그라운드에서 실행.

6. Nginx 설치 및 설정:

  • Nginx를 설치하여, 클라이언트와 서버 사이에서 요청을 중계하는 Reverse Proxy 역할을 하도록 설정.
  • React 빌드 파일은 Nginx를 통해 정적으로 제공되며, 프론트엔드 요청은 Nginx가 처리.
  • Nest.js API는 Nginx에서 백엔드 API 요청을 리버스 프록시를 통해 처리하도록 설정하여, React 프론트엔드와 백엔드 API가 같은 도메인에서 작동하도록 구성.

7. 도메인 연결:

  • Nginx를 통해 도메인 연결도 설정하여, 도메인을 통해 애플리케이션에 접근할 수 있게 배포를 완료.

이 과정을 통해 Nest.js와 React 프로젝트가 VM 환경에서 성공적으로 배포되었다!

 

잠시 짚고 넘어갈 부분이 보여서 하나 적어본다!

 

배포를 할 때 왜 빌드를 해야하고, 빌드의 목적이 무엇일까?

 

Nest.js와 React는 각각 다른 목적과 동작 방식을 가진 애플리케이션이기 때문에, 빌드가 필요한 이유도 다르다.

 

먼저 Nest.js에서 빌드가 필요한 이유에 대해 알아보자.

 

Nest.js는 백엔드 프레임워크로, 주로 API 서버를 구축할 때 사용된다. Nest.js는 기본적으로 TypeScript로 작성되며, 이 TypeScript 코드를 Node.js에서 실행할 수 있는 JavaScript로 변환하는 과정이 빌드다.

 

1. TypeScript를 JavaScript로 변환

  • Nest.js는 TypeScript로 작성된 애플리케이션이다. Node.js는 JavaScript만 실행할 수 있으므로, TypeScript 코드를 JavaScript로 변환하는 과정이 필수이다.
  • npm run build를 통해 Nest.js 애플리케이션은 TypeScript를 JavaScript로 컴파일하여, Node.js 환경에서 실행할 수 있게 만들어준다.

2. 타입 검사 및 코드 검증

  • TypeScript는 정적 타입을 제공하므로, 빌드 과정에서 타입 오류컴파일 오류를 미리 확인할 수 있다. 이는 애플리케이션이 잘못된 타입이나 변수로 실행되지 않도록 보호해준다.

3. 최적화

  • 빌드 과정에서는 코드가 최적화되어 배포 환경에서 더 효율적으로 실행된다. 불필요한 코드가 제거되고, 더 가볍고 빠른 실행을 위해 트리 셰이킹(사용되지 않는 코드를 제거하는 과정) 등이 적용된다.

다음으로 React에서 빌드가 필요한 이유에 대해 알아보자.

 

React는 프론트엔드 라이브러리로, UI를 구축하기 위해 사용된다. React 애플리케이션은 개발 환경에서 동적으로 실행되지만, 배포 환경에서는 최적화된 정적 파일로 변환되어야 한다. 이 정적 파일은 브라우저에서 실행되며, 서버에서 동작하는 것이 아니다.

 

1. 개발 코드 -> 정적 파일 변환

  • React는 개발 환경에서 동적 개발 서버를 사용하지만, 배포 환경에서는 최적화된 정적 파일로 제공되어야 한다.
  • npm run build 명령어를 실행하면, HTML, CSS, JavaScript 파일로 컴파일되어 정적 리소스로 변환된다. 이 파일들은 브라우저에서 실행되며, 서버는 정적 파일을 제공하는 역할만 한다.

2. 코드 최적화

  • 빌드 과정에서 코드 압축과 최적화가 이루어진다. React 코드는 압축되고, 불필요한 공백, 주석 등이 제거되어 파일 크기가 작아진다.
  • 트리 셰이킹을 통해 사용되지 않는 코드를 제거함으로써 최적화된 성능을 제공한다.

3. 브라우저 호환성

  • 최신 JavaScript 문법은 모든 브라우저에서 지원되지 않기 때문에, 빌드 과정에서 구형 브라우저에서도 동작할 수 있도록 트랜스파일링이 이루어진다. 이를 통해 React 애플리케이션이 다양한 환경에서 실행될 수 있다.

확실히 개발환경에서 개발 할 때에 비해 배포를 할 땐 더욱더 신경써야 할 부분이 많다는 점. 하지만 이럴 수 밖에 없는게 배포를 했다는 것은 외부의 접근을 허용하는 동시에 유저가 사용하는 입장이니..  

 

마지막으로 VM의 장점과 단점에 대해 살펴보고 Docker와 Kubernetes로 넘어가도록 하겠다!

 

장점

  • 완전한 분리: VM은 각각 독립된 운영체제를 실행하기 때문에, 서로 간의 완전한 분리가 가능하며 보안성이 높다.
  • 다양한 OS 지원: 하나의 호스트 머신에서 여러 운영체제(Windows, Linux 등)를 동시에 실행할 수 있다.
  • 이미 성숙한 기술: 다양한 환경에서 오래 사용된 기술로 신뢰성과 안정성이 높다.

단점

  • 무거운 리소스 사용: VM은 전체 운영체제를 실행하므로 많은 CPU, 메모리, 스토리지 리소스를 소비한다.
  • 느린 부팅 시간: 운영체제 자체를 실행하므로 부팅과 종료에 시간이 많이 걸린다.
  • 오버헤드: 하이퍼바이저(가상화 소프트웨어)를 통한 가상화로 인해 성능 오버헤드가 발생한다.

엘리스에서 VM을 사용한 이유는 Docker/Kubernetes의 복잡성과 학습 곡선을 줄이고, 기본적인 서버 운영 환경을 이해하도록 돕기 위함으로 보인다! 아마 작은 프로젝트에 Docker/Kubernetes를 사용하기엔 상당히 오버헤드가 되지 않았을까 싶다..

 

허나 현업에서는 Docker와 Kubernetes를 주로 사용하기 때문에 각각에 대해 잘 알아보고 장단점을 확실하게 파악하는게 중요하다고 생각한다!

Docker?

Docker컨테이너를 사용해 애플리케이션과 그 의존성을 패키징하여 실행하는 기술이다.

 

컨테이너는 운영체제의 커널을 공유하면서 가벼운 가상화를 제공한다. 각각의 컨테이너는 독립적으로 애플리케이션을 실행하지만, VM과 달리 운영체제 전체를 포함하지 않는다.

 

이미지는 Docker에서 애플리케이션을 실행하기 위한 불변의 패키지이며, 컨테이너는 그 이미지를 기반으로 실행된 인스턴스이다.

 

장점

  • 경량성: 컨테이너는 운영체제 전체를 포함하지 않고 애플리케이션과 필요한 라이브러리만 포함하므로, VM에 비해 매우 가볍고 빠르게 실행된다.
  • 빠른 시작 시간: 컨테이너는 운영체제의 커널을 공유하므로 즉시 시작할 수 있다.
  • 이식성: 컨테이너는 동일한 이미지로 어디서든 동일하게 실행되므로, 개발 환경과 운영 환경 간의 일관성이 보장된다.
  • 자원 효율성: 하나의 호스트에서 많은 수의 컨테이너를 실행할 수 있으며, 자원을 효율적으로 사용한다.

단점

  • 운영체제 종속성: 컨테이너는 운영체제의 커널을 공유하기 때문에, 호스트 운영체제와 다른 운영체제( Windows에서 Linux 컨테이너 실행 )는 직접적으로 실행할 수 없다.
  • 보안: 각 컨테이너는 동일한 커널을 공유하므로, 완전한 격리는 VM에 비해 상대적으로 약하다.
  • 복잡성: 복잡한 애플리케이션 구성을 다루기 위해서는 추가적인 네트워킹 및 데이터 관리가 필요하다.

복잡한 운영 환경에서 애플리케이션을 신속하게 배포하고, 일관성 있는 개발 및 운영 환경을 보장하며, 자원 효율성을 극대화할 수 있기 때문에 Docker가 현업에서 많이 사용된다!

( 개발자가 로컬 개발 환경에서 만든 컨테이너는 테스트 환경, 배포 환경에서도 동일한 방식으로 실행되기 때문에 "개발 환경에서는 동작하지만 배포 환경에서는 동작하지 않는 문제"를 줄인다는 점이 매력적이다. )

 

또한 Kubernetes와 결합하여, 대규모 애플리케이션 관리와 자동화된 배포, 확장성 등의 요구를 효과적으로 해결할 수 있다는 점에서도 Docker는 매우 널리 사용된다는 점을 기억 해 두면 좋겠다!

Kubernetes?

Kubernetes는 컨테이너 오케스트레이션 플랫폼으로, 다수의 컨테이너를 자동으로 배포, 확장, 관리하는 시스템이다. Docker와 같은 컨테이너 런타임에서 생성된 컨테이너들을 효율적으로 운영할 수 있도록 도와준다.

 

Kubernetes는 컨테이너화된 애플리케이션의 자동화된 배포, 확장성 관리, 자원 할당, 복구 등을 담당한다.

 

장점

  • 자동화된 관리: 애플리케이션의 자동 배포, 확장, 복구를 제공하여 수동 개입을 줄여준다.
  • 확장성: 컨테이너 기반 애플리케이션을 대규모로 확장하거나 축소하는 작업을 쉽게 할 수 있다.
  • 자체 복구 기능: 장애가 발생한 컨테이너를 자동으로 재시작하고, 클러스터 전체의 상태를 지속적으로 모니터링한다.
  • 서비스 디스커버리 및 로드 밸런싱: 서비스 간의 통신과 로드 밸런싱을 지원하여 확장 가능한 애플리케이션을 쉽게 구축할 수 있다.

단점

  • 복잡성: Kubernetes는 매우 강력하지만, 설정하고 운영하는 것이 어렵다. 특히 소규모 프로젝트에서는 오버헤드가 될 수 있다.
  • 리소스 사용: Kubernetes 자체도 리소스를 사용하므로, 운영에 적합한 인프라가 필요하다.
  • 러닝 커브: 완전히 이해하고 제대로 활용하기까지는 많은 학습이 필요하다.

아래 내용은 현업에 몸을 담고있진 않지만 chatGPT에서 발췌를 해 보았다. 그래도 왜 사용하는지 정도는 알고 뛰어들어야 하지 않은가! 

현업에서 Docker와 Kubernetes의 중요성?

현업에서는 빠른 배포, 유연한 확장성, 일관성 있는 환경 제공이 매우 중요하다. 다음과 같은 이유로 Docker와 Kubernetes가 많은 기업에서 사용된다.

  • CI/CD 파이프라인 통합: Docker는 CI/CD 파이프라인에 쉽게 통합될 수 있으며, 이로 인해 개발, 테스트, 배포 과정이 자동화되고, 코드의 변경이 빠르게 프로덕션 환경에 반영될 수 있다.
  • 마이크로서비스 아키텍처 지원: 현업에서는 하나의 거대한 애플리케이션을 여러 개의 마이크로서비스로 분리해 관리하는 경우가 많다. Docker와 Kubernetes는 각 마이크로서비스를 독립적으로 실행하고 관리할 수 있어, 마이크로서비스 아키텍처와 매우 잘 맞다.
  • 확장성과 자원 최적화: Kubernetes는 컨테이너의 수를 자동으로 늘리거나 줄일 수 있어, 트래픽에 따라 애플리케이션을 자동으로 확장할 수 있다. 이는 특히 클라우드 환경에서 비용 절감과 자원 효율성 향상에 큰 도움이 된다.

VM과 Docker/Kubernetes의 비교

  • VM은 전체 운영체제(OS)를 가상화하여, 더 많은 자원을 소비하고 부팅 시간이 오래 걸린다. 이와 달리, Docker는 애플리케이션과 그 의존성만을 가상화하므로, 더 가볍고 빠르게 실행할 수 있다.
  • VM은 완전한 격리 환경을 제공하지만, Docker는 커널을 공유하기 때문에 가벼운 격리만 제공한다. 그럼에도 Docker는 자원 효율성과 빠른 배포에서 큰 이점을 제공하여 클라우드 인프라에서 자주 사용된다.
  • Kubernetes는 Docker를 넘어 컨테이너를 관리하고 배포하는 복잡한 작업을 자동화해 주기 때문에, 대규모 서비스에서 필수적인 도구로 자리 잡았다. 예를 들어, 서비스에 트래픽이 급증할 경우 Kubernetes는 자동으로 컨테이너 인스턴스를 추가해 트래픽을 처리할 수 있다.

배포를 정리 하면서 떠오른 말이 하나 있다. 코드만 잘 짜는 개발자는 하수라고 했던가? 여러가지 고려해야 할 부분이 상당히 많은 듯 하다. CS를 공부하면서도 느끼고 배포를 공부하면서도 느끼지만 알면 알수록 신기한 세상이다.

 

하긴 컴퓨터가 필수로 자리잡은 세상에서 컴퓨터 관련된 일을 하는 사람이 컴퓨터에 대해 잘 모르는건 너무나도 모순이다!

 

늘 새로운게 나온다는 것은 나를 괴롭히려고 세상에 나온것이 아닌 편리하게 해주려고 나온 것임을 명심하자.