Skip to Content
IoT ์•ฑ ๊ฐœ๋ฐœ๋ฐ์ดํ„ฐ ๋ฐฑ์—”๋“œ

๋ฐ์ดํ„ฐ ๋ฐฑ์—”๋“œ

IronFlock์€ TimescaleDB๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฐ ํ”„๋กœ์ ํŠธ์— ์ „์šฉ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ํ”„๋กœ๋น„์ €๋‹ํ•ฉ๋‹ˆ๋‹ค. ์•ฑ์ด ๋ฐ์ดํ„ฐ ์Šคํ‚ค๋งˆ๋ฅผ ์ •์˜ํ•˜๋ฉด IronFlock์ด ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•˜๊ณ  ๋””๋ฐ”์ด์Šค๊ฐ€ ์•ฑ์— ์ถ”๊ฐ€๋˜๋Š” ์ˆœ๊ฐ„๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

์ž‘๋™ ๋ฐฉ์‹

  1. .ironflock/data-template.yml์— ๋ฐ์ดํ„ฐ ์Šคํ‚ค๋งˆ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
  2. IronFlock SDK๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์—ฃ์ง€ ์ฝ”๋“œ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐœํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  3. IronFlock์ด ์•ฑ์ด ์„ค์น˜๋œ ๊ฐ ํ”„๋กœ์ ํŠธ์—์„œ ์ž๋™์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  4. ๋ฐ์ดํ„ฐ๋Š” ๋””๋ฐ”์ด์Šค์—์„œ ๋ฉ”์‹œ์ง• ์‹œ์Šคํ…œ์„ ํ†ตํ•ด ํ”„๋กœ์ ํŠธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋กœ ํ๋ฆ…๋‹ˆ๋‹ค.

๊ฐ ํ”„๋กœ์ ํŠธ๋Š” ์ž์ฒด ๋ฌผ๋ฆฌ์  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค โ€” ํ”„๋กœ์ ํŠธ ๊ฐ„ ๋ฐ์ดํ„ฐ ๊ณต์œ ๋Š” ์—†์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๋Š” ์ž์‹ ์˜ ํ”„๋กœ์ ํŠธ์—์„œ ์•ฑ์ด ์ˆ˜์ง‘ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์™„์ „ํžˆ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๋Š” ์ด ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ์Šคํ‚ค๋งˆ ์ •์˜

.ironflock/ ๋””๋ ‰ํ„ฐ๋ฆฌ์— data-template.yml ํŒŒ์ผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค:

data: tables: - tablename: sensordata columns: - id: tsp name: ํƒ€์ž„์Šคํƒฌํ”„ description: ์ธก์ • ํƒ€์ž„์Šคํƒฌํ”„ path: args[0].timestamp dataType: timestamp - id: temperature name: ์˜จ๋„ description: ์„ญ์”จ ์˜จ๋„ ์ธก์ •๊ฐ’ path: args[0].temperature dataType: numeric - id: humidity name: ์Šต๋„ description: ์ƒ๋Œ€ ์Šต๋„ ๋ฐฑ๋ถ„์œจ path: args[0].humidity dataType: numeric - id: device_id name: ๋””๋ฐ”์ด์Šค ID description: ์†Œ์Šค ๋””๋ฐ”์ด์Šค ์‹๋ณ„์ž path: args[0].device_id dataType: string

์ปฌ๋Ÿผ ์˜ต์…˜

ํ•„๋“œ์„ค๋ช…
id๋‚ด๋ถ€ ์ปฌ๋Ÿผ ์‹๋ณ„์ž (ํƒ€์ž„์Šคํƒฌํ”„ ์ปฌ๋Ÿผ์—๋Š” tsp ์‚ฌ์šฉ)
name๋ณด๋“œ์— ํ‘œ์‹œ๋˜๋Š” ์‚ฌ๋žŒ์ด ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ์ปฌ๋Ÿผ ์ด๋ฆ„
description์„ ํƒ์  ์„ค๋ช…
path๋ฐœํ–‰๋œ ๋ฐ์ดํ„ฐ ๊ฐ์ฒด์—์„œ ๊ฐ’์˜ ๊ฒฝ๋กœ (์˜ˆ: args[0].temperature)
dataTypetimestamp, numeric, string, boolean ์ค‘ ํ•˜๋‚˜
secret์ด ์ปฌ๋Ÿผ์„ ์ €์žฅ ์‹œ ์•”ํ˜ธํ™”ํ•˜๊ณ  ์ผ๋ฐ˜ ์ฝ๊ธฐ์—์„œ๋Š” ์ ˆ๋Œ€ ํ‰๋ฌธ์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค โ€” ์•„๋ž˜ ๋น„๋ฐ€ ์ปฌ๋Ÿผ ์ฐธ๊ณ 

๋น„๋ฐ€ ์ปฌ๋Ÿผ

์ €์žฅ์€ ํ•ด์•ผ ํ•˜์ง€๋งŒ ์ ˆ๋Œ€ ํ‘œ์‹œ๋˜์–ด์„œ๋Š” ์•ˆ ๋˜๋Š” ๊ฐ’์ด ์žˆ์Šต๋‹ˆ๋‹ค. API ํ† ํฐ, ๋””๋ฐ”์ด์Šค ๋น„๋ฐ€๋ฒˆํ˜ธ, ๋ผ์ด์„ ์Šค ํ‚ค ๊ฐ™์€ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ปฌ๋Ÿผ์„ secret: true๋กœ ํ‘œ์‹œํ•˜๋ฉด ๋ฐ์ดํ„ฐ ๋ฐฑ์—”๋“œ๊ฐ€ ์‚ฝ์ž… ์‹œ์ ์— ์ด๋ฅผ ์•”ํ˜ธํ™”ํ•ฉ๋‹ˆ๋‹ค:

- tablename: credentials columns: - id: tsp dataType: timestamp - id: device_id dataType: string - id: api_token dataType: string secret: true

๊ทธ ์ดํ›„๋กœ๋Š” ์–ด๋–ค ์ผ๋ฐ˜ ์ฝ๊ธฐ๋„ ํ‰๋ฌธ์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค โ€” ๊ทธ ๊ฐ’์„ ์ž‘์„ฑํ•œ ์•ฑ์—๊ฒŒ์กฐ์ฐจ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค:

์ฝ๊ธฐ ๊ฒฝ๋กœ๋Œ๋ ค๋ฐ›๋Š” ๊ฐ’
๋ณด๋“œ, ์œ„์ ฏ, ๊ทธ๋ฆฌ๊ณ  ๋ฉ”์‹œ์ง€ ๋ผ์šฐํ„ฐ๋ฅผ ๊ฑฐ์น˜๋Š” ๊ทธ ๋ฐ–์˜ ๋ชจ๋“  ๊ฒƒํ”Œ๋ ˆ์ด์Šคํ™€๋” __secret__
SQL ์ ‘๊ทผ (FleetDB Access์˜ Postgres ๋กœ๊ทธ์ธ)์ €์žฅ๋œ ์•”ํ˜ธ๋ฌธ, ifsec:1:โ€ฆ
SDK์˜ ํ‰๋ฌธ ์กฐํšŒ ํ•จ์ˆ˜๋ณตํ˜ธํ™”๋œ ๊ฐ’

NULL์€ ๋ชจ๋“  ๊ฒฝ๋กœ์—์„œ NULL ๊ทธ๋Œ€๋กœ ์œ ์ง€๋˜๋ฏ€๋กœ, โ€œ์„ค์ •๋˜์—ˆ์ง€๋งŒ ์ˆจ๊ฒจ์งโ€๊ณผ โ€œํ•œ ๋ฒˆ๋„ ์ž‘์„ฑ๋˜์ง€ ์•Š์Œโ€์€ ๊ณ„์† ๊ตฌ๋ถ„๋ฉ๋‹ˆ๋‹ค.

๋น„๋ฐ€ ๊ฐ’์„ ํ‰๋ฌธ์œผ๋กœ ๋‹ค์‹œ ์ฝ๋Š” ๊ฒƒ์€ ์˜ค์ง ์•ฑ ์ž์‹ ์˜ ์ปจํ…Œ์ด๋„ˆ์—์„œ SDK๋ฅผ ํ†ตํ•ด์„œ๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค โ€” SDK ์ฐธ์กฐ์˜ ๋น„๋ฐ€ ์ปฌ๋Ÿผ์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค. ๋ณด๋“œ๋‚˜ ๋‹ค๋ฅธ ์•ฑ์€ ์ด๋ฅผ ์ „ํ˜€ ์–ป์„ ์ˆ˜ ์—†์œผ๋ฉฐ, ๋ฐ”๋กœ ๊ทธ ์ ์ด โ€œํ‰๋ฌธ์œผ๋กœ ์ ˆ๋Œ€ ํ‘œ์‹œ๋˜์ง€ ์•Š์Œโ€์„ ๊ฒ‰์น˜๋ ˆ๊ฐ€ ์•„๋‹Œ ์‚ฌ์‹ค๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

๋น„๋ฐ€ ๊ฐ’์„ ์žƒ์ง€ ์•Š๊ณ  ํ–‰ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ. ์—”ํ‹ฐํ‹ฐ ํ…Œ์ด๋ธ”์—์„œ ํ–‰์„ ํŽธ์ง‘ํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ๋Š” ์‹ค์ œ ๋น„๋ฐ€ ๊ฐ’์„ ๋˜๋Œ๋ ค ๋ณด๋‚ผ ์ˆ˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค โ€” ์ฝ๊ธฐ๋Š” ์–ธ์ œ๋‚˜ ํ”Œ๋ ˆ์ด์Šคํ™€๋”๋งŒ ๋Œ๋ ค์ฃผ์—ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋ฐ์ดํ„ฐ ๋ฐฑ์—”๋“œ๋Š” ์“ฐ๊ธฐ ์‹œ์ ์— ํ”Œ๋ ˆ์ด์Šคํ™€๋” __secret__(๊ทธ๋ฆฌ๊ณ  ๋ณด๋“œ๊ฐ€ ํ‘œ์‹œํ•˜๋Š” โ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ข ๋งˆ์Šคํฌ)๋ฅผ ์ด์ „ ๊ฐ’ ์œ ์ง€๋กœ ์ทจ๊ธ‰ํ•˜๋ฉฐ, ๋น„๋ฐ€ ์ปฌ๋Ÿผ์„ ์ƒ๋žตํ•ด๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. ๋ช…์‹œ์ ์œผ๋กœ null์„ ๋ณด๋‚ด๋ฉด ๋น„๋ฐ€ ๊ฐ’์ด ๋น„์›Œ์ง‘๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ณด๋“œ ์–‘์‹์—์„œ ๊ธฐ๊ณ„์˜ ์„ค๋ช…์„ ํŽธ์ง‘ํ•ด๋„ ๊ทธ ์ ‘๊ทผ ์ฝ”๋“œ๊ฐ€ ์ง€์›Œ์ง€๋Š” ์ผ์€ ๊ฒฐ์ฝ” ์—†์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ๋‘ ๊ฐ€์ง€ ๊ฒฐ๊ณผ๊ฐ€ ๋”ฐ๋ผ ๋‚˜์˜ต๋‹ˆ๋‹ค: ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด __secret__์™€ โ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ข ์ž์ฒด๋Š” ๋น„๋ฐ€ ๊ฐ’์œผ๋กœ ์ €์žฅํ•  ์ˆ˜ ์—†๊ณ (์›์‹œ ifsec:โ€ฆ ์•”ํ˜ธ๋ฌธ๋„ ์ž…๋ ฅ์œผ๋กœ ๊ฑฐ๋ถ€๋ฉ๋‹ˆ๋‹ค), ์—”ํ‹ฐํ‹ฐ ํ‚ค๊ฐ€ ์—†๋Š” ํ…Œ์ด๋ธ”์—์„œ๋Š” ํ”Œ๋ ˆ์ด์Šคํ™€๋” ์“ฐ๊ธฐ๊ฐ€ ๊ฑฐ๋ถ€๋ฉ๋‹ˆ๋‹ค โ€” ์œ ์ง€ํ•  ์ด์ „ ํ–‰์ด ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋ฏธ๋ฆฌ ๊ณ ๋ คํ•ด ๋‘์–ด์•ผ ํ•  ์„ธ ๊ฐ€์ง€ ๊ฒฐ๊ณผ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ถŒ๊ณ  ์‚ฌํ•ญ์ด ์•„๋‹ˆ๋ผ ๋„˜์–ด์„ค ์ˆ˜ ์—†๋Š” ์ œํ•œ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค:

  • ๋น„๋ฐ€ ์ปฌ๋Ÿผ์€ ๋ฌธ์ž์—ด๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์•”ํ˜ธํ™”์˜ ์‚ฐ์ถœ๋ฌผ์€ ํ…์ŠคํŠธ์ด๋ฏ€๋กœ numeric, boolean, timestamp ์ปฌ๋Ÿผ์€ ๋น„๋ฐ€๋กœ ์ง€์ •ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ํ•„์ˆ˜ ์ปฌ๋Ÿผ์ธ tsp ์—ญ์‹œ ๋น„๋ฐ€๋กœ ์ง€์ •ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  • ๋น„๋ฐ€ ์ปฌ๋Ÿผ์œผ๋กœ๋Š” ํ•„ํ„ฐ๋ง, ๊ทธ๋ฃนํ™”, ์ •๋ ฌ์„ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ํ–‰์ด ๊ฐ์ž์˜ ๋ฌด์ž‘์œ„ ๊ฐ’์œผ๋กœ ์•”ํ˜ธํ™”๋˜๋ฏ€๋กœ, ๋™์ผํ•œ ๋น„๋ฐ€ ๊ฐ’์„ ๋‹ด์€ ๋‘ ํ–‰๋„ ์„œ๋กœ ๋‹ค๋ฅธ ์•”ํ˜ธ๋ฌธ์œผ๋กœ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ๋น„๋ฐ€ ์ปฌ๋Ÿผ์— ๋Œ€ํ•œ ๋™๋“ฑ ํ•„ํ„ฐ, GROUP BY, ORDER BY, DISTINCT๋Š” ์• ์ดˆ์— ๋™์ž‘ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. โ€œ์ด ๊ฐ’์ด ์ผ์น˜ํ•ฉ๋‹ˆ๊นŒ?โ€์— ๋‹ตํ•˜๋ ค๋ฉด SDK์˜ ๊ฒ€์ฆ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. ์ด ํ•จ์ˆ˜๋Š” ๋ฌด์–ธ๊ฐ€๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋Œ€์‹  ๋ฐ์ดํ„ฐ ๋ฐฑ์—”๋“œ ๋‚ด๋ถ€์—์„œ ๋น„๊ต๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • ๋น„๋ฐ€ ์ปฌ๋Ÿผ์€ ์—”ํ‹ฐํ‹ฐ ํ‚ค๊ฐ€ ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ํ–‰๋งˆ๋‹ค ์•”ํ˜ธ๋ฌธ์ด ๋‹ค๋ฅด๋ฏ€๋กœ ์—”ํ‹ฐํ‹ฐ๋ณ„ ์ตœ์‹  ์กฐํšŒ๋Š” ๋ชจ๋“  ํ–‰์„ ์ œ๊ฐ๊ธฐ ๋‹ค๋ฅธ ์—”ํ‹ฐํ‹ฐ๋กœ ์ทจ๊ธ‰ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋น„๋ฐ€ ์ปฌ๋Ÿผ์„ maintainLatestFlagFor์— ์ง€์ •ํ•˜๋ฉด ๊ทธ๋Œ€๋กœ ๊ฑฐ๋ถ€๋ฉ๋‹ˆ๋‹ค.

๋’ค์˜ ๋‘ ์ œํ•œ์€ ๋ฐ์ดํ„ฐ ํ…œํ”Œ๋ฆฟ์ด ๊ฒ€์ฆ๋  ๋•Œ ํ™•์ธ๋˜๋ฏ€๋กœ, ์ด๋ฅผ ์–ด๊ธฐ๋Š” ํ…Œ์ด๋ธ”์€ ๋‚˜์ค‘์— ์˜ค์ž‘๋™ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋ฆด๋ฆฌ์Šค ์‹œ์ ์— ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.

ํ…Œ์ด๋ธ” ์˜ต์…˜

columns ์™ธ์—๋„ ํ…Œ์ด๋ธ”์„ ์–ด๋–ป๊ฒŒ ์„ค๋ช…ํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ์–ผ๋งˆ๋‚˜ ์˜ค๋ž˜ ๋ณด๊ด€ํ• ์ง€ ์ œ์–ดํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์„ ํƒ์  ํ‚ค๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

data: tables: - tablename: sensordata description: ์ƒ์‚ฐ ํ˜„์žฅ์˜ ํ™˜๊ฒฝ ์ธก์ •๊ฐ’ chunkTimeInterval: 1 hour dropAfter: 30 days columns: # ...
ํ•„๋“œ์„ค๋ช…
tablenameํ…Œ์ด๋ธ” ์ด๋ฆ„
description์„ ํƒ์  ์„ค๋ช…. UI์— ํ‘œ์‹œ๋˜๋ฉฐ AI ์—์ด์ „ํŠธ๊ฐ€ ํ…Œ์ด๋ธ”์„ ์ดํ•ดํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค
chunkTimeIntervalํ…Œ์ด๋ธ”์ด ๋‚˜๋‰˜๋Š” ์‹œ๊ฐ„ ํŒŒํ‹ฐ์…˜์˜ ํฌ๊ธฐ. ๊ธฐ๋ณธ๊ฐ’์€ 7 days
dropAfter๋ณด์กด ๊ธฐ๊ฐ„ โ€” ์ด๋ณด๋‹ค ์˜ค๋ž˜๋œ ํŒŒํ‹ฐ์…˜์€ ์ž๋™์œผ๋กœ ์‚ญ์ œ๋ฉ๋‹ˆ๋‹ค
downsample๊ธด ์‹œ๊ฐ„ ์ฐฝ ์ฐจํŠธ๋ฅผ ๋น ๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์ „ ์ง‘๊ณ„๋œ ์‚ฌ๋ณธ์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค โ€” ์•„๋ž˜ ์—ฐ์† ๋‹ค์šด์ƒ˜ํ”Œ๋ง ์ฐธ๊ณ 
maintainLatestFlagFor๊ณ ์œ  ์—”ํ‹ฐํ‹ฐ๋ฅผ ์‹๋ณ„ํ•˜๋Š” ์ปฌ๋Ÿผ โ€” ์•„๋ž˜ ์—”ํ‹ฐํ‹ฐ์˜ ์ตœ์‹  ์ƒํƒœ ์ถ”์  ์ฐธ๊ณ 
private์ด ํ…Œ์ด๋ธ”์„ ๋‹ค๋ฅธ ์•ฑ์—์„œ ์ˆจ๊น๋‹ˆ๋‹ค โ€” ์•„๋ž˜ ๋‹ค๋ฅธ ์•ฑ๊ณผ ๋ฐ์ดํ„ฐ ๊ณต์œ ํ•˜๊ธฐ ์ฐธ๊ณ 

**chunkTimeInterval**์€ ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ๋ฅผ ๋””์Šคํฌ์—์„œ ์–ด๋–ป๊ฒŒ ๋ถ„ํ• ํ• ์ง€ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ํŒŒํ‹ฐ์…˜ ํ•˜๋‚˜๊ฐ€ ํ•œ ๋ฒˆ์— ์กฐํšŒํ•˜๋Š” ๋ฐ์ดํ„ฐ๋Ÿ‰๊ณผ ๋Œ€๋žต ์ผ์น˜ํ•˜๋„๋ก ์„ ํƒํ•˜์„ธ์š”. ๋งค์ดˆ ์ˆ˜์ง‘๋˜๋Š” ๊ณ ๋นˆ๋„ ๋ฐ์ดํ„ฐ๋Š” ์ž‘์€ ์ฒญํฌ(๋ถ„~์‹œ๊ฐ„ ๋‹จ์œ„)๊ฐ€, ์ฒœ์ฒœํžˆ ๋ณ€ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋Š” ํฐ ์ฒญํฌ(์ฃผ ๋‹จ์œ„)๊ฐ€ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์•ฑ์˜ ๊ธฐ๋ณธ๊ฐ’์ผ ๋ฟ์ด๋ฉฐ, ํ”„๋กœ์ ํŠธ ์†Œ์œ ์ž๊ฐ€ ๋‚˜์ค‘์— ์ž์‹ ์˜ ๋ฐ์ดํ„ฐ ๋ฐฑ์—”๋“œ์—์„œ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

**dropAfter**๋Š” ํ…Œ์ด๋ธ”์„ ๋กค๋ง ์œˆ๋„์šฐ๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ง€์ •ํ•œ ๊ธฐ๊ฐ„๋ณด๋‹ค ์˜ค๋ž˜๋œ ํŒŒํ‹ฐ์…˜์ด ํ†ต์งธ๋กœ ์‚ญ์ œ๋˜๋ฏ€๋กœ ๊ฐœ๋ณ„ ํ–‰์„ ์ง€์šฐ๋Š” ๊ฒƒ๋ณด๋‹ค ํ›จ์”ฌ ์ €๋ ดํ•ฉ๋‹ˆ๋‹ค. ์ •๋ฆฌ ์ž‘์—…์€ dropAfter / 4 ์ฃผ๊ธฐ๋กœ ์‹คํ–‰๋˜๋ฏ€๋กœ, ๋ ˆ์ฝ”๋“œ๋Š” ํŒŒํ‹ฐ์…˜์ด ์ œ๊ฑฐ๋˜๊ธฐ ์ „๊นŒ์ง€ ๋งŒ๋ฃŒ ์‹œ์ ์„ ์ตœ๋Œ€ ํ•ด๋‹น ๊ธฐ๊ฐ„์˜ 1/4๋งŒํผ ๋„˜๊ฒจ ๋‚จ์•„ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ๋ฌด๊ธฐํ•œ ๋ณด๊ด€ํ•˜๋ ค๋ฉด dropAfter๋ฅผ ์ƒ๋žตํ•˜์„ธ์š”.

๋‘ ๊ฐ’ ๋ชจ๋‘ PostgreSQL ์ธํ„ฐ๋ฒŒ ๋ฌธ์ž์—ด์„ ๋ฐ›์Šต๋‹ˆ๋‹ค โ€” 30 minutes, 1 hour, 7 days, 6 months.

์—ฐ์† ๋‹ค์šด์ƒ˜ํ”Œ๋ง

๋Œ€์‹œ๋ณด๋“œ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ์ดํ„ฐ ์ง‘๊ณ„๋ฅผ ์š”์ฒญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค โ€” ์‹œ๊ฐ„๋ณ„ ํ‰๊ท , ์ผ๋ณ„ ํ•ฉ๊ณ„, ๊ธฐ๊ณ„๋ณ„ ๊ฐœ์ˆ˜ ๋“ฑ. ์ด๋ฅผ ์›์‹œ ๋ ˆ์ฝ”๋“œ์—์„œ ๊ณ„์‚ฐํ•˜๋Š” ๊ฒƒ์€ ํ•˜๋ฃจ์น˜๋ผ๋ฉด ๊ดœ์ฐฎ์ง€๋งŒ 1๋…„์น˜๋ผ๋ฉด ๋น„์šฉ์ด ํฝ๋‹ˆ๋‹ค. ํ…Œ์ด๋ธ”์— downsample์„ ์ถ”๊ฐ€ํ•˜๋ฉด ํ”Œ๋žซํผ์ด ์ง€์†์ ์œผ๋กœ ๊ฐฑ์‹ ๋˜๋Š” ์‚ฌ์ „ ์ง‘๊ณ„๋œ ์‚ฌ๋ณธ์„ ์œ ์ง€ํ•˜๊ณ , ๊ธด ์‹œ๊ฐ„ ์ฐฝ ์ฟผ๋ฆฌ๋ฅผ ์›์‹œ ๋ฐ์ดํ„ฐ ๋Œ€์‹  ๊ทธ ์‚ฌ๋ณธ์œผ๋กœ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค:

data: tables: - tablename: sensordata dropAfter: 30 days downsample: bucket: 1 minute keepFor: 2 years paths: - payload.temperature columns: # ...
ํ•„๋“œ์„ค๋ช…
bucket์‚ฌ์ „ ์ง‘๊ณ„๋œ ์‚ฌ๋ณธ์˜ ์„ธ๋ถ„์„ฑ. ๊ธฐ๋ณธ๊ฐ’์€ 1 minute
keepFor๋‹ค์šด์ƒ˜ํ”Œ๋ง๋œ ์ด๋ ฅ์„ ๋ณด๊ด€ํ•  ๊ธฐ๊ฐ„. ์ƒ๋žตํ•˜๋ฉด ๋ฌด๊ธฐํ•œ ๋ณด๊ด€
pathsํฌํ•จํ•  JSON ํ•„๋“œ ๊ฒฝ๋กœ. ๋Œ€์‹œ๋ณด๋“œ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ํ‘œ๊ธฐ๋ฒ•

**bucket**์€ ์ฐจํŠธ์— ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€์žฅ ๋ฏธ์„ธํ•œ ํ•ด์ƒ๋„์ž…๋‹ˆ๋‹ค โ€” ์ด๋ณด๋‹ค ํ›จ์”ฌ ๋ฏธ์„ธํ•œ ๋ฒ„ํ‚ท์„ ์š”์ฒญํ•˜๋Š” ์ฐจํŠธ๋Š” ๋Œ€์‹  ์›์‹œ ํ…Œ์ด๋ธ”์„ ์ฝ์Šต๋‹ˆ๋‹ค. ํ•˜๋ฃจ๋ฅผ ๊ท ๋“ฑํ•˜๊ฒŒ ๋‚˜๋ˆ„๋Š” 1 second๋ถ€ํ„ฐ 1 day๊นŒ์ง€์˜ ๊ณ ์ • ํญ ์ธํ„ฐ๋ฒŒ(1 minute, 5 minutes, 1 hour)์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์ธ 1 minute์€ ์‚ฌ์‹ค์ƒ ๋ชจ๋“  ๋Œ€์‹œ๋ณด๋“œ์— ์ ํ•ฉํ•˜๋ฉฐ, ๋ฒ„ํ‚ท์„ ๋” ํฌ๊ฒŒ ์žก์œผ๋ฉด ์Šคํ† ๋ฆฌ์ง€์™€ ์“ฐ๊ธฐ ์ฒ˜๋ฆฌ๋Ÿ‰์ด ์ค„์–ด๋“ญ๋‹ˆ๋‹ค.

**keepFor**๋Š” ๊ธด ์ด๋ ฅ์„ ์• ์ดˆ์— ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ด์ฃผ๋Š” ๊ฐ’์ž…๋‹ˆ๋‹ค. ์›์‹œ ๋ ˆ์ฝ”๋“œ๋Š” dropAfter์— ๋”ฐ๋ผ ์‚ฌ๋ผ์ง€์ง€๋งŒ ๋‹ค์šด์ƒ˜ํ”Œ๋ง๋œ ์‚ฌ๋ณธ์€ ์ž์ฒด ๋ณด์กด ๊ธฐ๊ฐ„์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค. ์›์‹œ ๋ฐ์ดํ„ฐ๋ฅผ 30์ผ, ๋‹ค์šด์ƒ˜ํ”Œ๋ง๋œ ๋ฐ์ดํ„ฐ๋ฅผ 2๋…„ ๋ณด๊ด€ํ•˜๋ฉด, ๋ณด๋“œ๋Š” ์Šคํ† ๋ฆฌ์ง€์˜ ์ผ๋ถ€๋งŒ ์‚ฌ์šฉํ•˜๊ณ ๋„ 2๋…„์น˜ ์‹œ๊ฐ„๋ณ„ ํ‰๊ท ์„ ๊ณ„์† ์ฐจํŠธ๋กœ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. dropAfter๋ณด๋‹ค ๊ธธ๊ฒŒ ์„ค์ •ํ•˜์„ธ์š” โ€” ๊ทธ ๋ฐ˜๋Œ€๋Š” ํ”Œ๋žซํผ์ด ์ž˜๋ชป๋œ ๊ตฌ์„ฑ์œผ๋กœ ๊ฐ„์ฃผํ•˜์—ฌ ๊ฑฐ๋ถ€ํ•ฉ๋‹ˆ๋‹ค.

**paths**๋Š” ๋‹ค์šด์ƒ˜ํ”Œ๋ง์„ JSON ์ปฌ๋Ÿผ ๋‚ด๋ถ€์˜ ๊ฐ’๊นŒ์ง€ ํ™•์žฅํ•ฉ๋‹ˆ๋‹ค. ์ˆซ์ž ์ปฌ๋Ÿผ์€ ์ž๋™์œผ๋กœ ํฌํ•จ๋˜์ง€๋งŒ, JSON ์ปฌ๋Ÿผ์—๋Š” ๊ณ ์ •๋œ ํ‚ค ์ง‘ํ•ฉ์ด ์—†์œผ๋ฏ€๋กœ JSON ํ•„๋“œ๋Š” ๋ช…์‹œ์ ์œผ๋กœ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์„ ์–ธํ•˜์ง€ ์•Š์€ ํ•„๋“œ๋„ ๋Œ€์‹œ๋ณด๋“œ์—์„œ ๊ทธ๋Œ€๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค โ€” ๋‹จ์ง€ ์›์‹œ ํ…Œ์ด๋ธ”์—์„œ ๊ณ„์‚ฐ๋  ๋ฟ์ž…๋‹ˆ๋‹ค.

๊ทธ ๋ฐ–์˜ ๋ชจ๋“  ๊ฒƒ์€ ์ž๋™์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ์ˆซ์ž ์ปฌ๋Ÿผ์— ๋Œ€ํ•ด ํ†ต๊ณ„(ํ‰๊ท , ํ•ฉ๊ณ„, ์ตœ์†Ÿ๊ฐ’, ์ตœ๋Œ“๊ฐ’, ์ฒซ ๋ฒˆ์งธ ๊ฐ’, ๋งˆ์ง€๋ง‰ ๊ฐ’, ๋ ˆ์ฝ”๋“œ ์ˆ˜)๊ฐ€ ์œ ์ง€๋˜๋ฉฐ, ํ…Œ์ด๋ธ”์˜ ์—”ํ‹ฐํ‹ฐ ํ‚ค(maintainLatestFlagFor, ์—†์œผ๋ฉด ๋ฐœํ–‰ ๋””๋ฐ”์ด์Šค)๋กœ ๊ทธ๋ฃนํ™”๋ฉ๋‹ˆ๋‹ค. ๋Œ€์‹œ๋ณด๋“œ๋Š” ์•„๋ฌด๋Ÿฐ ์„ค์ •๋„ ํ•„์š” ์—†๊ณ  ์ด ๊ธฐ๋Šฅ์„ ์ธ์ง€ํ•  ํ•„์š”๋„ ์—†์Šต๋‹ˆ๋‹ค: ์œ„์ ฏ์€ ํ‰์†Œ์ฒ˜๋Ÿผ ์ฟผ๋ฆฌํ•˜๊ณ , ํ”Œ๋žซํผ์ด ์ฟผ๋ฆฌ๋งˆ๋‹ค ์‚ฌ์ „ ์ง‘๊ณ„๋œ ์‚ฌ๋ณธ์œผ๋กœ ์‘๋‹ตํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํŒ๋‹จํ•ฉ๋‹ˆ๋‹ค โ€” ์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ๋ณธ์ด ๊ทธ๋ฃน์œผ๋กœ ๋ฌถ์ง€ ์•Š๋Š” ์ปฌ๋Ÿผ์„ ํ•„ํ„ฐ๊ฐ€ ์ฐธ์กฐํ•˜๋Š” ๋“ฑ ์‘๋‹ตํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ์—๋Š” ํˆฌ๋ช…ํ•˜๊ฒŒ ์›์‹œ ํ…Œ์ด๋ธ”๋กœ ๋˜๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค.

์Šคํ‚ค๋งˆ ๋ณ€๊ฒฝ์€ ์‚ฌ๋ณธ์„ ์žฌ๊ตฌ์ถ•ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์šด์ƒ˜ํ”Œ๋ง๋œ ํ…Œ์ด๋ธ”์˜ ์ปฌ๋Ÿผ์„ ์ถ”๊ฐ€ยท์ œ๊ฑฐํ•˜๊ฑฐ๋‚˜ ํƒ€์ž…์„ ๋ฐ”๊พธ๋Š” ๊ฒƒ โ€” ๋˜๋Š” downsample ๋ธ”๋ก ์ž์ฒด๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ โ€” ์€ ์›์‹œ ํ…Œ์ด๋ธ”์—์„œ ์‚ฌ์ „ ์ง‘๊ณ„๋œ ์‚ฌ๋ณธ์„ ์žฌ๊ตฌ์ถ•ํ•ฉ๋‹ˆ๋‹ค. dropAfter๋ณด๋‹ค ์˜ค๋ž˜๋œ ๊ฒƒ์€ ์žฌ๊ตฌ์„ฑํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ์†Œ์‹ค๋ฉ๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ค ๋•Œ ์ด ๋ธ”๋ก๋„ ํ•จ๊ป˜ ์„ค์ •ํ•˜๊ณ , ์˜ค๋ž˜ ์šด์˜๋œ ํ…Œ์ด๋ธ”์— ๋Œ€ํ•œ ์ดํ›„์˜ ์Šคํ‚ค๋งˆ ๋ณ€๊ฒฝ์€ ์‹ ์ค‘ํ•œ ๊ฒฐ์ •์œผ๋กœ ๋‹ค๋ฃจ์‹ญ์‹œ์˜ค.

์—ฃ์ง€ ์ฝ”๋“œ์—์„œ ๋ฐ์ดํ„ฐ ๋ฐœํ–‰

IronFlock SDK๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•ฑ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•ฉ๋‹ˆ๋‹ค:

from ironflock import IronFlock flock = IronFlock() flock.publish_to_table("sensordata", { "timestamp": "2025-01-15T10:30:00Z", "temperature": 23.5, "humidity": 62.1, "device_id": "sensor-001" })

๊ณ ๋นˆ๋„ ๋ฐ์ดํ„ฐ์˜ ๊ฒฝ์šฐ, ํ–‰๋งˆ๋‹ค ํ•œ ๋ฒˆ์”ฉ ์™•๋ณตํ•˜๋Š” ๋Œ€์‹  publish_rows_to_table / publishRowsToTable(fire-and-forget) ๋˜๋Š” append_rows_to_table / appendRowsToTable(์‚ฝ์ž… ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜)์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ์ผ ๋ฉ”์‹œ์ง€๋กœ ์—ฌ๋Ÿฌ ํ–‰์„ ์ „์†กํ•˜์‹ญ์‹œ์˜ค. ๊ฐ ๋ฐฐ์น˜๋Š” ์›์ž์ ์œผ๋กœ ์‚ฝ์ž…๋ฉ๋‹ˆ๋‹ค โ€” ์ „๋ถ€ ์•„๋‹ˆ๋ฉด ์ „๋ฌด์ž…๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ SDK ์ฐธ์กฐ๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

๋ณ€ํ™˜ ํ…Œ์ด๋ธ”

์›์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ ์ง‘๊ณ„ํ•˜๊ฑฐ๋‚˜ ์ฒ˜๋ฆฌํ•˜๋Š” SQL ๋ณ€ํ™˜์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

data: tables: - tablename: sensordata columns: # ... ์›์‹œ ๋ฐ์ดํ„ฐ ์ปฌ๋Ÿผ ... transforms: - tablename: hourly_averages materialize: true schedule: "0 * * * *" sql: > SELECT time_bucket('1 hour', tsp) AS hour, avg(temperature) AS avg_temp, avg(humidity) AS avg_humidity FROM sensordata GROUP BY hour columns: - id: hour name: ์‹œ๊ฐ„ dataType: timestamp - id: avg_temp name: ํ‰๊ท  ์˜จ๋„ dataType: numeric - id: avg_humidity name: ํ‰๊ท  ์Šต๋„ dataType: numeric
ํ•„๋“œ์„ค๋ช…
tablenameํŒŒ์ƒ ํ…Œ์ด๋ธ”์˜ ์ด๋ฆ„
materializetrue์ด๋ฉด ๊ฒฐ๊ณผ๊ฐ€ ํ…Œ์ด๋ธ”๋กœ ์ €์žฅ๋จ
schedule๋ณ€ํ™˜์ด ์‹คํ–‰๋˜๋Š” ํฌ๋ก  ํ‘œํ˜„์‹
sql๋ณ€ํ™˜์„ ๊ณ„์‚ฐํ•˜๋Š” SQL ์ฟผ๋ฆฌ
columns์ถœ๋ ฅ์˜ ์ปฌ๋Ÿผ ์ •์˜

๋ณ€ํ™˜ ํ…Œ์ด๋ธ”์€ ์ผ๋ฐ˜ ํ…Œ์ด๋ธ”๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ณด๋“œ ๋ฐ SDK๋ฅผ ํ†ตํ•ด ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ณ€ํ™˜์€ ์ž์‹ ์˜ SQL์ด ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ทธ๋Œ€๋กœ ์ฝํž™๋‹ˆ๋‹ค: ์œ„์ ฏ์˜ ์‹œ๊ฐ„ ์ฐฝ, ์บ˜๋ฆฐ๋” ํ•„ํ„ฐ, latest ๋ชจ๋“œ๋Š” ํ…Œ์ด๋ธ”์— ์ ์šฉ๋˜๋ฉฐ ๋ณ€ํ™˜์—์„œ๋Š” ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์„ธ ๊ฐ€์ง€ ๊ทœ์น™์ด ๋”ฐ๋ผ ๋‚˜์˜ต๋‹ˆ๋‹ค. ์‹œ๊ฐ„ ๋ฒ”์œ„๋Š” ์ฟผ๋ฆฌ ์•ˆ์—์„œ ์ œํ•œํ•˜๊ณ (WHERE tsp > now() - interval '7 days'), ์‹œ๊ณ„์—ด์€ ์ตœ์‹  ์ˆœ์œผ๋กœ ์ •๋ ฌํ•˜์—ฌ(ORDER BY <time column> DESC) ํ–‰ ์ œํ•œ์ด ๊ฑธ๋ ค๋„ ์ตœ์‹  ํ–‰์ด ๋‚จ๊ฒŒ ํ•˜๋ฉฐ, ๋ณด๋“œ์—์„œ ๊ทธ๋ฆฌ๊ฑฐ๋‚˜ ํ•„ํ„ฐ๋งํ•  ๋ชจ๋“  ์ปฌ๋Ÿผ์„ ์„ ํƒํ•˜์‹ญ์‹œ์˜ค โ€” ๋ณ€ํ™˜์—๋Š” ์•”๋ฌต์ ์ธ ํƒ€์ž„์Šคํƒฌํ”„ ์ปฌ๋Ÿผ์ด๋‚˜ ๋””๋ฐ”์ด์Šค ์ปฌ๋Ÿผ์ด ์—†์Šต๋‹ˆ๋‹ค. ํ•œ ๋ฒˆ์˜ ์ฝ๊ธฐ๋Š” ์ตœ๋Œ€ 3000ํ–‰์„ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ ์ฟผ๋ฆฌ์—์„œ ์ง‘๊ณ„ํ•˜์‹ญ์‹œ์˜ค.

๋ณ€ํ™˜์„ ์–ป๋Š” ๋ฐฉ๋ฒ•์ด ์•ฑ๊ณผ ํ•จ๊ป˜ ๋ฐฐํฌํ•˜๋Š” ๊ฒƒ๋งŒ ์žˆ๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค: Data Access ๊ถŒํ•œ์ด ์žˆ๋Š” ํ”„๋กœ์ ํŠธ ๋ฉค๋ฒ„๋Š” ์•ฑ ์—†์ด๋„ ํ”„๋กœ์ ํŠธ์˜ ๋ฐ์ดํ„ฐ ๋ทฐ์—์„œ ๋™์ผํ•œ ์ข…๋ฅ˜์˜ ๋ณ€ํ™˜์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, AI ์–ด์‹œ์Šคํ„ดํŠธ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ ๋ณ€ํ™˜์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

์—”ํ‹ฐํ‹ฐ์˜ ์ตœ์‹  ์ƒํƒœ ์ถ”์ 

์‹ค์ œ ์—”ํ‹ฐํ‹ฐ(๊ธฐ๊ณ„, ์ž์‚ฐ, ์ƒ์‚ฐ ์ฃผ๋ฌธ)์˜ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ํ…Œ์ด๋ธ”์˜ ๊ฒฝ์šฐ IronFlock์€ **์ตœ์‹  ์ƒํƒœ ์ถ”์ (latest-state tracking)**์ด๋ผ๋Š” ํŒจํ„ด์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

๋ฌด์–ธ๊ฐ€๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ ํ–‰์„ ๋ฎ์–ด์“ฐ๋Š” ๋Œ€์‹  ํ•ญ์ƒ ์ƒˆ ํ–‰์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ๊ณ ์œ ํ•œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์‹๋ณ„ํ•˜๋Š” ์ปฌ๋Ÿผ์„ ์„ ์–ธํ•ด ๋‘๋ฉด, IronFlock์ด ํ…Œ์ด๋ธ”์„ ์ฝ์„ ๋•Œ๋งˆ๋‹ค ์—”ํ‹ฐํ‹ฐ๋ณ„๋กœ ๊ฐ€์žฅ ์ตœ๊ทผ ํ–‰์„ ๋„์ถœํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ชจ๋“  ๋ณ€๊ฒฝ์˜ ์ „์ฒด ์ด๋ ฅ์„ ๋ณด์œ ํ•˜๋ฉด์„œ ํ˜„์žฌ ์ƒํƒœ๋งŒ ์ฟผ๋ฆฌํ•˜๋Š” ๊ฒƒ๋„ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

maintainLatestFlagFor๋กœ ํ…Œ์ด๋ธ”์—์„œ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค:

- tablename: machineform maintainLatestFlagFor: ['machinename'] columns: - id: tsp dataType: timestamp - id: machinename dataType: string - id: machinetype dataType: string - id: active dataType: boolean - id: description dataType: string

maintainLatestFlagFor๋Š” ๊ณ ์œ ํ•œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ํ•จ๊ป˜ ์‹๋ณ„ํ•˜๋Š” ์ปฌ๋Ÿผ ๋ชฉ๋ก์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. ํ–‰ ์ž์ฒด์—๋Š” ์•„๋ฌด๊ฒƒ๋„ ๊ธฐ๋ก๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. IronFlock์€ ํ•ด๋‹น ์—”ํ‹ฐํ‹ฐ ํ‚ค์™€ ํƒ€์ž„์Šคํƒฌํ”„๋กœ ํ…Œ์ด๋ธ”์„ ์ธ๋ฑ์‹ฑํ•˜๊ณ , ์ฟผ๋ฆฌ ์‹œ์ ์— ์—”ํ‹ฐํ‹ฐ๋ณ„๋กœ ๊ฐ€์žฅ ์ตœ๊ทผ ํ–‰์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋Šฆ๊ฒŒ ๋„์ฐฉํ•˜๊ฑฐ๋‚˜ ์ˆœ์„œ๊ฐ€ ๋’ค๋ฐ”๋€ ์ฑ„ ๋„์ฐฉํ•œ ํ–‰์ด ์˜ค๋ž˜๋œ ํ‘œ์‹œ๋ฅผ ๋‚จ๊ธฐ๋Š” ์ผ์€ ๊ฒฐ์ฝ” ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ถ€๋ถ„ ํ–‰์œผ๋กœ ์—”ํ‹ฐํ‹ฐ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ

์—”ํ‹ฐํ‹ฐ ํ…Œ์ด๋ธ”์— ์ถ”๊ฐ€๋˜๋Š” ํ–‰์€ ๊ทธ ์—”ํ‹ฐํ‹ฐ์˜ ์ƒˆ ๋ฒ„์ „์ž…๋‹ˆ๋‹ค โ€” ๊ทธ๋ฆฌ๊ณ  ๋ฐ˜๋“œ์‹œ ์™„์ „ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ํ–‰์ด ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ์ปฌ๋Ÿผ์€ ํ•ด๋‹น ์—”ํ‹ฐํ‹ฐ์˜ ์ง์ „ ์ตœ์‹  ํ–‰์—์„œ ๋ฌผ๋ ค๋ฐ›์œผ๋ฏ€๋กœ, ํ•„๋“œ ํ•˜๋‚˜๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋ ค๋ฉด ์—”ํ‹ฐํ‹ฐ ํ‚ค, ํƒ€์ž„์Šคํƒฌํ”„, ๊ทธ๋ฆฌ๊ณ  ๊ทธ ํ•„๋“œ๋งŒ ๋ฐœํ–‰ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค:

์ƒˆ ํ–‰์˜ ์ปฌ๋Ÿผ์ด์ €์žฅ๋œ ๋ฒ„์ „์— ๋‹ด๊ธฐ๋Š” ๊ฐ’
์ œ๊ณต๋œ ๊ฒฝ์šฐ (0, false, ""๋„ ์ œ๊ณต๋œ ๊ฒƒ์œผ๋กœ ์นฉ๋‹ˆ๋‹ค)์ œ๊ณต๋œ ๊ฐ’
๋ช…์‹œ์ ์œผ๋กœ null์ธ ๊ฒฝ์šฐNULL โ€” ์ปฌ๋Ÿผ์ด ๋น„์›Œ์ง‘๋‹ˆ๋‹ค
์—†๋Š” ๊ฒฝ์šฐ์ง์ „ ์ตœ์‹  ํ–‰์˜ ๊ฐ’

์•Œ์•„ ๋‘๋ฉด ์ข‹์€ ๋‘ ๊ฐ€์ง€ ์„ธ๋ถ€ ์‚ฌํ•ญ์ด ์žˆ์Šต๋‹ˆ๋‹ค:

  • ๋ชจ๋“  ์ปฌ๋Ÿผ์„ ์ œ๊ณตํ•˜๋Š” ํ–‰์€ ์ง์ „ ํ–‰ ์กฐํšŒ๋ฅผ ์•„์˜ˆ ๊ฑด๋„ˆ๋›ฐ๋ฏ€๋กœ, ์™„์ „ํ•œ ํ–‰์€ ์ง€๊ธˆ๊นŒ์ง€์™€ ๋˜‘๊ฐ™์ด ์ €๋ ดํ•ฉ๋‹ˆ๋‹ค โ€” ๊ณ ๋นˆ๋„ ๊ฒฝ๋กœ์—์„œ๋Š” ๊ณ„์† ์™„์ „ํ•œ ํ–‰์„ ๋ณด๋‚ด์‹ญ์‹œ์˜ค.
  • ์ƒ์†์€ ์‹œ๊ฐ„ ์ˆœ์„œ๋ฅผ ์กด์ค‘ํ•ฉ๋‹ˆ๋‹ค. ๋” ์˜ค๋ž˜๋œ ํƒ€์ž„์Šคํƒฌํ”„๋ฅผ ๋‹ฌ๊ณ  ๋„์ฐฉํ•œ ํ–‰(๋ฐฑํ•„)์€ ์ž์‹ ์˜ tsp ์ด์ „์ด๊ฑฐ๋‚˜ ๊ฐ™์€ ์‹œ์ ์˜ ํ–‰์—์„œ๋งŒ ๋ฌผ๋ ค๋ฐ›์œผ๋ฉฐ, ๋” ์ƒˆ๋กœ์šด ํ–‰์—์„œ๋Š” ๊ฒฐ์ฝ” ๋ฌผ๋ ค๋ฐ›์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

maintainLatestFlagFor๊ฐ€ ์—†๋Š” ํ…Œ์ด๋ธ”์€ ๋‹จ์ˆœ ์ถ”๊ฐ€ ์˜๋ฏธ๋ก ์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค: ํ–‰์ด ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ์ปฌ๋Ÿผ์€ NULL๋กœ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.

ํ˜„์žฌ ๊ธฐ๊ณ„ ์ƒํƒœ๋งŒ ์ฟผ๋ฆฌํ•˜๋ ค๋ฉด:

SELECT DISTINCT ON (machinename) * FROM machineform ORDER BY machinename, tsp DESC

ํŠน์ • ๊ธฐ๊ณ„์˜ ์ „์ฒด ์ด๋ ฅ์„ ๋ณด๋ ค๋ฉด:

SELECT * FROM machineform WHERE machinename = 'Assembly-Line-01' ORDER BY tsp

์ด ์ฟผ๋ฆฌ๋ฅผ ์ง์ ‘ ์ž‘์„ฑํ•  ์ผ์€ ๊ฑฐ์˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด ํ…Œ์ด๋ธ”์— ์—ฐ๊ฒฐ๋œ ๋ณด๋“œ์˜ ์œ„์ ฏ์—๋Š” ํ•„ํ„ฐ ์„ค์ •์— latest ํ† ๊ธ€์ด ์žˆ์–ด ์ถ”๊ฐ€ ์ž‘์—… ์—†์ด ์‚ฌ์šฉ์ž๊ฐ€ ํ•ญ์ƒ ํ˜„์žฌ ๊ฐ’์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. SDK์—์„œ๋Š” filterAnd์— {"latest": true}๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋™์ผํ•œ ๋ชจ๋“œ๋ฅผ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค โ€” getHistory๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

latest_flag์—์„œ ์—…๊ทธ๋ ˆ์ด๋“œ: ์ด์ „ ๋ฒ„์ „์˜ IronFlock์€ latest_flag๋ผ๋Š” ๋ฌผ๋ฆฌ์  boolean ์ปฌ๋Ÿผ์„ ์ €์žฅํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ์ปฌ๋Ÿผ์€ ๋” ์ด์ƒ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค โ€” ๋Œ€์‹  ํ˜„์žฌ ์ƒํƒœ๋ฅผ SQL์—์„œ ๋„์ถœํ•˜๋ฏ€๋กœ ํ–‰์ด ์ˆœ์„œ์— ์–ด๊ธ‹๋‚˜๊ฒŒ ๋„์ฐฉํ•ด๋„ ๊ฒฐ๊ณผ๊ฐ€ ์ •ํ™•ํ•˜๊ฒŒ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. latest_flag = true๋กœ ํ•„ํ„ฐ๋งํ•˜๋Š” ๊ธฐ์กด ๋ณด๋“œ์™€ SDK ํ˜ธ์ถœ์€ ๊ณ„์† ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค: IronFlock์ด ์ด๋ฅผ ์ธ์‹ํ•˜์—ฌ ์ตœ์‹  ์ƒํƒœ ๋ชจ๋“œ๋ฅผ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ƒˆ ์ฝ”๋“œ์—์„œ๋Š” latest ํ† ๊ธ€ ๋˜๋Š” {"latest": true} ํ•„ํ„ฐ ํ•ญ๋ชฉ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ ˆ์ฝ”๋“œ ์†Œํ”„ํŠธ ์‚ญ์ œ

IronFlock์˜ ์ถ”๊ฐ€ ์ „์šฉ ๋ชจ๋ธ์—์„œ๋Š” ๋ ˆ์ฝ”๋“œ๊ฐ€ ๋ฌผ๋ฆฌ์ ์œผ๋กœ ์‚ญ์ œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  deleted boolean ์ปฌ๋Ÿผ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ ˆ์ฝ”๋“œ๋ฅผ ์‚ญ์ œ๋œ ๊ฒƒ์œผ๋กœ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ „์ฒด ๊ฐ์‚ฌ ์ถ”์ ์„ ๋ณด์กดํ•˜๋ฉด์„œ ์‚ญ์ œ๋œ ๋ ˆ์ฝ”๋“œ๋ฅผ ๋Œ€์‹œ๋ณด๋“œ์—์„œ ์ˆจ๊น๋‹ˆ๋‹ค.

๋ชจ๋“  ์—”ํ‹ฐํ‹ฐ ํ…Œ์ด๋ธ”์— deleted ์ปฌ๋Ÿผ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค:

- id: deleted name: ์‚ญ์ œ๋จ dataType: boolean

์‚ฌ์šฉ์ž๊ฐ€ ๋ ˆ์ฝ”๋“œ๋ฅผ ์‚ญ์ œํ•  ๋•Œ(์˜ˆ: ๋ณด๋“œ์˜ ์–‘์‹์„ ํ†ตํ•ด) ์•ฑ์€ ํ•ด๋‹น ์—”ํ‹ฐํ‹ฐ์— ๋Œ€ํ•ด deleted: true๊ฐ€ ํฌํ•จ๋œ ์ƒˆ ํ–‰์„ ๋ฐœํ–‰ํ•ฉ๋‹ˆ๋‹ค. maintainLatestFlagFor์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ์ด ์ƒˆ ํ–‰์ด ์ตœ์‹  ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ์ดํ›„์˜ ๋ถ€๋ถ„ ํ–‰์€ ๋‹ค๋ฅธ ์ปฌ๋Ÿผ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ deleted ํ‘œ์‹œ๋ฅผ ๋ฌผ๋ ค๋ฐ›์œผ๋ฏ€๋กœ, deleted๋ฅผ ์–ธ๊ธ‰ํ•˜์ง€ ์•Š๋Š” ์—…๋ฐ์ดํŠธ๊ฐ€ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋˜์‚ด๋ฆฌ์ง€๋„, ์ˆจ๊ธฐ์ง€๋„ ์•Š์Šต๋‹ˆ๋‹ค.

ํ™œ์„ฑ(์‚ญ์ œ๋˜์ง€ ์•Š์€) ํ˜„์žฌ ๋ ˆ์ฝ”๋“œ๋งŒ ์ฟผ๋ฆฌํ•˜๋ ค๋ฉด:

SELECT * FROM ( SELECT DISTINCT ON (machinename) * FROM machineform ORDER BY machinename, tsp DESC ) latest WHERE deleted IS NULL OR deleted = false

deleted ๊ฒ€์‚ฌ๋Š” ๊ธฐ๊ณ„๋ณ„ ์ตœ์‹  ํ–‰์ด ์„ ํƒ๋œ ๋‹ค์Œ์— ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด ์ˆœ์„œ๊ฐ€ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค: ์‚ญ์ œ๋œ ํ–‰์„ ๋จผ์ € ๊ฑธ๋Ÿฌ๋‚ด๋ฉด ์ด์ „์˜ ์‚ญ์ œ๋˜์ง€ ์•Š์€ ํ–‰์ด ํ˜„์žฌ ์ƒํƒœ๋กœ ๋‹ค์‹œ ๋‚˜ํƒ€๋‚˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๋ณด๋“œ ์œ„์ ฏ๊ณผ SDK๋Š” ๋™์ผํ•œ ์ˆœ์„œ๋ฅผ ์ž๋™์œผ๋กœ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค โ€” latest ํ† ๊ธ€(๋˜๋Š” {"latest": true})์„ deleted ํ•„ํ„ฐ์™€ ์กฐํ•ฉํ•˜๋ฉด ์ •ํ™•ํžˆ ์ด ๋™์ž‘์ด ๋ฉ๋‹ˆ๋‹ค. ์–‘์‹ ์ œ์ถœ ์งํ›„ ์‚ญ์ œ๋œ ๋ ˆ์ฝ”๋“œ๊ฐ€ ๋Œ€์‹œ๋ณด๋“œ์—์„œ ์ฆ‰์‹œ ์‚ฌ๋ผ์ง€์ง€๋งŒ, ์ด๋ ฅ ๋ฐ ๊ฐ์‚ฌ ๋ชฉ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—๋Š” ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ์•ฑ๊ณผ ๋ฐ์ดํ„ฐ ๊ณต์œ ํ•˜๊ธฐ

๋ฐ์ดํ„ฐ ๋ฐฑ์—”๋“œ๋Š” ์•ฑ ์ „์šฉ์ž…๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ์— ์„ค์น˜๋œ ๋‹ค๋ฅธ ์–ด๋–ค ์•ฑ๋„ ์—ฌ๋Ÿฌ๋ถ„์˜ ํ…Œ์ด๋ธ”์„ ๋ณผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. data-template.yml์˜ ์„ ํƒ์  ํ‚ค ๋‘ ๊ฐœ๊ฐ€ ์ด๋ฅผ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ์•ฑ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์œผ๋ ค๋ฉด, ์ฝ์–ด์˜ฌ ์•ฑ๋“ค์„ ์ตœ์ƒ์œ„ consumes: ์„น์…˜์— ๋‚˜์—ดํ•ฉ๋‹ˆ๋‹ค. data: ์•ˆ์ด ์•„๋‹ˆ๋ผ ๊ทธ ์˜†์— ๋‘ก๋‹ˆ๋‹ค.

consumes: - app: machine-monitor reason: "๋ชจ๋‹ˆํ„ฐ์˜ ๊ธฐ๊ณ„ ์ƒํƒœ ๋ฐ ์นด์šดํ„ฐ ์ŠคํŠธ๋ฆผ์—์„œ OEE๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค" data: tables: - tablename: oee_results columns: # ... ํ‰์†Œ์™€ ๊ฐ™์ด ์•ฑ ์ž์ฒด ํ…Œ์ด๋ธ”

app์€ ์ œ๊ณต ์•ฑ์˜ ๊ธฐ์ˆ  ์ด๋ฆ„์ด๊ฑฐ๋‚˜, ํ”„๋กœ์ ํŠธ ๋‚ด ๋ชจ๋“  ์•ฑ์„ ์˜๋ฏธํ•˜๋Š” "*"(๋”ฐ์˜ดํ‘œ ํ•„์ˆ˜)์ž…๋‹ˆ๋‹ค. reason์€ ๋™์˜ ๋Œ€ํ™”์ƒ์ž์—์„œ ์‚ฌ์šฉ์ž์—๊ฒŒ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ์„ ์–ธ๋งŒ์œผ๋กœ๋Š” ์•„๋ฌด๊ฒƒ๋„ ํ—ˆ์šฉ๋˜์ง€ ์•Š์œผ๋ฉฐ ์‚ฌ์šฉ์ž์˜ ์Šน์ธ์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ๋ณ„ ํ…Œ์ด๋ธ”์„ ๋น„๊ณต๊ฐœ๋กœ ๋‘๋ ค๋ฉด private: true๋กœ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ์ •์˜ํ•œ ๋ชจ๋“  ๊ฒƒ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ณต์œ  ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ๋น„๊ณต๊ฐœ ํ…Œ์ด๋ธ”์ด๋‚˜ ํŠธ๋žœ์Šคํผ์€ ๋‹ค๋ฅธ ์•ฑ์ด ๋ณด๋Š” ์นดํƒˆ๋กœ๊ทธ์— ์ „ํ˜€ ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

data: tables: - tablename: measurements # ๊ณต์œ ๋จ(๊ธฐ๋ณธ๊ฐ’) columns: [ ... ] - tablename: calibration_state # ๋‚ด๋ถ€์šฉ โ€” ๋‹ค๋ฅธ ์•ฑ์—๋Š” ์ ˆ๋Œ€ ๋ณด์ด์ง€ ์•Š์Œ private: true columns: [ ... ]

์ ‘๊ทผ ๊ถŒํ•œ์€ ์ฝ๊ธฐ ์ „์šฉ์ด๋ฉฐ, ํ”„๋กœ์ ํŠธ๋ณ„๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ๋ถ€์—ฌํ•˜๊ณ  ์–ธ์ œ๋“ ์ง€ ์ฒ ํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ „์ฒด ๋ชจ๋ธ๊ณผ ์ œ๊ณต ์•ฑ์˜ ์ด๋ ฅยท๋ผ์ด๋ธŒ ์ŠคํŠธ๋ฆผ์„ ์ฝ๋Š” SDK ํ˜ธ์ถœ์€ ๋‹ค๋ฅธ ์•ฑ์˜ ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.

Last updated on