요즘 만든 프로젝트들로 정리한 실전 스택 선택 기준
요즘 만든 프로젝트들로 정리한 실전 스택 선택 기준
최근에 만든 프로젝트들을 쭉 보면 분야가 꽤 다양하다. 사내 리소스 관리 시스템, AI 채팅 워크벤치, 포토카드 키오스크, 네이버 블로그 자동화, 이미지 처리 도구까지.
겉으로 보면 전부 다른 프로젝트처럼 보이는데, 막상 스택을 펼쳐놓고 보면 반복되는 선택 기준이 있다. 빠르게 MVP를 만들되, 나중에 서비스가 커졌을 때 갈아엎지 않아도 되는 구조를 먼저 잡는 쪽이다.
이번 글은 요즘 작업한 프로젝트들을 기준으로 내가 어떤 상황에서 어떤 스택을 골랐는지 정리한 기록이다.
최근 프로젝트 스택 한눈에 보기
| 프로젝트 | 문제 | 핵심 스택 |
|---|---|---|
| KINOTON | 현장 인력 투입시간 기록과 월별 인건비 안분 | NestJS, Next.js, React Native, TypeScript, Monorepo |
| Gng AI Workbench | 여러 AI 모델을 프로젝트별로 비교하고 관리 | Next.js, React, Jotai, IndexedDB, SSE, FSD |
| Photo Card Kiosk | 바코드 검증 후 ESP32로 포토카드 출력 | Next.js, MongoDB, Web Bluetooth, ESP32 |
| Blog Analyzer | 네이버 블로그 원고 자동 생성과 AI 엔진 통합 | FastAPI, Python, MongoDB, OpenAI, Claude, Gemini |
| 검색 노출 자동화 | 네이버 검색 결과 수집과 블로그 노출 체크 | Node.js, TypeScript, Cheerio, MongoDB |
| 이미지 처리 도구 | 메타데이터 제거, 회전, 변형, 크롭 자동화 | Python, PySide6, Pillow, OpenCV, NumPy |
요약하면 최근 작업은 크게 네 갈래다.
- 업무 시스템:
NestJS + Next.js + React Native + Monorepo - AI 도구:
Next.js또는FastAPI중심의 Provider Adapter 구조 - 운영 자동화:
TypeScript + Cheerio + MongoDB - 로컬/하드웨어 도구:
Python또는Web Bluetooth + ESP32
스택 이름만 보면 이것저것 섞은 느낌이지만, 기준은 꽤 단순하다. 화면이 중요하면 Next.js, 규칙과 권한이 중요하면 NestJS, AI/텍스트 파이프라인이 중요하면 Python, 하드웨어와 브라우저를 붙여야 하면 Web Bluetooth를 선택했다.
1. 업무 시스템은 타입 공유가 먼저다
KINOTON은 통합기술부 리소스 안분 관리 시스템이다. 기술자가 모바일에서 시간을 기록하고, 관리자가 웹에서 월별 인건비를 확인하고, 서버가 마감 잠금과 리포트 생성을 책임지는 구조다.
여기서 중요한 건 화면보다 계약이다.
TECHNICIAN, MANAGER, EXECUTIVE 같은 역할, PROJECT, INTERNAL 같은 업무 구분, 월 마감 상태, 시간 기록 요청/응답 타입이 웹과 모바일과 서버에서 모두 같은 의미로 쓰여야 한다.
그래서 모노레포를 선택했다.
kinoton/
├── apps/
│ ├── api/ # NestJS
│ ├── web/ # Next.js
│ └── mobile/ # Expo
└── packages/
├── shared-types
└── api-client
이 구조의 장점은 명확하다. API 응답 필드 하나가 바뀌면 웹과 모바일에서 바로 타입 에러가 난다. 운영자가 보는 대시보드와 기술자가 쓰는 앱이 같은 비즈니스 언어를 공유하게 된다.
업무 시스템은 초반에 화면부터 만들면 빨라 보인다. 그런데 권한, 상태, 마감, 리포트처럼 바뀌면 안 되는 규칙이 많을수록 타입과 도메인 모델을 먼저 고정하는 게 훨씬 싸게 먹힌다.
내 기준은 이렇다.
- 웹과 모바일이 같은 API를 쓰면 모노레포를 먼저 검토한다.
- 비즈니스 규칙이 많으면 NestJS처럼 계층이 분명한 서버를 둔다.
- 서버 상태는 TanStack Query, 화면 내부 상태는 Jotai로 분리한다.
- MVP라도
shared-types는 초반부터 둔다.
KINOTON에서 제일 중요한 스택은 사실 Next.js도, React Native도 아니고 공유 타입이었다.
2. AI 프로젝트는 Provider Adapter가 핵심이다
AI 프로젝트는 두 종류로 나뉘었다.
하나는 Gng AI Workbench처럼 사용자가 직접 모델을 바꿔가며 대화하고 비교하는 도구다. 다른 하나는 Blog Analyzer처럼 원고 생성 파이프라인 안에서 여러 AI 엔진을 단계별로 호출하는 도구다.
둘 다 핵심 문제는 같다.
AI 제공자마다 요청 형식, 응답 형식, 스트리밍 방식, 에러 형태가 다르다. OpenAI만 붙였을 때는 단순한데, Claude, Gemini, Grok, Solar, DeepSeek까지 들어오면 코드가 금방 지저분해진다.
그래서 Provider Adapter 패턴을 썼다.
interface StreamAdapter {
connect(prompt: string): AsyncGenerator<string>;
abort(): void;
}
겉에서는 같은 인터페이스로 호출하고, 안쪽에서 제공자별 차이를 흡수하는 방식이다. SSE 스트리밍도 이 구조로 정리하면 새 모델을 붙일 때 기존 채팅 UI를 거의 건드리지 않아도 된다.
Gng AI Workbench에서는 브라우저 안에 대화 기록과 프로젝트 설정을 남기기 위해 IndexedDB를 썼다. 서버에 모든 대화를 저장하지 않아도 되고, 프로젝트별 시스템 프롬프트를 로컬에서 빠르게 바꿀 수 있다.
반대로 Blog Analyzer는 원고 생성 안정성이 더 중요했다. 2000자 이상 글을 한 번에 생성하면 중간에 끊기거나 JSON이 깨지는 경우가 많아서, Python 기반 FastAPI 서버에서 단계별 생성 파이프라인을 구성했다.
PHASE 1: 화자 설정
PHASE 2: 소제목 생성
PHASE 3: 연관 키워드 추출
PHASE 4: 제목 생성
PHASE 5~7: 본문 생성
PHASE 8: 키워드 검증
여기서는 TypeScript보다 Python이 편했다. 텍스트 후처리, 정규식, 형태소 분석, AI 응답 파싱을 계속 다뤄야 했기 때문이다.
정리하면 이렇다.
- 사용자 인터랙션이 중심이면 Next.js 기반 AI Workbench가 좋다.
- 긴 텍스트 파이프라인과 후처리가 중심이면 FastAPI/Python이 편하다.
- 제공자가 2개 이상이면 처음부터 Adapter를 둔다.
- 스트리밍은 UI 코드에 직접 묻히지 말고 도메인 계층으로 빼야 한다.
AI 프로젝트는 모델 이름보다 구조가 중요하다. 모델은 계속 바뀌지만, 제공자를 갈아 끼우는 구조는 오래 간다.
3. 하드웨어를 붙일 때는 설치 없는 흐름이 강하다
Photo Card Kiosk는 바코드를 스캔하면 쿠폰을 검증하고, ESP32에 BLE 명령을 보내 포토카드를 출력하는 시스템이다.
처음부터 네이티브 앱을 만들 수도 있었지만, 키오스크 운영 환경에서는 설치와 업데이트가 부담이다. 웹으로 열고 바로 동작하는 게 훨씬 낫다. 그래서 Web Bluetooth를 선택했다.
[바코드 스캔]
→ [쿠폰 검증]
→ [BLE 연결]
→ [ESP32]
→ [릴레이 트리거]
→ [머신 작동]
이 프로젝트에서 Next.js는 화면만 담당하지 않는다. 쿠폰 검증 API, 관리자용 데이터, 키오스크 UI까지 한 번에 묶는다. MongoDB에서는 findOneAndUpdate로 쿠폰 중복 사용을 원자적으로 막고, 브라우저에서는 Web Bluetooth로 ESP32와 직접 통신한다.
Web Bluetooth는 제약도 있다. HTTPS 환경이 필요하고, 지원 브라우저도 확인해야 한다. 그래도 별도 앱 없이 하드웨어까지 제어할 수 있다는 장점이 크다.
선택 기준은 이렇게 잡았다.
- 운영자가 웹으로 접근해야 하면 Next.js를 먼저 둔다.
- 쿠폰/티켓처럼 중복 사용 방지가 중요하면 DB 업데이트를 원자적으로 처리한다.
- 하드웨어 제어가 단순 명령 중심이면 Web Bluetooth를 검토한다.
- 펌웨어는 ESP32 + Arduino Framework로 작게 시작한다.
하드웨어 프로젝트는 멋진 기술보다 운영 동선이 더 중요하다. 설치 없이 열리고, 문제가 생겼을 때 바로 새로고침해서 복구되는 흐름이 실제 현장에서는 꽤 강하다.
4. 자동화는 Node와 Python을 구분해서 쓴다
네이버 검색 노출 자동화나 블로그 모니터링은 Node.js와 TypeScript를 많이 썼다. HTML을 가져와서 Cheerio로 파싱하고, 블로그 ID 노출 여부를 체크하고, 결과를 MongoDB에 저장하는 흐름이다.
이런 작업은 브라우저/웹 구조와 가까워서 Node가 잘 맞았다. 특히 URL, HTML, JSON, 스케줄러, Slack 보고 같은 운영 자동화는 TypeScript로 타입을 잡아두면 유지보수가 편하다.
반대로 이미지 메타데이터 제거, 회전 보정, 크롭, 변형 같은 작업은 Python이 더 낫다. Pillow, OpenCV, NumPy가 이미 잘 갖춰져 있고, 로컬 GUI가 필요하면 PySide6로 빠르게 만들 수 있다.
내 기준은 간단하다.
- 웹 페이지 수집과 API 자동화는 TypeScript/Node.js
- 이미지 처리와 파일 변환은 Python
- 사람이 매일 반복하는 운영 업무는 스크립트보다 작은 서비스로 만든다.
- 결과 확인이 중요하면 로그보다 리포트 화면이나 Slack 메시지까지 포함한다.
자동화는 “돌아간다”에서 끝내면 오래 못 간다. 실패했을 때 어디서 막혔는지, 다시 돌려도 안전한지, 결과를 누가 확인하는지가 더 중요하다.
5. 요즘 스택 선택 기준
최근 프로젝트를 기준으로 정리하면, 나는 요즘 이렇게 고른다.
Next.js
화면, API, 배포를 한 프로젝트에서 빠르게 묶어야 할 때 쓴다. 관리자 대시보드, 키오스크, AI Workbench처럼 사용자 경험이 중요한 프로젝트에 잘 맞는다.
NestJS
권한, 도메인 규칙, 상태 전이, 리포트처럼 백엔드 규칙이 중요한 프로젝트에 쓴다. KINOTON의 월 마감 잠금처럼 한 번 잘못 열리면 데이터 신뢰도가 깨지는 기능은 구조가 있는 서버가 필요하다.
React Native + Expo
현장 사용자가 모바일에서 빠르게 기록해야 할 때 쓴다. 네이티브 수준의 배포가 필요하지만, MVP 속도도 중요할 때 Expo가 균형이 좋다.
Jotai + TanStack Query
서버 데이터와 클라이언트 UI 상태를 분리할 때 쓴다. 대시보드 필터, 현재 프로젝트, 스트리밍 상태처럼 화면 안에서 움직이는 값은 Jotai가 편하고, API 데이터는 TanStack Query가 편하다.
FastAPI/Python
AI 텍스트 파이프라인, 이미지 처리, 데이터 후처리가 많은 프로젝트에서 쓴다. 특히 예외 케이스가 많은 문자열 처리나 파일 처리는 Python 생태계가 여전히 강하다.
MongoDB
스키마가 빠르게 바뀌는 MVP, 로그성 데이터, 쿠폰/분석 결과처럼 문서 단위로 저장하기 좋은 데이터에 쓴다. 단, 돈이나 정산처럼 정합성이 중요한 영역은 추후 PostgreSQL 전환을 염두에 둔다.
결론
요즘 작업하면서 느낀 건 스택을 “좋은 기술 목록”으로 고르면 안 된다는 점이다. 프로젝트마다 먼저 봐야 할 축이 다르다.
- 계약이 중요하면 타입 공유
- 규칙이 중요하면 백엔드 계층
- 사용감이 중요하면 프론트 구조
- 제공자가 많으면 Adapter
- 운영 현장이 중요하면 설치 없는 흐름
- 반복 업무가 많으면 자동화와 보고까지 포함
그래서 최근 내 기본 조합은 TypeScript 중심 + 필요한 곳에 Python + 모노레포/Adapter/FSD로 경계 잡기에 가깝다.
스택은 결국 선택의 기록이다. 왜 이 기술을 썼는지 설명할 수 있으면, 다음 프로젝트에서도 덜 흔들린다.