하나의 언어로 프론트엔드, 백엔드, 데이터베이스를 모두. 컴파일 타임 반응성부터 RAG-native 하이브리드 DB까지 — 모두 Vais 컴파일러 위에서 동작합니다.
세 가지 핵심 제품
각 레이어는 독립적으로 사용하거나, Vais 생태계 전체와 함께 결합할 수 있습니다.
런타임 Virtual DOM 없이 컴파일 타임에 반응성을 해결하는 웹 프레임워크. Vais 컴파일러가 직접 최적화된 DOM 업데이트 코드를 생성합니다.
벡터 검색, 그래프 쿼리, SQL, 전문 검색(FTS)을 단일 엔진에 통합한 임베딩 가능한 데이터베이스. AI 애플리케이션에 최적화되어 있습니다.
Express/Axum 스타일의 라우팅 API를 제공하는 고성능 HTTP 서버. vaisdb와 zero-copy FFI로 직접 연결되며 Vais 타입 안전성을 서버까지 확장합니다.
풀스택 예시
vais-web, vais-server, vaisdb를 함께 사용하는 실제 패턴입니다.
# vais-web: 컴파일 타임 반응성, SSR 지원
U vais_web::{Component, signal, effect}
U vais_web::html::{div, input, ul, li}
S SearchResult { title: str, score: f32 }
# 컴포넌트 정의 — 컴파일 타임에 DOM 업데이트 코드 생성
P F SearchPage() -> Component {
query := signal("")
results := signal(Vec::new())
# effect: query 변경 시 자동 재실행 (컴파일 타임 의존성 추적)
effect(|| {
I query.get().len() >= 2 {
res := fetch_search(query.get())
results.set(res)
}
})
div(|| {
input(
placeholder: "VaisDB에서 검색...",
on_input: |e| query.set(e.value)
)
ul(|| {
F render_item(r: SearchResult) {
li("~{r.title} (score: ~{r.score:.2})")
}
results.get().iter() |> map(render_item)
})
})
}
# vais-server: Express/Axum 스타일 라우팅
U vais_server::{App, Router, Json}
U vaisdb::{Db, HybridQuery}
S SearchReq { q: str, limit: i32 }
S SearchResp { results: Vec<Hit>, took_ms: f64 }
# GET /api/search?q=...&limit=10
A F handle_search(req: SearchReq, db: Db) -> Json<SearchResp> {
# HybridQuery: 벡터 + 키워드 동시 검색 (RAG-native)
hits := Y db.hybrid_query(HybridQuery {
text: req.q,
top_k: req.limit,
mode: "rrf", # reciprocal rank fusion
})?
Json(SearchResp {
results: hits,
took_ms: elapsed_ms(),
})
}
F main() {
db := Db::open("./data/vais.db")!
app := App::new()
.state(db)
.get("/api/search", handle_search)
.serve_static("./dist") # VaisX 빌드 결과물 서빙
app.listen("0.0.0.0:8080")!
}
# VaisDB: Vector + Graph + SQL + FTS 하이브리드
U vaisdb::{Db, Collection, EmbedModel}
S Article {
id: i64,
title: str,
body: str,
tags: Vec<str>,
# 임베딩은 자동 생성 — 별도 파이프라인 불필요
#[embed(model = "text-embedding-3-small", field = "body")]
vec: Vec<f32>,
}
F setup_db() -> Db {
db := Db::open("./data/vais.db")!
# 컬렉션 생성: SQL 테이블 + 벡터 인덱스 + FTS 인덱스 자동 설정
db.collection::<Article>("articles")
.vector_index("hnsw", dim: 1536)
.fts_index(fields: ["title", "body"])
.graph_edges("related_to")
.create()!
db
}
# RAG 파이프라인 — 한 줄로 완성
A F rag_query(db: Db, question: str) -> str {
context := Y db.rag(question, top_k: 5)?
llm_complete("~{context}\n\nQ: ~{question}")!
}