SSR 방식의 Next.js
를 통해 웹 애플리케이션을 개발하다보면
필연적으로 고려해야하는 부분이 있다.
DB Connection을 어떻게 구축하는게 좋을까?
특히, 기존 애플리케이션 구조가 전혀 없어 새롭게 시작해야하는 시점에 깊이 하게되는 고민인데,
필자는 Oracle DB 서버가 구동중이고 React
나 FastAPI
와 같은 프론트엔드/백엔드가 전혀 없는
현 단계에서 시스템 마이그레이션을 고려하면서 다음 내용을 고민하게 되었다.
당연히 애플리케이션 아키텍처가 4-Tier Layered
로 구조화되어 Business Logic
계층과 Data layer
가 분리되어있다면 당연히 Next.js
+ FastAPI/Node.js
+ DB
의 방식이 올바른 접근법이겠지만,
Data Layer
와 Business Logic
계층의 분리가 명확하지 않은 3-Tier Layered
방식을 기존 시스템이 따른다면 점진적 마이그레이션에선 위의 고민에 직면하는 것이 당연하다고 생각한다.
아래 게시글에서는 SSR
및 REST API
와 같은 기초적인 기술 개념에 대해서는 따로 설명없이 진행하겠다.
가장 흔하게 사용되는 애플리케이션 구조로, FastAPI
나 Express
를 통해 WAS
를 구축하고
REST API
방식을 통해 Next
에게 데이터를 전달하고, 요청받는 구조이다.
간단히 나타내는 아키텍처 구조는 다음과 같다.
Client → Next.js (SSR/SSG) ↔ REST API (FastAPI/Node.js) ↔ Oracle DB
프론트엔드와는 HTTP(S)
방식으로 통신하나,
실시간 및 양방향 통신이 주요하게 요구된다면
Web Socket
이나 gRPC
방식의 프로토콜을 적용할 수 있다.
프로덕션 배포 시, 백엔드를 위한 별도의 서버 인스턴스가 필요하고
이를 온프레미스 인프라로 진행할 수도, AWS EC2
나 Oracle Cloud(OCI)
등의 클라우드 서비스로 진행할 수도 있다.
당연히 그만큼 필수적인 비용이 발생하게 된다.
또한 프론트엔드와 백엔드의 도메인 차이가 발생해 Cross Origin
및 포트 차이가 발생하게 되고
CORS
핸들링을 위한 별도의 장치가 선행되어야한다.
Nginx, Vercel 등의
Reverse Proxy
가 이를 해결하기 위한 가장 대표적인 방법 중 하나이다.
구현된 백엔드 로직은 흔히 말하는 JSON 상하차
를 진행하게 되는데
request로 받는 요청을 확인해 DB에 접근하고, 상호작용을 통해 도출된 결과를 response로 프론트엔드에 전달한다.
그럼, Serverless Architecture란 무엇일까
최근 각광받는 아키텍처 구조로, 기존 백엔드의 역할을 프론트엔드의 Server Actions
로 이관해
데이터 접근부터 API 요청 처리를 하나의 프레임워크에서 진행하는 방식을 의미한다.
Client → Next.js (API Routes/Server Actions) ↔ Supabase
가장 대표적으로 사용되는 접근 방식은
Next.js
+Supabase
Supabase
자체가 Serverless에 특화된 방식으로서 POST
, GET
등의 Method 처리를 직접적으로 제공하고, 별도의 인스턴스가 필요없는 클라우드 방식이기 때문에
빠른 개발 속도와 비용 절감을 위해 많이 사용한다.
빠른 MVP를 위해서는 이만한 접근법이 없는 셈
Client → Next.js (API Routes/Server Actions) ↔ Serverless Platform ↔ DB
외에는 AWS Lambda
, Oracle Functions
를 통해 요청이 있을 때만 Server ON 방식을 통해
DB와 접근하고 response를 제공하는 것이 기초적인 방식의 아키텍처이다.
당연히 별도의 지속적으로 켜져있는 서버 인스턴스가 요구되지 않고 CORS
고려사항도 훨씬 간단해지나,
Next.js
환경의 개발 숙련도가 더욱 요구되고
대용량 트래픽 처리나 동시성 처리, 캐싱 등에 있어선
Redis
나 Kafka
등을 도입하기 편리한 WAS 구축 방식이 더 유리하다.
그럼 이제 Oracle DB와 Next
직접 연결을 고려해보자.
Client → Next.js (API Routes/Server Actions) ↔ Oracle DB (On-Premise)
현재 상태는 온프레미스 인프라로 Oracle DB를 접근할 수 있는 상태에서
Next
에 Server Actions
방식을 고민하는 것이다.
Server Action
에 직접적인 DML
쿼리를 작성해 데이터를 조회하고, DB를 핸들링한다면
별도의 백엔드 로직이나 인스턴스를 필요로 하지 않으면서 애플리케이션을 구축할 수 있다.
당연히 CORS
핸들링 역시 고려할 필요가 없다.
다만, DML
권한 관리가 핵심 이슈로 작용하며
개발자에게 트랜잭션 관리 및 쿼리 튜닝 등 핵심적인 DB 지식이 추가로 요구된다.
예를 들어, Client Layer
에서 JWT
나 세션을 통해 인증된 사용자 정보를 기반으로
Next.js
의 Actions
과정에서 Role
을 명시적으로 확인해 DB 핸들링 과정에서 발생하는 사고를 예방해야한다.
당연히 보안성에 대한 고려사항과 정책 수립이 선행되어야 하기 때문에, 전문적인 지식 역시 필수적이다.
또한 해당 방식은
동시 연결의 한계가 명확하고, 처리 시간에 따른 지연 발생 확률이 기하급수적으로 증가하며
효과적인 캐싱 전략에 대한 별도의 구조와 설계가 필요하다.
점진적 마이그레이션을 고려한다면,
1. Next.js ↔ Oracle DB
(PL/SQL을 통한 비즈니스 로직 처리
2. Next.js ↔ WAS ↔ Oracle DB
(PL/SQL 로직을 WAS로 점진적 이관)
의 방식이 효과적이다.
특히 프로시저, 패키지, 트리거의 역할을 확인해 이를 각각의 API로 이동하면서
유지보수성을 향상하는게 개발자의 목표라고 생각한다.
다음은 Claude
를 통해 작성된 차이점 정리표이다.
구분 | Next.js + Oracle 직접 연결 | Next.js + WAS + Oracle |
---|---|---|
아키텍처 | Client → Next.js(Vercel) → Oracle(On-premise) | Client → Next.js → WAS → Oracle(On-premise) |
복잡도 | 🟢 단순 (2-Tier) | 🔴 복잡 (3-Tier) |
Serverless 여부 | ⚠️ 부분적 (Frontend만) | ❌ Traditional |
초기 구축 속도 | 🟢 빠름 | 🔴 느림 |
성능 지표 | Next.js 직접 연결 | Next.js + WAS |
---|---|---|
최대 동시 연결 | 🔴 제한적 (~50-200개) | 🟢 높음 (수천개) |
응답 시간 | 🟡 250ms (Cold: 1.2s) | 🟢 50-100ms |
처리량 (TPS) | 🔴 낮음 (100 TPS) | 🟢 높음 (1000+ TPS) |
Cold Start | 🔴 있음 (1-3초) | 🟢 없음 |
네트워크 지연 | 🔴 높음 (Cloud↔On-premise) | 🟡 중간 (내부망 활용 가능) |
연결 풀 관리 | 🔴 제한적 (Function별) | 🟢 최적화 (WAS 레벨) |
캐싱 전략 | 🟡 기본 수준 | 🟢 고급 (Redis, Memcached) |
개발 측면 | Next.js 직접 연결 | Next.js + WAS |
---|---|---|
코드 구조 | 🟡 결합도 높음 | 🟢 관심사 분리 |
팀 협업 | 🔴 풀스택 개발자 필요 | 🟢 역할별 전문화 |
API 버전 관리 | 🔴 어려움 | 🟢 체계적 관리 |
배포 전략 | 🔴 전체 재배포 | 🟢 독립적 배포 |
테스트 전략 | 🟡 E2E 중심 | 🟢 계층별 테스트 |
디버깅 | 🟡 통합 환경 | 🟢 계층별 분리 |
기술 스택 확장 | 🔴 Next.js 종속 | 🟢 다양한 기술 선택 |
보안 요소 | Next.js 직접 연결 | Next.js + WAS |
---|---|---|
네트워크 격리 | 🔴 Oracle 외부 노출 필요 | 🟢 내부망 보호 |
접근 제어 | 🟡 애플리케이션 레벨 | 🟢 다계층 제어 |
권한 관리 | 🟡 단일 계정 or 제한적 | 🟢 세밀한 Role 기반 |
감사 로깅 | 🟡 애플리케이션 로그 | 🟢 통합 로깅 시스템 |
암호화 | 🟡 TLS 기본 | 🟢 End-to-End 암호화 |
DML 권한 제어 | 🟡 코드 레벨 검증 | 🟢 DB + WAS 이중 검증 |
네트워크 측면 | Next.js 직접 연결 | Next.js + WAS |
---|---|---|
CORS 이슈 | 🟢 없음 (Same Origin) | 🟢 없음 (적절한 설정 시) |
프록시 필요성 | ⚠️ 네트워크 접근성에 따라 | 🟢 불필요 (내부망) |
방화벽 설정 | 🔴 복잡 (외부 접근 허용) | 🟢 단순 (내부망 유지) |
VPN 필요성 | ⚠️ 보안상 권장 | 🟢 선택적 |
IP 화이트리스트 | 🔴 Vercel IP 대역 관리 | 🟢 고정 IP 관리 |
비용 요소 | Next.js 직접 연결 | Next.js + WAS |
---|---|---|
초기 구축 비용 | 🟢 낮음 | 🔴 높음 |
인프라 비용 | 🟢 낮음 (Serverless) | 🔴 높음 (서버 유지) |
개발 인력 | 🟢 적음 (풀스택 1-2명) | 🔴 많음 (FE/BE 팀) |
운영 복잡도 | 🟢 낮음 | 🔴 높음 |
장기 운영 비용 | 🟡 트래픽 증가 시 상승 | 🟢 예측 가능 |
모니터링 비용 | 🟢 통합 모니터링 | 🔴 다중 시스템 모니터링 |
프로젝트 규모 | 사용자 수 | 동시 접속 | 권장 아키텍처 | 핵심 이유 |
---|---|---|---|---|
소규모 프로토타입 | < 100 | < 10 | 🟢 Next.js 직접 | 빠른 개발, 검증 |
스타트업 MVP | < 1K | < 50 | 🟢 Next.js 직접 | 비용 효율성 |
중소 서비스 | 1K-10K | 50-200 | 🟡 상황별 선택 | 성장 계획에 따라 |
기업 서비스 | 10K-50K | 200-1K | 🔴 WAS 분리 | 확장성, 안정성 |
대규모 엔터프라이즈 | 50K+ | 1K+ | 🔴 WAS 분리 | 성능, 보안 필수 |
전환 신호 | 임계점 | 대응 방안 |
---|---|---|
응답 시간 지연 | > 500ms 지속 | WAS 도입 검토 |
동시 연결 한계 | > 200 동시 사용자 | 백엔드 분리 시작 |
복잡성 증가 | 비즈니스 로직 복잡화 | 점진적 서비스 분리 |
보안 요구사항 | 엔터프라이즈 보안 정책 | WAS 기반 보안 아키텍처 |
팀 규모 확장 | 개발자 5명 이상 | 역할별 팀 구성 |
단계 | 아키텍처 | 특징 | 적용 시점 |
---|---|---|---|
1단계 | Next.js 직접 연결 | MVP, 빠른 검증 | 프로젝트 시작 |
2단계 | Hybrid (읽기: 직접, 쓰기: API) | 점진적 분리 | 성능 한계 도달 |
3단계 | 부분 WAS 분리 | 핵심 기능만 분리 | 보안/복잡성 증가 |
4단계 | 완전 WAS 분리 | 마이크로서비스 | 전사 확산 |
체크 항목 | 설명 |
---|---|
☐ 팀 규모 5명 이하 | 풀스택 개발 가능 |
☐ DAU 10K 이하 | 트래픽 부담 적음 |
☐ 단순한 CRUD 위주 | 복잡한 비즈니스 로직 없음 |
☐ 빠른 시장 진입 필요 | 개발 속도 우선 |
☐ 제한된 예산 | 비용 효율성 중요 |
☐ 풀스택 개발 역량 보유 | 기술적 역량 충분 |
체크 항목 | 설명 |
---|---|
☐ 엔터프라이즈 환경 | 높은 안정성 요구 |
☐ DAU 10K 이상 | 대용량 트래픽 처리 |
☐ 복잡한 비즈니스 로직 | 트랜잭션, 배치 처리 |
☐ 높은 보안 요구사항 | 엔터프라이즈 보안 정책 |
☐ 다양한 클라이언트 지원 | 웹, 모바일, API |
☐ 전문 개발팀 보유 | 역할별 전문성 |
Start Simple → Scale Smart
다음 포스팅엔
Next
와 Oracle
연결을 Gemini CLI
를 통해 진행하는 개발 과정을 작성해보겠다.