스프링(Spring)과 장고(Django)를 도마 위에 올려두고, 자바(Java)와 파이썬(Python) 위주로 생각을 해보자
“백엔드를 개발하는 것”은 결국, JVM/Python 런타임 위에서 돌아가는 서버를 만드는 것입니다.
저는 “프레임워크가 없었으면 어떻게 했을까?”를 생각하는 것을 좋아합니다.
프레임워크 없을 때와 있을 때를 비교하는, 비교 학습 방법의 일환이죠.
근데 “프레임워크 vs 순수 언어” 구도에는 층이 하나 빠져 있습니다 — 서버는 프레임워크만으로 안 돌아갑니다. 프레임워크보다 더 로우레벨에서 시작합니다.
OS 커널 → JVM/파이썬 런타임 → 그 위에 코드
java.net.Socket 또는 파이썬 socketjava.net.Socket 파이썬 socket) 사용GET /users HTTP/1.1... 로 해석/users 를 어떤 처리 코드로 보낼시 결정1번과 2번은 표준 라이브러리나 WAS가 해줘요. Django/Spring이 진짜 대신해주는 건 주로 3~5번 + 그 주변 반복 작업이에요.
WAS는 언어마다 정체가 다른데, 자바의 경우 Tomcat을 쓰고, Tomcat은 자바로 짜인 프로그램이에요. 파이썬은 표준 WAS 하나만 있는게 아니고, 예시로 Gunicorn은 파이썬으로 짜있고, uvicorn은 파이썬 + C 혼합인 등, 몇 가지가 있습니다.
그리고 1~2단계의 Tomcat과 3~5단계 Spring을 잇는 규약이 Servlet입니다: Tomcat ↔ Servlet ↔ Spring 파이썬의 경우 WSGI(동기) 또는 ASGI(비동기)에요: Gunicorn ↔ WSGI ↔ Django.
이제 프레임워크가 무엇을 하는지 봅시다.
(1) 라우팅 — 없으면 거대한 if-else 지옥.
if path == "/users" and method == "GET":
handle_list_users()
elif path == "/users" and method == "POST":
handle_create_user()
elif path.startswith("/users/") and method == "GET":
user_id = path.split("/")[2] # 직접 파싱
handle_get_user(user_id)
# 엔드포인트 100개면 이게 100개
urls.py에 path("users/<int:id>/", view) — <int:id> 파싱까지 자동@GetMapping("/users/{id}") 애노테이션 하나(2) DB 접근 — 없으면 SQL 문자열 + 객체 변환 수작업