Backend

Spring Boot vs. FastAPI (매우 주관적)

mopil 2022. 10. 19. 11:46
반응형

*Spring Boot를 주력으로 사용하는 입장에서 평가한 굉장히 주관적인 평입니다.

2024. 01. 01 업데이트

 

 

타입 안정성 (Spring Boot > FastAPI)

강타입 언어인 JVM 계열보다, 약타입 인터프리터 언어인 파이썬이 훨씬 약하고 불편했다.

물론 pydantic과 type hinting을 지원하지만, 그래도 2% 부족한 면이 느껴졌다.

 

IDE 자동완성의 아쉬움

파이썬은 라이브러리가 동적으로 생성해 내는 함수나 클래스일 경우, IDE의 자동완성을 사용할 수 없어서 매우 불편했다.

 

레퍼런스 (Spring Boot > FastAPI)

이 글을 최초 작성할 땐, FastAPI 관련 한글 레퍼런스 (블로그 정리 글)이 매우 적었었는데, 24.01.01 기준 꽤 많이 늘어났음을 느낄 수 있었다.

 

그래도 아직은 Spring Boot에는 미치지 못하는 것 같다. 

 

FastAPI는 상대적으로 버그도 많은 것 같다.

 

생산성 (Spring Boot ?? FastAPI)

프레임워크의 컨셉에 따라 생산성이 달라지는 것 같다.

 

소규모 프로젝트 : Spring Boot < FastAPI

중/대규모 프로젝트 : Spring Boot > FastAPI

 

엔터프라이즈 급 규모는 FastAPI를 사용하면 아무래도 컨벤션을 잘 정해야 일관성 있는 코드를 작성할 수 있을 것 같다는 생각을 했다. (자유도가 너무 높은 게 단점처럼 느껴졌다.)

 

JSON 직렬화 (Spring Boot = FastAPI)

Spring Boot : 내장 Jackson을 활용한 메시지 컨버터가 자동으로 직렬화

FastAPI : 내장 Pydantic을 활용한 자동 직렬화

 

둘 다 내장 JSON 라이브러리가 있어서, 객체를 반환하면 자동으로 JSON 직렬화를 해준다. FastAPI는 추가로 딕셔너리 타입을 리턴해도 JSON처럼 변환해 주는데 개인적으로 이 방법이 간단한 JSON 리턴값을 만들 때 추가적은 객체를 만들지 않아도 돼서 좀 더 편리했던 것 같다.

 

2024. 01. 01 추가

하지만 규모 있는 프로젝트를 할수록 딕셔너리 형태를 그대로 내리기보다는, pydatic을 활용한 dto형식으로 더 많이 내려서 사실 두 프레임워크 비슷한 것 같다.

별도의 설정을 안 해줘도 되고, 컨트롤러에서 객체를 그대로 리턴해도 되는 부분에서는 Spring이 좀 더 편한 것 같다고 느껴지기도 했다.

 

템플릿 엔진 (Spring Boot > FastAPI)

Spring Boot : Thymeleaf, Mustache 등 다양하게 지원

FastAPI : Jinja2 (외에 다양한 게 있는 것 같으나 이게 제일 많이 쓰임)

 

사실 Jinja2 라이브러리는 Django/Flask에서 주력된 템플릿 엔진이다.

(물론 파이썬 진영 공용 템플릿 엔진 라이브러리이긴 하지만)

 

FastAPI가 비교적 신생 프레임워크다 보니까 Jinja2와 관련된 자료를 찾기 어려웠다.

 

그래서 외부 css를 import 하거나 경로 설정 문제에서 명쾌한 답을 못 찾았는데, 그런 부분에 관련해서는 자료가 풍부한 스프링이 좀 더 나은 것 같다.

 

요청 변수 처리 부분 (Spring Boot ≤ FastAPI)

Spring Boot : PathVariable, ModelAttribute, RequestBody 등 강력한 어노테이션 지원

FastAPI : 라우팅 핸들러 파라미터로 받음

요청 변수 처리 부분은 개인적으로 FastAPI가 더 편리하다고 느껴졌다. 별도의 명시 없이도 라우팅 핸들러 파라미터로 넣어놓으면 알아서 잡아준다.

스프링의 긴 어노테이션보다 간결해서 보기 편했다.

 

예외 처리 (Spring Boot > FastAPI)

Spring Boot : 다양한 방법 지원, 그중 어노테이션 기반 ControllerAdvice는 매우 강력함

FastAPI : 미들웨어로 처리

FastAPI를 깊게 사용해 본 게 아니지만, 예외처리를 미들웨어로 구현했었다. 예외처리 부분에서는 스프링이 더 편리하고 강력한 것 같다.

 

DI (Spring Boot > FastAPI)

Spring Boot : 스프링 컨테이너로 DI를 지원(강제)함

FastAPI : 기본 Depends 함수를 제공함

스프링은 기본적으로 DI를 지원(강제)하지만, FastAPI는 그렇지 않다.

스프링에서 자주 사용하는 3레이어 아키텍처 (서비스-컨트롤러-레포지토리)를 구현하려면 외부 DI 라이브러리를 사용해야 하고 구조도 복잡해진다.

서비스 구조가 복잡해질수록 DI의 필요성이 높아지는데, 이를 기본적으로 제공하는 스프링이 개인적으로 더 좋다고 느껴졌다.

FastAPI의 Depends 함수는 라우터 파라미터로 계속 전달해줘야 해서 코드가 조금 지저분 해지고 아직 깊게 사용안 해봐서 그런지 DI를 깔끔하게 할 수 있는 방법을 찾지 못했다.

 

2024. 01. 01 추가

파이썬이 함수형 프로그래밍을 지향하기 때문에, 함수 기반으로 DI를 지원한다. 이는 클래스 기반 DI를 사용해 온 필자로써는 상당히 어색했다. 물론 클래스기반 DI를 사용할 순 있다.

소규모 프로젝트는 DI를 필요하지 않았던 경험이 훨씬 많으므로, 이 역시 프로젝트 규모에 따라 달라질 것 같다.

 

Test (Spring Boot > FastAPI)

Spring Boot : 내장 JUnit + Mockito

FastAPI : 외부 pytest

테스트의 편의성은 둘 다 비슷한 것 같다. 다만 FastAPI는 외부 라이브러리인 pytest를 사용해야 한다.

 

2024. 01. 01

pytest를 깊이 있게 써보지 않았지만, 코틀린의 kotest + Mockk가 좀 더 강력하고 편리한 것 같다. 다양한 테스트코드 스타일을 지원하는 것은 덤

 

ORM (Spring Boot ≥ FastAPI)

Spring Boot : Spring Data JPA(JPA/Hibernate)

FastAPI : SQLAlchemy

 

엔티티를 정의하는 방법이나 연관관계 매핑은 스프링이나 FastAPI나 둘 다 비슷한 거 같다.

 

다만, SQLAlchemy는 QueryDSL마냥 메소드 체이닝 하는 방식으로 쿼리를 짠다.

 

기본적인 CRUD가 없어서 직접 만들어야 한다 그렇지만 JPQL을 작성하는 것보다 메서드 체이닝처럼 쓰는 게 좀 더 편한 거 같다.

 

복잡한 동적 쿼리를 사용하려면 스프링은 QueryDSL과 같은 외부 라이브러리 도움이 필요하지만, SQLAlchemy를 사용하면 이를 기본적으로 커버할 수 있다.

 

하지만 기본 CRUD 메서드를 손수 제작해야 한다는 건 상당히 귀찮았다.

 

2024. 01. 01 추가

최근에는 peewee라는 새로운 ORM을 써봤는데 문서가 SQLAlchemy 보다 풍부한 것 같다. 다만 peewee가 async를 지원하지 않아서.. 궁합이 안 맞는다고 한다.

(물론 쓸 수 있도록 추가 설정을 해서 사용할 순 있다.)

 

혹시라도 도입할 생각이 있으신 분들은 참고하시길...

peewee 공식 문서

https://docs.peewee-orm.com/en/latest/

 

peewee — peewee 3.17.0 documentation

© Copyright charles leifer. Revision e0db76f0.

docs.peewee-orm.com

 

FastAPI 공식 문서

https://fastapi.tiangolo.com/how-to/sql-databases-peewee/

 

SQL (Relational) Databases with Peewee - FastAPI

FastAPI framework, high performance, easy to learn, fast to code, ready for production

fastapi.tiangolo.com

 

async를 지원하지 않아 부적합하다고 공식문서에서 말하는 중...

 

 

배포 관련 (Spring Boot > FastAPI)

Spring Boot : 내장 WAS(톰캣)과 쓰레드 풀을 활용한 다중 처리 가능, JAR 빌드 후 배포가 용이함

FastAPI : Nginx를 사용해야 하고, 프로덕션 환경에서는 파이썬 고질적인 GIL 정책 때문에 gunicorn을 활용한 멀티 프로세스 방식으로 운영해야 함 -> 이벤트 루프 방식으로 고성능 처리 가능함 (걱정 안 해도 됨)

 

배포, 운영 관리 측면에서는 스프링이 압도적으로 편리하다고 느껴졌다.

 

application 설정 파일로 쓰레드 풀 설정도 편리하고, JAR 빌드 후 배포 과정도 편리했다.

 

반면 FastAPI는 Nginx 서버를 앞단에 두어야 하고, 파이썬의 GIL 문제 때문에 gunicorn을 활용한 worker 프로세스를 두는 방식으로 운영을 해야 한다.

 

이렇게 여러 프로세스를 두면 로깅과 모니터링도 조금 불편했다. 물론 큰 트래픽이 몰리지 않는 서비스면 상관없지만, 이를 고려해야 하는 환경이 조금 부담된다고 느껴졌다.

 

 

2024.01.01 추가

FastAPI는 별도의 빌드 없이 바로 배포가 되어서, 규모가 커질수록 빌드-배포 시간 차이가 확연하게 느껴졌다.

(보통 Spring Boot 빌드시간은 1~2분 남짓인데, FastAPI는 거의 바로 된다.)

 

이런 부분에서는 파이썬이 훨씬 좋다고 느껴졌다.

 

프로젝트 구조 관련 (Spring Boot > FastAPI)

3레이어 아키텍처와 MVC 패턴을 활용하는 스프링의 정형화된 구조가 개인적으로 좀 더 안정감을 준다고 생각했다.

 

FastAPI 같은 경우는 프로젝트 구조를 강제하는 틀이 없다.

 

그래서 뭔가 정형화된 best practice를 찾기 어려웠고, 내가 설계한 구조가 괜찮은 구조인지를 알기가 조금 어려웠다.

 

이러한 부분에서는 정형화된 틀을 제공하는 스프링이 좀 더 좋다고 느껴졌다.

(아무래도 FastAPI는 이름처럼 경량 프레임워크라는 특징 때문에 그런 것 같다.)

 

DTO (Spring Boot = FastAPI)

Spring Boot : record(Java17), data class(Kotlin) 언어 차원에서 지원

FastAPI : pydantic 라이브러리 지원

 

DTO를 만드는 방법은 두 프레임워크 비슷했다.

 

개인적으로는 코틀린의 data class가 제일 편했고, 그다음은 비슷했다. 둘 다 껍데기 객체를 만들어서 전달하면 된다. 

 

유효성 검증 (Spring Boot > FastAPI)

둘 다 당연히 검증을 지원하지만, 어노테이션 기반의 스프링이 좀 더 강력하다고 느껴졌다.

 

FastAPI 또한 데코레이터 패턴을 활용해서 validator를 구현가능하지만, 아무래도 기본적으로 제공하는 스프링이 좀 더 편리하다고 생각했다.

 

API 문서화 (Spring Boot FastAPI)

Spring Boot : Swagger, Rest Docs 등 다양하게 지원

FastAPI : Swagger를 기본적으로 내장하고 있음

 

스프링은 API 문서화를 하려면 Swagger 설정을 추가로 해줘야 하는데, FastAPI는 이를 기본적으로 내장하고 있다. 이 부분은 참 편했던 것 같다.

 

 

결론

FastAPI와 Spring Boot 모두 꽤 사용해 본 결과, 개인적으로 내린 결론이다.

 

FastAPI

  • 소~중규모 프로젝트 (API 수 < 30, 협업 대상 2~3)
  • 딥러닝 모델 서빙이 필요한 경우
  • 모두가 파이썬에 익숙한 경우

 

Spring Boot

  • 소~대규모 프로젝트 
  • 모두가 JVM 언어 (자바, 코틀린)에 익숙한 경우

 

필자는 딥러닝 모델을 탑재해야 하는 경우가 아니고서는 웬만하면 Spring Boot를 사용한다.

반응형