본문 바로가기
BackEnd/Project

[PharmNav] Ch04. 개발 환경 구성 & 도커

by 개발 Blog 2024. 9. 1.

공부 내용을 정리하고 앞으로의 학습에 이해를 돕기 위해 작성합니다.

이번 장에서는 프로젝트의 개발 환경을 구성하고, Docker를 사용하여 애플리케이션을 컨테이너 화하는 과정을 자세히 설명한다. 이 과정에서는 프로젝트의 생성부터 GitHub 연동, 필요한 플러그인의 설치, 그리고 Docker를 사용한 배포까지 단계별로 진행된다.

 

프로젝트 생성 및 깃허브 연동

먼저, IntelliJ IDEA에서 새로운 Spring Boot 프로젝트를 생성한다. 이 프로젝트에서는 다음과 같은 기본적인 의존성을 추가한다.

 

플러그인 설치 및 설정

IntelliJ IDEA에서 개발 편의성을 높이기 위해 다음과 같은 플러그인들을 설치한다.

  • Spock: Groovy 기반의 테스트 프레임워크로, JUnit보다 간편하게 테스트 코드를 작성할 수 있다.
  • Handlebars: 프론트엔드 템플릿 엔진으로, 간단한 뷰를 만들 때 유용하다.
  • Lombok: 코드에서 반복적인 부분을 줄여주는 플러그인으로, @Getter, @Setter 등을 자동으로 생성해 준다.

Lombok 활성화

Lombok을 사용하기 위해서는 IntelliJ IDEA에서 Lombok을 활성화해야 한다. Settings > Build, Execution, Deployment > Compiler > Annotation Processors에서 "Enable annotation processing" 옵션을 체크해 준다.

 

의존성 설정

아직 데이터베이스와 관련된 설정을 하지 않았기 때문에 JPA와 MariaDB 설정은 주석 처리해 두었다. 다음은 build.gradle의 의존성 설정 예시이다.

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.3.3'
    id 'io.spring.dependency-management' version '1.1.6'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
//    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
//    runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
    annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
    useJUnitPlatform()
}

 

GitHub 연동

프로젝트를 생성한 후, GitHub와 연동하여 버전 관리를 시작한다. 다음 명령어들을 사용하여 로컬 프로젝트를 GitHub 리포지토리에 연결한다.

git init
git remote add origin [리포지토리 주소]
git add .
git commit -m "first commit"
git push origin main

 

도커 및 도커 컴포즈 설정

이제 Docker를 사용하여 애플리케이션을 컨테이너 화하고, 이를 통해 배포하는 방법을 설명한다.

 

도커란?

  • 컨테이너 기반의 가상화 플랫폼: Docker는 컨테이너를 사용하여 응용 프로그램을 더 쉽게 만들고, 배포하고, 실행할 수 있도록 설계된 도구이다. 각 컨테이너는 응용 프로그램을 실행하는 데 필요한 모든 것을 포함하고 있어, 환경에 구애받지 않고 일관된 실행 환경을 제공한다.
  • 서버 환경 통일: Docker는 여러 서버에서 동일한 환경을 보장할 수 있어, "A 서버에서는 되는데 B 서버에서는 안 되는" 문제를 해결할 수 있다.

도커 왜 사용해야 될까?

  • 서버 환경 통일: 동일한 기능을 수행하는 여러 서버 간의 환경 차이가 문제가 될 수 있다. Docker는 서버마다 동일한 환경을 제공하여 이러한 문제를 해결할 수 있다.
  • 자동 확장(Auto Scaling): Docker는 동일한 환경을 유지하기 때문에 서버의 확장성과 관리를 더욱 용이하게 해 준다.

하이퍼바이저 기반 가상화와 Docker의 차이점

전통적인 배포 방식에서는 한 대의 서버에서 하나의 애플리케이션만 운영하는 방식이 일반적이었다. 그러나 이 방식은 자원의 효율성이 떨어지며, 여러 애플리케이션을 동시에 실행하는 데 한계가 있다. 이를 개선하기 위해 등장한 것이 하이퍼바이저 기반 가상화이다.

 

 

하이퍼바이저 기반 가상화

  • 하이퍼바이저는 호스트 시스템(예: 윈도우, 리눅스 등)에서 다수의 게스트 OS(가상 머신)를 구동할 수 있게 해주는 소프트웨어이다.
  • 각 가상 머신(VM)은 독립적으로 동작하며, 자신의 운영 체제와 필요한 라이브러리 및 애플리케이션을 포함한다.
  • 이러한 구조는 물리적인 서버 한 대에서 여러 개의 가상 머신을 동시에 운영할 수 있게 해 준다. 따라서 서버 자원을 보다 효율적으로 활용할 수 있다.

Docker의 등장과 차이점

Docker는 하이퍼바이저 기반 가상화에서 한 단계 더 발전한 개념이다. Docker는 하이퍼바이저 구조를 토대로 등장했으며, VM보다 훨씬 가볍게 동작한다. Docker가 가볍게 동작하는 이유는 다음과 같다:

  • OS 레벨 가상화: Docker는 전체 운영 체제를 가상화하는 대신, 호스트 OS 커널을 공유하는 컨테이너 방식으로 애플리케이션을 격리한다. 즉, 각 컨테이너는 독립된 애플리케이션 환경을 가지지만, 운영 체제의 커널은 호스트와 공유한다.
  • 더 적은 오버헤드: 하이퍼바이저 기반 가상화는 각 VM이 독립적인 운영 체제를 포함하므로, 리소스 소모가 크다. 반면, Docker 컨테이너는 호스트 OS 커널을 공유하므로 리소스 소모가 적고, 빠르게 실행된다.
  • 유연한 배포 및 확장: Docker는 컨테이너의 경량화 덕분에 더 빠른 시작 시간과 유연한 배포 및 확장이 가능하다. 이는 클라우드 환경에서 특히 유리하다.

도커 컨테이너와 이미지

  • 이미지: 코드, 런타임, 시스템 도구, 시스템 라이브러리 및 설정과 같은 응용 프로그램을 실행하는 데 필요한 모든 것을 포함하는 패키지이다. 이미지는 Docker Hub와 같은 서비스에서 버전 관리할 수 있다.
  • 컨테이너: Docker 이미지를 독립된 공간에서 실행할 수 있게 해주는 기술로, 프로그램을 실행하는 데 필요한 설정이나 종속성들을 포함하는 이미지의 인스턴스이다.

도커 파일 이란?

Dockerfile은 Docker 이미지를 생성하기 위해 필요한 패키지, 의존성, 소스 코드 등을 기록한 파일로, 이를 기반으로 이미지를 생성할 수 있다. 즉, 이미지는 컨테이너를 실행하기 위한 모든 정보를 가지고 있기 때문에 새로운 서버를 추가할 때 의존성 파일을 다시 컴파일하거나 설치할 필요가 없다.

 

도커 파일 주요 명령어

  • FROM: 새로운 이미지를 생성할 때 기반으로 사용할 이미지를 지정한다. 예를 들어, JDK 17이 포함된 컨테이너를 사용하려면 FROM openjdk:17로 시작한다.
  • ARG: 이미지 빌드 시점에서 사용할 변수를 지정한다.
  • COPY: 호스트에 있는 파일이나 디렉토리를 Docker 이미지의 파일 시스템으로 복사한다.
  • ENV: 컨테이너에서 사용할 환경 변수를 지정한다.
  • ENTRYPOINT: 컨테이너가 실행될 때 항상 실행되어야 하는 커맨드를 지정한다.

예시 Dockerfile

FROM openjdk:17
ARG JAR_FILE=build/libs/app.jar
COPY ${JAR_FILE} ./app.jar
ENV TZ=Asia/Seoul
ENTRYPOINT ["java", "-jar", "./app.jar"]

 

도커 컴포즈란?

Docker Compose는 멀티 컨테이너 Docker 애플리케이션을 정의하고 실행하는 도구이다. 예를 들어, 애플리케이션, 데이터베이스, Redis, Nginx 등을 각각 독립적인 컨테이너로 관리할 수 있다.

  • 다중 컨테이너 관리: Docker Compose를 통해 여러 개의 Docker 컨테이너로 구성된 서비스를 구축하고, 네트워크 연결과 실행 순서를 자동으로 관리할 수 있다.
  • docker-compose.yml: 이 파일을 작성하여 여러 개의 컨테이너를 한 번에 실행하고 관리할 수 있다.

실습 : Docker 설치 및 환경 설정

도커 설치

Docker 공식 사이트에서 자신의 OS에 맞게 Docker를 설치한다.

https://docs.docker.com/desktop/

 

아래 사이트에서 무료 플랜으로 회원가입을 한다. 

https://hub.docker.com/

 

설치 후 명령어로 설치와 로그인 인증을 확인한다.

 

Jar 파일 생성 및 Dockerfile 작성

인텔리제이 터미널에서 다음 명령어로 jar파일을 생성한다.

./gradlew build

 

build.gradle에서 jar 파일 이름을 변경한다.

bootJar{
    archiveFileName = 'app.jar'
}

 

Clean 후, 다시 빌드하여 이름을 확인한다.

 

Dockerfile 작성

Jar 파일을 Docker 컨테이너 내로 복사하고, 이를 실행하기 위한 Dockerfile을 작성한다:

FROM openjdk:17
ARG JAR_FILE=build/libs/app.jar
COPY ${JAR_FILE} ./app.jar
ENV TZ=Asia/Seoul
ENTRYPOINT ["java", "-jar", "./app.jar"]

 

Docker 이미지 빌드 및 실행

작성한 Dockerfile을 기반으로 이미지를 빌드한다.

docker build -t eunhan97/application-project-test .

 

빌드된 이미지를 확인한다.

docker images

 

이미지를 실행한다.

docker run -p 8080:8080 eunhan97/application-project-test:latest

 

Docker 컨테이너 상태 확인 및 접속

Docker의 실행 상태를 확인하고, 컨테이너 내부로 접속한다.

docker ps
docker exec -it [컨테이너ID] bash

 

이번 글에서는 프로젝트의 개발 환경을 구성하고, Docker를 활용하여 애플리케이션을 컨테이너 화하는 방법을 다뤘다. Docker를 통해 일관된 개발 및 배포 환경을 구축할 수 있으며, 서버 간의 환경 차이로 인한 문제를 최소화할 수 있다