Skip to content

Backend 기술 스택

최우창 edited this page Aug 17, 2023 · 26 revisions

기술 스택

image

Backend

  • Java 17
  • Spring Boot 3.1.1
  • Swagger
  • Lombok
  • Spring Data JPA
  • H2 Database
  • MySQL
  • JWT
  • RestAssuredMockMvc

Infra

  • Github Action
  • Jenkins
  • Docker
  • Nginx

📝 Java 17 & Spring 3.1.1

스프링 부트 3.x 버전부터는 Java17을 기반으로 작성된 프레임워크입니다. Java 17은 record, instanceOf, multiline 문자열 등 새로운 기능이 포함된 최신 LTS 버전이기 때문에 해당 기능들을 기본으로 가져갈 수 있다는 장점이 존재합니다.

Spring AOT

Spring AOT(Ahead Of Time) 엔진은 빌드 시 Spring 애플리케이션을 분석하고 최적화하는 도구이다. AOT 엔진은 GraalVM이 필요로 하는 설정을 생성해주는데, 해당 설정을 통해 자바 프로젝트이지만 네이티브 바이너리로 만들어 실행 시간과 메모리 사용량을 획기적으로 줄여줍니다.

요약하자면 기존 JVM 방식에서는 프로그램이 올라갈 때 바이트 코드를 컴파일하지만, AOT는 바이트코드를 분석하고 최적화해서 실행하기에 빠르고 메모리 효율적인 코드를 생성합니다.

따라서 성능 향상을 경험할 수 있다고 판단하였습니다.

지원 기간

스크린샷 2023-08-11 오후 2 09 20

우선 프로젝트를 진행할 시점에 3.1.x 버전이 출시된 상태였습니다. 비교 대상이었던 2.7.x 버전과 비교하였을 때 지원 기간이 상대적으로 길어서 장기적으로 오래 사용하기 위해 선택하였습니다.

프로젝트 생성

스크린샷 2023-08-11 오후 2 06 09

위의 사진에서는 확인할 수 없지만, 프로젝트를 시작할 시점에서는 Spring Initializr 사이트에서 가장 최근의 3.x 버전이 3.1.1 버전이었습니다. 따라서 3.1.1 버전으로 프로젝트를 생성하였습니다.

참고


📝 Swagger

Swagger는 API를 문서화하고 테스트할 수 있는 오픈 소스 프레임워크입니다. 테스트를 기반으로 문서화를 진행하는 Spring REST Docs와 달리 어노테이션을 통해 간편하게 API 문서를 자동으로 만들 수 있습니다. 또한 자체적으로 사용자 친화적인 UI도 제공해 주고 있으므로 문서를 쉽게 읽고 테스트할 수 있습니다.

문서화에 사용되는 어노테이션이 프로덕션 코드에 존재하기에 가독성을 떨어뜨린다는 단점도 존재합니다. API 스펙이 변했을 때 어노테이션 메타 데이터를 적절하게 바꿔주지 않으면 잘못된 정보를 전달할 수 있습니다.

저희 팀에서 Spring REST Docs와 비교하여 Swagger를 선택한 이유는 다음과 같습니다.

1. 개발 속도

스프린트마다 빠르게 개발을 진행해야만 하는 상황이었기 때문에 복잡한 설정과 학습 난도가 있는 Spring REST Docs보다는 간편하게 API 문서화가 가능한 Swagger를 사용하기로 하였습니다.

2. 사용자 친화적인 UI

Swagger는 Spring REST Docs와 달리 사용자 친화적인 UI를 제공하기에 문서화에 있어 큰 장점으로 다가왔습니다.

3. 단점 보완

컨트롤러에 붙어 있는 어노테이션은 컨트롤러 인터페이스를 생성해서 해당 위치로 옮길 수 있습니다. 이를 통해 실제 로직이 담겨있는 코드의 가독성을 높일 수 있도록 개선할 수 있습니다.

현재는 위와 같은 장점으로 인해 Swagger를 선택하였지만, 추후 Swagger의 단점을 직접 경험하게 되었을 때 Spring REST Docs로 기술을 바꿔보는 과정도 직접 경험해보고자 합니다.


📝 Lombok

롬복은 자바에서 제공하는 라이브러리로 getter, setter, toString등의 반복되는 보일러 플레이트 코드를 어노테이션 형태로 대체하여 사용할 수 있도록 도와줍니다.

1. 반복되는 코드 제거 및 코드 가독성 상승

보일러 플레이트 코드를 어노테이션으로 대체하여 프로덕션에서 가독성 좋은 코드를 유지할 수 있습니다.

2. 편한 설정 및 팀원들의 이해도

롬복을 설정하는 것을 어려운 일이 아닙니다. 누구든지 쉽게 설정하고 사용할 수 있습니다. 또한 팀원들 모두 롬복에 대해 익숙하고 이에대한 장점을 확실하게 알고 있었습니다.

물론 무분별한 롬복 사용은 가독성을 해칠 수도 있지만, 실제로 사용해봤다면 단점보다 장점이 훨씬 와닿는 라이브러리라고 생각했습니다. 따라서 보투게더에서는 롬복을 도입하여 사용하기로 결정했습니다.


📝 Spring Data JPA

JPA는 자바 진영의 ORM 기술 표준입니다.. Spring Data JPA는 JPA를 더 쉽게 사용하기 위해 스프링에서 제공하고 있는 프레임워크 입니다.

Spring Data JPA의 장점

  1. 사용 용이성: Spring Data JPA의 주요 이점 중 하나는 감소된 상용구 코드입니다. Repository 인터페이스를 정의하는 방법을 제공하고 최소한의 코드로 런타임 시 구현을 제공합니다.
  2. 편의성: Spring Data JPA는 메서드 이름에서 직접 쿼리를 구성하기 위한 도메인별 언어를 제공합니다. 예를 들어 'findByNameAndAge'라는 메서드는 자동으로 이름과 나이로 엔터티를 찾는 쿼리로 해석됩니다.
  3. Spring 생태계와의 통합: Spring 생태계의 일부이기 때문에 다른 Spring 모듈과 원활하게 통합됩니다.
  4. 표준화된 데이터 액세스: 데이터베이스 데이터에 액세스하는 표준화된 방법을 제공하여 어떻게 쓰이든지 일관된 동작을 보장합니다.
  5. 유연성: 개발자는 제공된 CRUD 방법을 자유롭게 사용하거나 따로 정의할 수 있습니다. 또한 필요한 경우 JPQL 또는 기본 SQL 쿼리로 자동 생성된 쿼리를 재정의할 수 있습니다.

📝 H2 Database

H2 Database는 용량이 매우 가볍고 디스크 기반, 인메모리 데이터베이스 입니다. 애플리케이션에 내장되어서 따로 설치 필요 없이 사용할 수 있으며 로컬이나 테스트 환경에서 인메모리 DB를 통해 빠르게 테스트가 가능합니다. 또한 브라우저에서 접속이 가능한 콘솔도 제공이 되어지기 때문에 UI를 통해 쉽게 DB의 데이터를 확인할 수 있는 등 여러 장점이 있습니다. 다만 단점이라고 하면은 인메모리로 사용할시 데이터가 휘발성이긴 하지만 개발용이나 테스트용도로는 문제가 없으며 운영서버로는 MySql를 사용하기 때문에 따로 큰 이슈는 없었습니다. 이와 같은이유로 H2 Database를 사용하였습니다.


📝 MySQL

MySQL의 장단점

  1. 장점
  • 무료입니다.
  • 일반적으로 속도가 빠른 편에 속합니다.
  • 많은 사용자를 가지고 있습니다.
  • Replication에 대해 충분히 테스트 되었습니다.
  • 풍부한 Reference가 존재합니다.
  • 테이블당 파일 하나의 storage를 갖기 때문에 백업이 편리합니다.
  • Context switching과 공용자원 접근 속도가 빠릅니다. (Multi-Thread)
  • 업그레이드 시 데이터의 덤프 및 restore가 불필요합니다.
  1. 단점
  • 트랜잭션 지원이 완벽하지 않습니다. (MyISAM)
  • 사용자 정의 함수(UDF)의 사용이 쉽지 않고 유연하지 못합니다.

Oracle과 비교했을 때 MySQL의 장단점

  1. 장점:
  • 오픈 소스: MySQL은 오픈 소스이므로 무료로 사용할 수 있으며 소스 코드는 대중에게 공개됩니다.
  • 비용 효율적: 오픈 소스이므로 일반적으로 중소 규모의 애플리케이션에 더 비용 효율적입니다.
  • 커뮤니티 지원: 대규모 사용자 커뮤니티는 MySQL용으로 특별히 개발된 많은 온라인 리소스, 포럼 및 도구를 찾을 수 있음을 의미합니다.
  • 사용하기 쉬움: MySQL은 종종 일부 엔터프라이즈 데이터베이스보다 기본 애플리케이션에 대해 더 간단하고 직관적인 것으로 간주됩니다.
  • 통합: 많은 소프트웨어 스택, 특히 LAMP 스택(Linux, Apache, MySQL, PHP/Perl/Python)과 잘 통합됩니다.
  • 복제: MySQL은 마스터-슬레이브 및 마스터-마스터 복제를 지원하여 백업 및 확장 솔루션을 허용합니다.
  1. 단점:
  • 기능: MySQL은 전통적으로 기능 측면에서 다른 데이터베이스보다 뒤떨어져 있지만 최근 버전에서는 이러한 격차가 많이 해소되었습니다.
  • 성능: 매우 큰 데이터 세트 또는 복잡한 작업의 경우 MySQL은 다른 RDBMS 시스템만큼 성능이 좋지 않을 수 있습니다.
  • 동시성: MyISAM 스토리지가 있는 이전 버전의 MySQL에는 테이블 수준 잠금 문제가 있었습니다. 그러나 InnoDB 스토리지 엔진에서는 행 수준 잠금이 지원됩니다.
  1. 비교 결과
  • 비용: MySQL은 특히 무료 버전이 있기 때문에 일반적으로 Oracle보다 저렴합니다.
  • 사용 시나리오: MySQL은 웹 애플리케이션과 중소형 애플리케이션에 널리 사용되는 반면 Oracle은 특히 미션 크리티컬 애플리케이션의 경우 엔터프라이즈 시장을 지배하고 있습니다.
  • 사용자 정의 가능성: 오픈 소스 특성으로 인해 MySQL은 Oracle보다 쉽게 ​​사용자 정의할 수 있습니다.
  • 라이선싱: MySQL에는 이중 라이선스 시스템이 있습니다. GPL에 따라 오픈 소스이지만 MySQL 코드를 독점 소프트웨어에 삽입하려면 상용 라이선스가 필요할 수 있습니다. 반면 Oracle은 상업적으로 라이센스가 부여됩니다.

PostgreSQL과 비교했을 떄 MySQL의 장단점

  1. 장점
  • 속도: MySQL은 특정 시나리오, 특히 읽기 작업이 많은 작업에서 PostgreSQL보다 빠를 수 있습니다.
  • 인기: PostgreSQL보다 더 널리 사용되며 더 큰 커뮤니티와 더 많은 타사 도구로 이어집니다.
  • 스토리지 엔진: 여러 스토리지 엔진(예: InnoDB, MyISAM)을 지원하여 사용자가 필요에 따라 선택할 수 있습니다.
  • 복제: 확장 및 백업을 위한 효과적인 마스터-슬레이브 및 마스터-마스터 복제 기능.
  • 사용 용이성: 많은 사용자가 MySQL을 설정하고 관리하기가 더 쉽다고 생각합니다.
  1. 단점
  • 기능: MySQL에는 사용자 정의 데이터 유형 또는 테이블 상속과 같은 PostgreSQL에 있는 일부 고급 기능이 없습니다.
  • ACID with MyISAM: MyISAM 스토리지 엔진은 ACID를 준수하지 않습니다(InnoDB는 준수하지만).

사용한 이유

현재 VoTogether 프로젝트의 규모와 목적을 고려했을 때, 비교적 간단하고 빠른 MySQL이 어울리다고 판단했습니다.


📝 JWT

JWT는 Json Web Token의 약자로 json형식을 사용한 claim기반의 웹 토큰입니다. JWT를 사용한 이유에 앞서 세션과 토큰 방식의 차이와 함께 토큰 인증 방식을 선택한 이유를 말씀드리겠습니다.

세션

세션은 웹 애플리케이션에서 사용자의 상태 정보를 서버에 유지하기 위한 메커니즘입니다. 사용자가 웹 서버에 접속하고, 웹 서버는 해당 사용자에 대한 정보를 기억하고 유지하기 위해 세션을 사용합니다.

장점

  • 세션은 서버에 저장되는 방식이기 때문에 보안에 강력합니다. 세션ID가 탈취된다고 하더라도 서버에서 해당 세션을 처리하여 무효화 시킬 수 있습니다.
  • 토큰에 비해서 적은 용량을 지니기 때문에 트래픽에 있어서 효율적입니다.

단점

  • 확장에 불리합니다. 특히 다중 서버 환경을 가정했을 경우 세션의 정합성을 유지하기가 어렵습니다.
  • 또한 다중 서버에서 각 서버의 메모리에 세션을 가지고 있는 경우 불필요한 데이터를 모두가 가지고 있어서 메모리 낭비가 발생할 수 있습니다.

토큰

세션과는 다르게 클라이언트에서 직접 정보를 가지고 있는 방식입니다. 주로 JWT를 많이 사용합니다.

장점

  • claim에 다양한 정보를 담을 수 있습니다.
  • 클라이언트에서 관리하기 때문에 세션 방식에 비해 서버에 부담이 덜합니다.
  • 다중서버로 확장했을 경우 관리하기 세션에 비해 관리하기 편합니다.

단점

  • 트래픽이 세션에 비해 크게 발생합니다.
  • 세션에 비해 만들고 검증하고 관리하는 과정 등이 번거롭습니다.

위와 같은 이유를 고려하여 추후에 서버를 확장하는 경우가 가장 크게 다가왔기 때문에 토큰이 세션에 비해 훨씬 관리하기 편할 것이라고 판단했습니다. 따라서 보투게더에서는 토큰을 사용하기로 했습니다.

JWT에서도 어떤 라이브러리를 사용할지에 대해 많이 고민했는데, 크게 java-jwt와 jjwt가 있었습니다. 보투게더에서는 jjwt를 선택했는데, 둘을 비교하면서 이유를 작성하곘습니다. 자세한 내용은 jwt.io사이트에서 확인할 수 있습니다.

Java-JWT

GitHub

  • github-stars : 5.4K
  • forks : 904
  • watch : 217

JJWT

GitHub

  • github-stars : 9.2K
  • forks : 1.3K
  • watch : 271

실제로 jwt.io에서 확인할 수 있는 것은 더 jjwt에서 더 많은 암호 알고리즘을 제공한다는 것이었습니다. 종합적인 이유를 토대로 사용자들이 더 많이 사용한다고 판단되는 JJWT를 사용하기로 결정했습니다.


📝 RestAssruedMockMvc

@WebMvcTest를 사용할 때 어떤 방식을 통해 검증하는 것이 좋을지 고민을 해보았습니다. 통상적으로 사용되는 MockMvc와 RestAssuredMockMvc를 두고 고민을 했습니다.

1. 가독성이 좋고, 사용하기 편하다.

먼저 BDD스타일의 given, when, then의 구조를 사용하기 때문에 MockMvc에 비해서 가독성이 훨씬 뛰어납니다. 테스트 코드의 경우 다양한 의존성을 불러오기 때문에 쉽게 지저분해지기 마련인데, BDD스타일을 사용함으로써 훨씬 더 좋은 가독성을 제공하기 때문에 복잡한 테스트 코드를 보다 쉽게 파악하도록 도와줍니다. 또한 RestAssrued와 제공되는 메서드가 거의 일치했고, 팀원들 역시 RestAssured의 제공되는 메서드들을 파악하고 있기에 빠르게 적용할 수 있다고 생각했습니다.

2. MockMvc에 비해 속도가 확연하게 차이나지 않는다.

MockMvc(빠름) > RestAssuredMockMvc > RestAssured(느림)순으로 속도가 빠릅니다. MockMvc랑 비교하여 성능측정을 했을 경우 약 2배정도의 차이로 MockMvc가 빨랐습니다. 하지만 이에도 RestAssuredMockMvc의 가독성이 훨씬 뛰어났고, 그만큼 서비스의 규모가 크지 않기 때문에 이로 발생하는 테스트 시간에서의 차이는 감안할 수 있겠다고 판단했습니다.

결과적으로 위와 같은 이유로 컨트롤러에 대한 단위테스트를 진행할 때는 RestAssuredMockMvc로 검증을 진행하기로 했습니다.


📝 Github Actions

보투게더 팀은 CI 테스트 자동화 툴로 Github Actions를 사용하기로 했습니다. 다른 툴과 비교하여 이를 사용한 이유는 다음과 같습니다.


1. Github와의 통합

Github Actions는 github에서 제공하기 때문에, github를 버전관리 툴로써 사용하는 입장에서는 가장 사용하기 좋다고 생각했습니다. github를 통해서 테스트를 진행하는 코드에서 오류가 발생한 라인을 바로 확인할 수 있다는 장점도 있습니다. Repository 내부의 actions탭을 통해서도 수행된 내용을 쉽게 확인할 수 있습니다.

2. Workflow 관리에 유용

.yml 파일을 통해서 workflow를 관리하기 때문에 팀원들이 이해하기 쉽고, 유지보수하기 편합니다. 또한 workflow를 작성하기 위한 문서들을 간단한 검색만으로 찾을 수 있기 때문에 쉽게 도입하기도 좋다고 판단했습니다.

위와 같은 이유 때문에 보투게더에서는 Github Actions를 CI 테스트 자동화 툴로 사용하기로 했습니다.


📝 Jenkins

자동 CI/CD 툴로는 대표적으로 젠킨스(Jenkins)와 깃허브 액션(github actions)이 있습니다. CI로 깃허브 액션을 사용하고 있었기에 깃허브 액션으로만 사용할 수 도 있었지만 다음과 같은 이유로 젠킨스도 사용하였습니다.

먼저 젠킨스는 깃허브 액션에 비해 많은 플러그인을 지원하고 관련문서 또한 많이 있어 원하는 리소스를 찾기가 수월합니다. 하지만 CI/CD를 구축하는데는 깃허브 액션보다 더 복잡하다는 단점이 있었지만 학습적인 측면에서 고려해보았을때 젠킨스도 학습해보면 좋을 것 같아서 큰 단점으로는 느껴지지 않았습니다. 또한 젠킨스는 파이프라인을 한 곳에서 쉽게 관리할 수 있고 UI가 보다 직관적이다는 여러 장점도 있었기에 젠킨스를 사용하였습니다.

참고자료


📝 Docker

도커는 컨테이너 기술을 활용한 가상화 플랫폼입니다. 도커를 사용함으로 얻을 수 있는 장점은 아래와 같습니다.

1. 애플리케이션의 개발과 배포가 편리해진다.

동일하게 작성된 애플리케이션이라도 실행 환경이 달라지면 예상하지 못한 결과가 발생할 수 있습니다. 도커는 이미지에 애플리케이션뿐 아니라 개발 환경까지 담을 수 있기에 쉽게 같은 환경에서 애플리케이션을 실행합니다.

개발을 진행하는 로컬 환경과 배포를 진행하는 EC2의 환경이 다름에도 도커를 사용한다면 같은 환경에서 테스트하고 애플리케이션을 실행할 수 있게 됩니다. 추가로 독립된 커널 OS가 존재하지 않기에 이미지 크기가 작아 애플리케이션 배포 속도가 빠르고 자원을 효율적으로 사용할 수 있습니다.

개발 서버 & 운영 서버 분리, 고가용성을 위한 운영 서버 여러 대 운영 등과 같은 상황에서도 동일한 환경을 쉽고 빠르게 구축할 수 있다는 장점도 있습니다.

2. 환경 격리

도커 이미지를 실행시킨 상태를 도커 컨테이너라고 합니다. 해당 기술은 독립된 환경에서 프로세스를 실행시키는 기술로 컨테이너는 각각 독립적으로 실행됩니다. 따라서 컨테이너 내부에서 발생하는 에러를 호스트 OS에 전파되지 않도록 격리할 수 있다는 장점이 존재합니다.

3. 버전 관리

도커 파일이나 도커 컴포즈 파일을 통해 버전과 환경 설정과 같은 정보들을 코드 레벨로 관리할 수 있습니다. 서버에 직접 들어가서 운영 중인 애플리케이션의 버전을 확인하는 작업 없이도 어떤 환경의 어떤 버전을 사용하는지 코드를 통해 명시할 수 있기에 버전 관리에 쉽다는 장점이 있습니다.

추가적인 버전 설치 없이 이미지만 바꾸면 버전도 쉽게 바꿀 수 있습니다.

위와 같은 장점이 존재하기에 저희 팀에서는 도커를 사용하도록 결정하였습니다.


📝 nginx

nginx를 사용함으로서 얻을 수 있는 이점은 크게 다음과 같습니다.

  • 가볍고 빠르며 이벤트 기반의 비동기 구조입니다. 동시 커넥션이 많아져도 Apache보다 메모리 사용률이 낮고 동시에 많은 요청을 처리할 수 있습니다.
  • 한개의 ec2내에서 리버스 프록시를 통해 was + ws로 사용이 가능했고 추후에 캐시를 사용하거나 로드 밸런서로도 활용 할 수 있고 서버 확장에도 용이합니다.
  • ssl인증서를 통해 쉽게 HTTPS를 적용할 수 있습니다.

nginx는 Apache에 비해 다양한 모듈이 없다는 단점이 있지만 모듈이 많다는 거에서는 큰장점으로 느껴지지 않았고 앞서 말한 장점들이 더 크게 느껴졌기에 nignx를 사용하였습니다.

참고자료

Clone this wiki locally