RSC 없이 DB 직접 호출부터 스트리밍까지 — TanStack Start와 Next.js, 풀스택 경계가 어디서 갈리는가
Next.js 13 App Router가 나왔을 때 솔직히 많이 흔들렸습니다. use client를 붙였다 떼었다 하면서 "나만 이상한 건가" 싶은 불안감, 서버 컴포넌트 안에서 useState를 쓰려다 런타임 에러를 맞닥뜨리는 경험. React와 Next.js를 어느 정도 써온 분이라면 한 번쯤 공감할 겁니다. 그 시기에 TanStack Start가 조용히 다른 방향에서 걷고 있었는데 — "RSC 없이도 풀스택 할 수 있다"는 명제를 들고요.
2025년 11월 v1.0이 공식 출시되면서, TanStack Start는 "흥미로운 실험"에서 프로덕션에서 실제로 쓸 수 있는 선택지로 바뀌었습니다. 안정된 API와 문서, Nitro 기반의 다양한 배포 타겟 지원이 갖춰진 겁니다. 이 글에서는 createServerFn, Selective SSR, 스트리밍이라는 세 레이어를 직접 짚어보면서, RSC 없이 어디까지 커버되는지 그리고 어디서 Next.js가 여전히 현실적인 선택인지 판단 기준을 함께 살펴봅니다. 데이터 중심 SaaS, 어드민 패널, B2B 앱을 만드는 분이라면 특히 실용적인 판단 기준을 가져갈 수 있을 겁니다. 이 글을 끝까지 읽으면, 내 다음 프로젝트에 TanStack Start를 선택할지 아닐지 근거 있는 결정을 내릴 수 있을 겁니다.
미리 말씀드리자면 — React와 Next.js를 써봤고, RSC나 Server Actions에서 한 번이라도 "이게 맞나?" 싶은 순간을 겪은 분을 대상으로 썼습니다. 이 글은 TanStack Start를 무조건 쓰라는 주장이 아닙니다. RSC가 꼭 필요한 케이스가 분명히 있고, 그 경계도 같이 살펴볼 겁니다.
핵심 개념
TanStack Start의 핵심 레이어는 세 가지입니다 — Just React 철학(클라이언트 주도 컴포지션), Selective SSR(라우트 단위 렌더링 전략), createServerFn(서버-클라이언트 RPC). 이 세 개는 독립적인 기능이 아닙니다. Just React 철학이 기반 원칙이고, Selective SSR이 라우트 레벨에서 렌더링 전략을 결정하며, createServerFn이 각 레이어 안에서 서버 코드를 안전하게 격리합니다. 하나씩 살펴보겠습니다.
"Just React" 철학이 의미하는 것
TanStack Start의 핵심 철학은 **"just React"**입니다. RSC 없이, 컴파일러 매직 없이, use client 디렉티브 없이 — 그냥 우리가 항상 써온 방식으로 React 컴포넌트를 작성합니다. 그러면서도 서버 렌더링, 데이터 페칭, API 라우트 같은 풀스택 기능을 전부 씁니다.
내부적으로는 Vite와 Nitro 위에서 동작합니다. TanStack Router가 라우팅 레이어를, Nitro가 서버 런타임을 담당합니다. 빌드 파이프라인은 Vite가 전담하니 HMR이 빠르고, 기존 Vite 플러그인 생태계를 그대로 활용할 수 있습니다.
Nitro: Nuxt 생태계에서 나온 서버 런타임입니다. H3 HTTP 프레임워크 기반으로, Node.js부터 Cloudflare Workers, Vercel, AWS Lambda까지 동일한 코드로 배포할 수 있는 어댑터 레이어를 제공합니다. TanStack Start가 특정 배포 환경에 종속되지 않는 이유가 바로 Nitro 때문입니다.
Selective SSR — 라우트 단위로 렌더링 전략을 고르는 것
RSC의 강점 중 하나가 "컴포넌트 단위 서버/클라이언트 분리"인데, TanStack Start는 이를 라우트 단위로 대응합니다. 라우트 정의에서 ssr 옵션 하나로 세 가지 전략 중 하나를 선택할 수 있습니다.
// app/routes/dashboard.tsx
export const Route = createFileRoute('/dashboard')({
// 완전한 서버 렌더링 — SEO가 중요한 페이지에 적합합니다
ssr: true,
// 서버에서 데이터만, 컴포넌트 렌더는 클라이언트
// ssr: 'data-only',
// 순수 클라이언트 SPA — 어드민 내부 페이지 등
// ssr: false,
loader: async () => fetchDashboardData(),
component: DashboardPage,
})처음 이 옵션을 봤을 때 "이게 RSC의 뭘 대체하는 거지?" 싶었는데, 실제로 써보니 생각보다 커버되는 케이스가 넓습니다. SaaS 어드민 같은 경우 대부분의 라우트가 ssr: 'data-only'로도 충분하거든요. 서버에서 데이터 검증·페칭하고 클라이언트에서 렌더하는 구조가 RSC의 "서버에서 데이터 페칭"을 상당 부분 대체합니다.
ssr: 'data-only'패턴: 로더 함수는 서버에서 실행되지만 컴포넌트 렌더링은 클라이언트에서 일어납니다. DB 접근, 환경변수 사용은 서버에서, 인터랙션은 클라이언트에서 — 역할이 명확하게 분리됩니다. TanStack Start 공식 Selective SSR 가이드에서 이 패턴을 자세히 다루고 있습니다.
createServerFn — RSC의 async Server Component를 대체하는 RPC
이게 TanStack Start에서 가장 중요한 개념입니다. 서버에서만 실행되는 함수를 클라이언트에서 타입 안전하게 호출하는 RPC 메커니즘인데, 빌드 타임에 클라이언트 번들에서는 RPC 스텁으로 교체됩니다. 실제 서버 코드가 브라우저에 노출될 일이 없습니다.
// app/functions/user.ts
// 이 파일의 코드는 서버에서만 실행됩니다
import { createServerFn } from '@tanstack/start'
import { z } from 'zod'
import { db } from '~/server/db' // Prisma 또는 Drizzle 모두 동일한 방식으로 씁니다
const getUser = createServerFn({ method: 'GET' })
.validator(z.object({ id: z.string() }))
.handler(async ({ data }) => {
return db.user.findUnique({ where: { id: data.id } })
})
const updateUserProfile = createServerFn({ method: 'POST' })
.validator(z.object({
id: z.string(),
name: z.string().min(1),
email: z.string().email(),
}))
.handler(async ({ data }) => {
return db.user.update({
where: { id: data.id },
data: { name: data.name, email: data.email },
})
})
export { getUser, updateUserProfile }// app/routes/profile.$userId.tsx
import { useState } from 'react'
import { createFileRoute } from '@tanstack/react-router'
import { getUser, updateUserProfile } from '~/functions/user'
export const Route = createFileRoute('/profile/$userId')({
loader: async ({ params }) => {
// 로더에서 서버 함수 호출 — SSR 시 서버 사이드에서 직접 실행됩니다
return getUser({ data: { id: params.userId } })
},
component: ProfilePage,
})
function ProfilePage() {
const user = Route.useLoaderData()
const [error, setError] = useState<string | null>(null)
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
const formData = new FormData(e.currentTarget)
try {
await updateUserProfile({
data: {
id: user.id,
name: formData.get('name') as string,
email: formData.get('email') as string,
},
})
} catch (err) {
// createServerFn에서 throw한 Error가 그대로 클라이언트에 전달됩니다
setError(err instanceof Error ? err.message : '오류가 발생했습니다')
}
}
return (
<form onSubmit={handleSubmit}>
{error && <p className="error-message">{error}</p>}
<input name="name" defaultValue={user.name} />
<input name="email" defaultValue={user.email} />
<button type="submit">저장</button>
</form>
)
}RSC에서 async Server Component로 하던 일을 여기서는 명시적인 함수 호출로 처리합니다. 어떤 분들은 "명시적이라 더 낫다"고 하고, 또 어떤 분들은 "RSC가 더 직관적"이라고 합니다. 저는 전자 쪽인데, 이유는 간단합니다 — 에러 스택을 보면 어디서 터졌는지 바로 나옵니다. RSC에서 렌더 중에 터지는 에러를 추적하다 지쳐본 경험이 있다면 이게 얼마나 편한지 금방 체감됩니다.
스트리밍 SSR과 Suspense — 그리고 데이터는 어디서 오는가
RSC 없이도 점진적 페이지 로딩이 가능합니다. React Suspense와 TanStack Query를 결합하면 서버 렌더링 결과를 청크 단위로 스트리밍할 수 있습니다. 이 섹션에서 처음 봤을 때 가장 궁금했던 부분 — 스트리밍되는 컴포넌트가 내부적으로 어떻게 데이터를 페칭하는지 — 를 같이 보겠습니다.
// app/functions/analytics.ts
import { createServerFn } from '@tanstack/start'
import { z } from 'zod'
import { db } from '~/server/db'
export const getRevenueData = createServerFn({ method: 'GET' })
.handler(async () => {
// 무거운 DB 집계 쿼리도 서버에서만 실행됩니다
return db.order.groupBy({
by: ['createdAt'],
_sum: { amount: true },
orderBy: { createdAt: 'asc' },
})
})
export const getUserActivity = createServerFn({ method: 'GET' })
.validator(z.object({ days: z.number().default(30) }))
.handler(async ({ data }) => {
const since = new Date(Date.now() - data.days * 86400 * 1000)
return db.userEvent.findMany({
where: { createdAt: { gte: since } },
})
})// app/routes/analytics.tsx
import { Suspense } from 'react'
import { useSuspenseQuery } from '@tanstack/react-query'
import { createFileRoute } from '@tanstack/react-router'
import { getRevenueData, getUserActivity } from '~/functions/analytics'
export const Route = createFileRoute('/analytics')({
ssr: true,
component: AnalyticsPage,
})
function RevenueChart() {
// useSuspenseQuery — 이 컴포넌트가 Suspense 경계 안에 있어야 동작합니다
const { data } = useSuspenseQuery({
queryKey: ['revenue'],
queryFn: () => getRevenueData(),
})
return <LineChart data={data} />
}
function UserActivityTable() {
const { data } = useSuspenseQuery({
queryKey: ['user-activity'],
queryFn: () => getUserActivity({ data: { days: 30 } }),
})
return <DataTable rows={data} />
}
function AnalyticsPage() {
return (
<div className="grid gap-6">
{/* 즉시 렌더되는 레이아웃 */}
<PageHeader title="Analytics" />
{/* 각 Suspense 경계가 독립적으로 스트리밍됩니다 */}
<Suspense fallback={<ChartSkeleton />}>
<RevenueChart />
</Suspense>
<Suspense fallback={<TableSkeleton />}>
<UserActivityTable />
</Suspense>
</div>
)
}이 패턴을 처음 봤을 때 "Next.js RSC 스트리밍이랑 뭐가 다른 거지?" 싶었는데, 써보고 나서 차이점이 하나 명확해졌습니다. Suspense 경계와 데이터 페칭의 연결이 전부 명시적입니다. RSC에서는 어디서 Suspense가 트리거되는지 감춰진 부분이 있는데, 여기서는 useSuspenseQuery가 어느 컴포넌트에서 어떤 데이터를 기다리는지 코드에서 바로 읽힙니다. 제어권이 더 명확하게 내 손에 있다는 느낌이 들었습니다.
실전 적용
예시 1: SaaS 어드민 대시보드 — ssr: 'data-only' + 서버 함수 패턴
실무에서 가장 자주 맞닥뜨리는 상황입니다. 어드민 대시보드는 SEO가 필요 없지만 초기 로딩 속도와 데이터 보안이 중요합니다. ssr: 'data-only'가 딱 맞는 케이스입니다.
// app/routes/admin/orders.tsx
import { createFileRoute } from '@tanstack/react-router'
import { createServerFn } from '@tanstack/start'
import { z } from 'zod'
import { db } from '~/server/db'
import { requireAdmin } from '~/server/auth'
// 서버 함수 — DB 접근, 권한 체크 전부 서버에서 처리됩니다
const getOrders = createServerFn({ method: 'GET' })
.validator(z.object({
page: z.number().default(1),
status: z.enum(['pending', 'shipped', 'delivered']).optional(),
}))
.handler(async ({ data }) => {
// 인증 체크는 클라이언트에 로직이 노출되지 않습니다
await requireAdmin()
return db.order.findMany({
where: { status: data.status },
skip: (data.page - 1) * 20,
take: 20,
include: { user: true, items: true },
})
})
export const Route = createFileRoute('/admin/orders')({
// 로더는 서버에서, 렌더는 클라이언트에서
ssr: 'data-only',
// URL 검색 파라미터를 타입 안전하게 검증합니다 (TanStack Router 고유 기능)
validateSearch: z.object({
page: z.number().catch(1),
status: z.enum(['pending', 'shipped', 'delivered']).optional(),
}),
loader: async ({ location }) => {
// location.search는 validateSearch 스키마로 이미 타입이 추론됩니다
const { page, status } = location.search
return getOrders({ data: { page, status } })
},
component: OrdersPage,
})
function OrdersPage() {
const orders = Route.useLoaderData()
const { page, status } = Route.useSearch()
return (
<div>
<OrderFilters currentStatus={status} />
<OrderTable orders={orders} />
<Pagination currentPage={page} />
</div>
)
}| 요소 | 역할 |
|---|---|
ssr: 'data-only' |
로더는 서버, 렌더는 클라이언트 — 인터랙티브 UI 유지 |
validateSearch |
URL 검색 파라미터 타입 안전성 보장 (TanStack Router 고유 기능) |
requireAdmin() |
서버 함수 내부에서만 실행 — 클라이언트 번들에 노출 없음 |
Route.useLoaderData() |
로더 리턴 타입이 자동으로 추론됩니다, 별도 타입 선언 불필요 |
예시 2: 스트리밍 대시보드 — Suspense로 무거운 차트 분리하기
분석 페이지처럼 DB 집계 쿼리가 여럿 필요한 경우, 모든 데이터가 준비될 때까지 기다리면 첫 화면 렌더가 늦어집니다. 스트리밍 패턴으로 레이아웃을 먼저 보여주고 무거운 컴포넌트는 나중에 채우는 방식을 쓸 수 있습니다. 예시 1에서 정의한 서버 함수 패턴을 그대로 확장하면 됩니다.
// app/routes/analytics.tsx
import { Suspense } from 'react'
import { useSuspenseQuery } from '@tanstack/react-query'
import { createFileRoute } from '@tanstack/react-router'
import { getRevenueData, getUserActivity } from '~/functions/analytics'
export const Route = createFileRoute('/analytics')({
ssr: true,
component: AnalyticsPage,
})
function RevenueChart() {
const { data } = useSuspenseQuery({
queryKey: ['revenue'],
queryFn: () => getRevenueData(),
})
return <LineChart data={data} />
}
function UserActivityTable() {
const { data } = useSuspenseQuery({
queryKey: ['user-activity'],
queryFn: () => getUserActivity({ data: { days: 30 } }),
})
return <DataTable rows={data} />
}
function AnalyticsPage() {
return (
<div className="grid gap-6">
<PageHeader title="Analytics" />
<Suspense fallback={<ChartSkeleton />}>
<RevenueChart />
</Suspense>
<Suspense fallback={<TableSkeleton />}>
<UserActivityTable />
</Suspense>
</div>
)
}useSuspenseQuery + createServerFn 조합으로 어떤 컴포넌트가 어떤 데이터를 기다리는지가 코드에서 바로 읽힌다는 점이 생각보다 편했습니다. Next.js RSC 스트리밍과 개발자 경험 차이가 크지 않으면서, 개인적으로는 디버깅이 훨씬 쉬웠습니다.
예시 3: React Router에서 TanStack Start로 — 마이그레이션 비용은 어느 정도인가
ReactJS Day 2025에서 대규모 코드베이스를 React Router에서 TanStack Start로 이전한 사례가 발표됐는데, 핵심 포인트는 "기존 컴포넌트를 거의 건드리지 않아도 된다"는 점이었습니다. 라우트 정의 방식만 바꾸면 됩니다.
// 기존 React Router v6
// routes/dashboard.tsx
import { useLoaderData } from 'react-router-dom'
export async function loader() {
return fetch('/api/dashboard').then(r => r.json())
}
export default function Dashboard() {
const data = useLoaderData()
return <DashboardUI data={data} />
}// TanStack Start로 전환
// app/routes/dashboard.tsx
import { createFileRoute } from '@tanstack/react-router'
import { getDashboardData } from '~/functions/dashboard'
export const Route = createFileRoute('/dashboard')({
ssr: 'data-only',
loader: async () => getDashboardData(),
component: Dashboard,
})
function Dashboard() {
// useLoaderData 대신 Route.useLoaderData — 리턴 타입이 자동 추론됩니다
const data = Route.useLoaderData()
return <DashboardUI data={data} />
}DashboardUI 컴포넌트 자체는 건드릴 필요가 없습니다. 라우트 래퍼와 데이터 페칭 레이어만 교체하면 됩니다. 기존 컴포넌트 자산을 그대로 가져올 수 있다는 점이 마이그레이션 비용을 크게 낮춰줍니다.
장단점 분석
장점
| 항목 | 내용 |
|---|---|
| 단순한 멘탈 모델 | "use client" / "use server" 경계 관리가 없습니다. 서버 코드는 createServerFn 안에만 있고, 나머지는 전부 클라이언트입니다 |
| 완전한 타입 안전성 | 서버-클라이언트 경계를 타입 시스템이 커버합니다. 라우트 파라미터, 검색 파라미터, 로더 리턴 타입 모두 자동 추론됩니다 |
| Vite 빌드 속도 | 프로젝트가 커져도 개발 서버 콜드 스타트와 HMR이 빠릅니다. Platformatic 벤치마크에서 Next.js RSC 빌드 대비 최대 4배 빠른 결과가 보고됐습니다 |
| 적은 JS 번들 | 같은 벤치마크에서 Next.js 대비 약 40% 적은 JS 번들이 보고된 사례가 있습니다 |
| 투명한 동작 방식 | 프레임워크 매직 레이어가 최소화됩니다. 에러가 나면 어디서 났는지 스택 추적이 예측 가능합니다 |
| 배포 유연성 | Nitro 기반으로 Node.js, Cloudflare Workers, Vercel, Netlify, AWS Lambda 등 동일한 코드로 배포할 수 있습니다 |
솔직히 이 중에서 가장 체감이 컸던 건 "투명한 동작 방식"이었습니다. RSC 환경에서 에러가 어디서 터졌는지 몰라 막막했던 경험이 있다면, createServerFn 기반 구조에서 에러 스택이 얼마나 읽히는지가 빠르게 감이 옵니다.
단점 및 주의사항
| 항목 | 내용 | 대응 방안 |
|---|---|---|
| 생태계 규모 | Next.js 대비 튜토리얼, 써드파티 통합, 스타터 템플릿이 적습니다 | 공식 문서 품질이 높으니 공식 예시 위주로 시작하는 것이 좋습니다 |
| AI 코딩 도구 지원 | Copilot, Cursor 등이 Next.js 패턴에 훨씬 많이 학습되어 있습니다 | TanStack 공식 문서를 컨텍스트로 제공하면 상당 부분 커버됩니다 |
| 컴포넌트 레벨 서버 렌더링 불가 | RSC처럼 컴포넌트 단위 서버/클라이언트 분리는 되지 않고 라우트 단위가 최소입니다 | ssr: 'data-only' + TanStack Query 조합으로 상당 부분 대응 가능합니다 |
| 공식 이미지/폰트 최적화 없음 | Next.js의 <Image>, 폰트 자동 최적화 같은 기능이 없습니다 |
@unpic/react 같은 써드파티 이미지 컴포넌트로 대응할 수 있습니다 |
| 엔터프라이즈 레퍼런스 부족 | 대규모 조직의 프로덕션 사례가 Next.js에 비해 적습니다 | v1.0 이후 사례가 빠르게 쌓이는 중입니다 |
| 정적 사이트에는 오버킬 | 마케팅 페이지 같은 순수 정적 콘텐츠에는 과한 선택입니다 | 정적 콘텐츠 위주라면 Astro가 더 적합합니다 |
이 중에서 "AI 코딩 도구 지원" 항목은 생각보다 문제가 적었습니다. TanStack 문서 링크를 컨텍스트로 던져주면 Cursor도 제법 잘 따라옵니다. 오히려 "생태계 규모" 쪽, 특히 인증 연동 스타터 같은 게 없어서 처음 세팅하는 데 시간이 더 걸렸습니다. 이 부분은 솔직히 아직 아쉽습니다.
TanStack Query (v5): 서버 함수 결과를 클라이언트에서 캐싱하고 동기화하는 라이브러리입니다.
ssr: 'data-only'패턴과 결합하면 RSC의 데이터 페칭 역할을 클라이언트 캐시 레이어에서 상당 부분 커버할 수 있습니다.
실무에서 가장 흔한 실수
-
createServerFn을 컴포넌트 파일 안에 정의하는 것 — 처음에 편하다고 컴포넌트 파일 상단에 바로 정의했다가, 빌드 결과물을 뜯어보니 서버 코드가 클라이언트 번들에 섞여 있었습니다. 빌드 타임 번들 분리가 의도대로 동작하지 않을 수 있습니다. 서버 함수는 반드시 별도 파일(~/functions/)로 분리하는 것이 좋습니다. -
모든 라우트를
ssr: true로 설정하는 것 — SEO가 필요 없는 어드민 페이지에도 완전한 SSR을 달았다가, DevTools에서 불필요한 서버 렌더 요청을 확인하고ssr: 'data-only'로 바꿨습니다. 라우트 성격에 맞게 선택하는 것이 서버 부하를 줄이는 첫걸음입니다. -
validateSearch없이 검색 파라미터를 사용하는 것 — TanStack Router에서 가장 강력한 기능 중 하나가 타입 안전 검색 파라미터인데,validateSearch스키마를 정의하지 않으면location.search가any타입이 됩니다. 이건 런타임에 조용히 터지는 버그로 이어집니다 — 특히page파라미터를 숫자로 기대했다가 문자열로 들어오는 케이스에서요.
마치며
TanStack Start는 RSC 없이도, createServerFn과 Selective SSR, 스트리밍이라는 세 레이어만으로 SaaS 대시보드, 어드민 패널, B2B 앱 수준의 풀스택 요구사항을 충분히 커버합니다.
RSC가 꼭 필요한 케이스 — 컴포넌트 단위 서버/클라이언트 분리, Vercel AI SDK의 streamUI, use(cache) 같은 RSC 전용 API — 가 있다면 Next.js가 현실적인 선택입니다. 하지만 데이터 중심 앱에서 그 밖의 대부분 시나리오라면 TanStack Start의 단순하고 예측 가능한 구조가 오히려 생산성을 높여줍니다. 저도 처음엔 "RSC 없으면 뭔가 부족하지 않나" 싶었는데, 직접 써보고 나서 생각이 달라진 건 딱 한 가지였습니다 — 에러가 났을 때 어디서 났는지가 바로 보이더라고요. 그게 생각보다 개발 속도에 큰 차이를 만들었습니다.
지금 바로 시작해볼 수 있는 3단계입니다:
- 프로젝트를 생성해보시면 좋습니다 —
pnpm create tanstack --template react-start-basic으로 기본 프로젝트를 만들 수 있습니다. 파일 기반 라우팅과 기본 SSR이 이미 세팅된 상태로 시작됩니다. createServerFn하나를 직접 만들어보시면 좋습니다 — DB 없이도 됩니다.process.env를 읽거나 파일 시스템에 접근하는 간단한 함수를 만들고, DevTools 네트워크 탭에서 해당 코드가 클라이언트 번들에서 사라지는 걸 확인해보시면 동작 방식이 직관적으로 이해됩니다.- 같은 앱에서 두 가지 SSR 전략을 비교해보시면 좋습니다 — 하나의 라우트는
ssr: true, 다른 하나는ssr: 'data-only'로 설정하고 네트워크 탭과 페이지 소스를 비교해보시면 각 모드의 차이가 실감납니다. 어떤 페이지에 어떤 전략이 맞는지 감이 잡힐 겁니다.
참고 자료
- TanStack Start Overview | TanStack 공식 문서
- Selective SSR | TanStack 공식 문서
- Server Functions | TanStack 공식 문서
- React Server Components Your Way | TanStack Blog
- Why TanStack Start is Ditching Adapters | TanStack Blog
- TanStack Start vs Next.js 비교 | TanStack 공식 문서
- TanStack Start v1 출시 | InfoQ
- TanStack Start 소개 | LogRocket
- Selective SSR in TanStack Start | LogRocket
- TanStack Start vs Next.js | LogRocket
- React SSR Framework Benchmark | Platformatic
- React Server Components in TanStack | Frontend Masters
- TanStack Start 배포 가이드 | Cloudflare Workers
- TanStack Start vs Next.js 2026 | Alex Cloudstar