๐Ÿ‡บ๐Ÿ‡ธ Glancer โ€” ๋ ˆ์ผ์ฆˆ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์งˆ๋ฌธ์„ ์‰ฌ์šด ๋ง๋กœ ๋ฌผ์–ด๋ณด์„ธ์š”

๋ฐœํ–‰: (2026๋…„ 5์›” 28์ผ AM 02:11 GMT+9)
5 ๋ถ„ ์†Œ์š”
์›๋ฌธ: Dev.to

Source: Dev.to

Overview

Glancer๋Š” Ruby on Rails ์—”์ง„์œผ๋กœ, ์ž์—ฐ์–ด๋ฅผ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์งˆ์˜ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. ๊ด€๋ จ ์Šคํ‚ค๋งˆ ์ปจํ…์ŠคํŠธ๋ฅผ ๊ฐ€์ ธ์™€ SELECT ์ฟผ๋ฆฌ(๋˜๋Š” ActiveRecord ํ‘œํ˜„์‹)๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ด๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๊ฒ€์ฆยท์‹คํ–‰ํ•œ ๋’ค, ๊ฒฐ๊ณผ์™€ ์‚ฌ๋žŒ์—๊ฒŒ ์ฝํžˆ๊ธฐ ์‰ฌ์šด ์„ค๋ช…์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

Example
โ€œ์ง€๋‚œ 30์ผ ๋™์•ˆ ์ฃผ๋ฌธ์ด ๋ช‡ ๊ฑด ์žˆ์—ˆ๊ณ , ์ƒํƒœ๋ณ„๋กœ ๊ทธ๋ฃนํ™”๋œ ๊ฒฐ๊ณผ๋Š”?โ€
โ†’ SELECT๊ฐ€ ์‹คํ–‰๋˜๊ณ , ๊ฒฐ๊ณผ๊ฐ€ ํ‘œ์‹œ๋˜๋ฉฐ, ๋‹ต๋ณ€์ด ์ž์—ฐ์–ด๋กœ ์ž‘์„ฑ๋ฉ๋‹ˆ๋‹ค.

Blazer์—์„œ ์˜๊ฐ์„ ๋ฐ›์€ Glancer๋Š” ์ˆ˜๋™ SQL ์ž‘์„ฑ์„ ์ž์—ฐ์–ด ์งˆ๋ฌธ์œผ๋กœ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค.

Installation

# Add to your Gemfile
gem "glancer"

์ œ๋„ˆ๋ ˆ์ดํ„ฐ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•ฉ๋‹ˆ๋‹ค:

rails generate glancer:install
rails db:migrate
rails glancer:index:all

์•ฑ์—์„œ /glancer ๊ฒฝ๋กœ์— ์ ‘์†ํ•˜๋ฉด ์งˆ๋ฌธ์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Configuration

์ œ๋„ˆ๋ ˆ์ดํ„ฐ๊ฐ€ ์ดˆ๊ธฐํ™” ํŒŒ์ผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ LLM ์ œ๊ณต์ž๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ตœ์†Œํ•œ์˜ Gemini ์„ค์ • ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

# config/initializers/glancer.rb
Glancer.configure do |config|
  config.llm_provider   = :gemini
  config.llm_model      = "gemini-2.0-flash"
  config.gemini_api_key = ENV["GEMINI_API_KEY"]

  config.schema_permission = true
end

์ง€์›๋˜๋Š” ์ œ๊ณต์ž์—๋Š” OpenAI, OpenRouter, ๊ทธ๋ฆฌ๊ณ  RubyLLM์ด ์ง€์›ํ•˜๋Š” ๋ชจ๋“  ๋ชจ๋ธ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ์—ญํ• ๋ณ„๋กœ ๋‹ค๋ฅธ ๋ชจ๋ธ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์˜ˆ: ์ฟผ๋ฆฌ ์ƒ์„ฑ์—๋Š” ๋” ๋˜‘๋˜‘ํ•œ ๋ชจ๋ธ, ์‘๋‹ต ์ž‘์„ฑ์—๋Š” ๋” ์ €๋ ดํ•œ ๋ชจ๋ธ).

Usage

  1. ๋ธŒ๋ผ์šฐ์ €์—์„œ /glancer๋ฅผ ์—ฝ๋‹ˆ๋‹ค.
  2. ์ž์—ฐ์–ด๋กœ ์งˆ๋ฌธ์„ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
  3. Glancer๊ฐ€ ์Šคํ‚ค๋งˆ ์ปจํ…์ŠคํŠธ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ , ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑยท๊ฒ€์ฆํ•œ ๋’ค ํŠธ๋žœ์žญ์…˜ ์•ˆ์—์„œ ์‹คํ–‰ํ•˜๊ณ , ๊ฒฐ๊ณผ์™€ ์„ค๋ช…์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

Safety

  • ๋ชจ๋“  ์ฟผ๋ฆฌ๋Š” ํ•ญ์ƒ ๋กค๋ฐฑ๋˜๋Š” ํŠธ๋žœ์žญ์…˜ ์•ˆ์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
  • ํ‚ค์›Œ๋“œ ์ฐจ๋‹จ ๋ฆฌ์ŠคํŠธ๊ฐ€ DELETE, UPDATE, INSERT, DROP ๋“ฑ๊ณผ ๊ฐ™์€ ๋ฌธ์žฅ์„ ์‹คํ–‰๊ธฐ๊นŒ์ง€ ๋„๋‹ฌํ•˜๊ธฐ ์ „์— ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค.
  • ์ถ”๊ฐ€ ๋ณดํ˜ธ๋ฅผ ์œ„ํ•ด Glancer๋ฅผ ์ฝ๊ธฐ ์ „์šฉ ๋ ˆํ”Œ๋ฆฌ์นด์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

No Extra Infrastructure

์ž„๋ฒ ๋”ฉ์€ ๊ธฐ์กด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ JSON ์ปฌ๋Ÿผ์— ์ €์žฅ๋ฉ๋‹ˆ๋‹คโ€”์™ธ๋ถ€ ๋ฒกํ„ฐ ์Šคํ† ์–ด(Pinecone, Weaviate ๋“ฑ)๋Š” ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Custom Context

config/glancer/llm_context.glancer.md์— ๋งˆํฌ๋‹ค์šด ํŒŒ์ผ์„ ์ถ”๊ฐ€ํ•ด ๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™, ์ƒํƒœ๊ฐ’, ๋งค์ถœ ๊ณ„์‚ฐ์‹, ๋ฌด์‹œํ•  ์ปฌ๋Ÿผ ๋“ฑ์„ Glancer์—๊ฒŒ ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

- `orders.status` ๊ฐ’: "pending" | "paid" | "shipped" | "refunded"
- ์›” ๋งค์ถœ = SUM(orders.total) WHERE status = "paid"
- "churn"์— ๋Œ€ํ•œ ์งˆ๋ฌธ์ด ๋“ค์–ด์˜ค๋ฉด `subscriptions` ํ…Œ์ด๋ธ”์˜ `churned_at` ์ปฌ๋Ÿผ์„ ์‚ฌ์šฉ

UI Features

  • ๊ฒฐ๊ณผ๊ฐ€ ํ…Œ์ด๋ธ” ํ˜•ํƒœ๋กœ ํ‘œ์‹œ๋˜๋ฉฐ ์›ํด๋ฆญ CSV ๋‚ด๋ณด๋‚ด๊ธฐ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  • ์ ์ ˆํ•œ ๊ฒฝ์šฐ ์ฐจํŠธ๊ฐ€ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
  • ์ฟผ๋ฆฌ๋Š” ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋ผ ๋ฉ”์ธ ์•ฑ ์Šค๋ ˆ๋“œ๊ฐ€ ์ž์œ ๋กญ๊ฒŒ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.
  • @table_name์„ ์ž…๋ ฅํ•˜๋ฉด ํŠน์ • ํ…Œ์ด๋ธ”์„ ์งˆ๋ฌธ์— ๊ณ ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ƒ์„ฑ๋œ SQL์„ ์ธ๋ผ์ธ์œผ๋กœ ํŽธ์ง‘ํ•˜๊ณ  ๋‹ค์‹œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋งˆ์ดํฌ๋กœ ์งˆ๋ฌธ์„ ๋ฐ›์•„ ์ ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์Šคํ‚ค๋งˆ ๋ทฐ์–ด๋Š” /glancer/db-schema์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Blazer Integration

์ด๋ฏธ Blazer๊ฐ€ ์„ค์น˜๋ผ ์žˆ๋‹ค๋ฉด, Glancer๋Š” ์ƒ์„ฑ๋œ SQL์„ ๋ฐ”๋กœ Blazer์—์„œ ์—ด ์ˆ˜ ์žˆ๋Š” ๋ฒ„ํŠผ์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

Contribution & Feedback

Glancer๋Š” ์Šคํ„ฐ๋”” ํ”„๋กœ์ ํŠธ๋กœ ์‹œ์ž‘ํ–ˆ์œผ๋ฉฐ ํ˜„์žฌ ๋ฒ„์ „ 1.0.0์ž…๋‹ˆ๋‹ค. ์ด์Šˆ์™€ ํ’€ ๋ฆฌํ€˜์ŠคํŠธ๋ฅผ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค. ์œ ์šฉํ•˜๋‹ค๊ณ  ์ƒ๊ฐ๋˜๋ฉด ๋ ˆํฌ์ง€ํ† ๋ฆฌ์— โญ๋ฅผ ๋‹ฌ์•„ ์ฃผ์„ธ์š”.

  • GitHub:
  • RubyGems:**
0 ์กฐํšŒ
Back to Blog

๊ด€๋ จ ๊ธ€

๋” ๋ณด๊ธฐ ยป