ํ”„๋กœ์ ํŠธ/DB ์ž๋™ํ™”

DB ์ผ์ผ ์ ๊ฒ€ ์ž๋™ํ™” POC (4) ์—‘์…€๋กœ ๋งŒ๋“  ๋ฐ๋ชจ API

THE NICOLE 2026. 6. 15. 13:53

ํ•ต์‹ฌ ์š”์•ฝ

  • ์ ๊ฒ€ ๋Œ€์ƒ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•˜๋Š” DPM API๊ฐ€ ์‚ฌ๋‚ด๋ง ์ „์šฉ์ด๋ผ ๊ฐœ๋ฐœ PC์—์„œ๋Š” ํ˜ธ์ถœํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋ฐ›์€ ์—‘์…€ ์‹ค๋ฐ์ดํ„ฐ๋ฅผ ์‹ค์ œ API์™€ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ๋‚ด๋ณด๋‚ด๋Š” ๋ฐ๋ชจ ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.
  • ๋ชฉํ‘œ๋Š” ๋‘ ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. (1) ์‹ค์ œ DPM API์™€ ์š”์ฒญ·์‘๋‹ต ํ˜•ํƒœ๋ฅผ ๋™์ผํ•˜๊ฒŒ ๋งž์ถฐ ํ˜„์žฅ ์ „ํ™˜ ์‹œ ์ฃผ์†Œ๋งŒ ๋ฐ”๊พธ๋ฉด ๋˜๊ฒŒ ํ•œ๋‹ค. (2) ์ด ๋ฐ๋ชจ๋กœ API ํ˜ธ์ถœ ์ฝ”๋“œ๋ฅผ ๋ฏธ๋ฆฌ ๊ฐœ๋ฐœ·๊ฒ€์ฆํ•œ๋‹ค.
  • ์˜์กด์„ฑ ์—†์ด ํŒŒ์ด์ฌ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ http.server๋กœ ๋‹จ์ผ ํŒŒ์ผ(demo_api.py)๋กœ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํ•ต์‹ฌ์€ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ๋ชจ๋“ˆ(collector)์˜ ์—‘์…€ ์ฝ๊ธฐ ๋กœ์ง์„ ๊ทธ๋Œ€๋กœ ์žฌ์‚ฌ์šฉํ•œ ์ ์ž…๋‹ˆ๋‹ค. ๋ฐ๋ชจ์™€ ์ˆ˜์ง‘ ๋ชจ๋“ˆ์ด ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์“ฐ๋ฏ€๋กœ ๊ฒฐ๊ณผ๊ฐ€ ์–ด๊ธ‹๋‚  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  • ๊ฒ€์ฆ ๊ฒฐ๊ณผ ์—‘์…€ ์ง์ ‘ ์ฝ๊ธฐ ๊ฒฝ๋กœ์™€ ๋ฐ๋ชจ API ํ˜ธ์ถœ ๊ฒฝ๋กœ๊ฐ€ 3๊ฐœ DB ๋ชจ๋‘ ์™„์ „ํžˆ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ƒˆ์Šต๋‹ˆ๋‹ค.

1. ๋ฐ๋ชจ API๊ฐ€ ํ•„์š”ํ•œ ์ด์œ 

์ด ์‹œ์Šคํ…œ์€ ๋ชจ๋‹ˆํ„ฐ๋ง ์†”๋ฃจ์…˜(DPM)์˜ OPEN API์—์„œ DB ์ง€ํ‘œ๋ฅผ ๋ฐ›์•„์˜ต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๊ทธ API๋Š” ์‚ฌ๋‚ด๋ง ์ „์šฉ ์ฃผ์†Œ(์˜ˆ: http://10.x.x.x:8081)๋ผ ์™ธ๋ถ€ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋Š” ์ ‘๊ทผ์ด ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ํ† ํฐ์ด ๋ฉ€์ฉกํ•ด๋„ ๋„คํŠธ์›Œํฌ๊ฐ€ ๋‹ฟ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๊ฐœ๋ฐœ ๋‹จ๊ณ„์—์„œ๋Š” ๋ฐœ์ฃผ์ฒ˜๊ฐ€ ์ถ”์ถœํ•ด ์ค€ ํ•œ ๋‹ฌ์น˜ 1๋ถ„ ๋‹จ์œ„ ์—‘์…€ ๋ฐ์ดํ„ฐ๋กœ ์ž‘์—…ํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์ œ๋Š”, ํ˜„์žฅ์— ๊ฐ€์„œ ์‹ค์ œ API๋กœ ๋ฐ”๊ฟ€ ๋•Œ ์ฝ”๋“œ๊ฐ€ ๋งŽ์ด ๋ฐ”๋€Œ๋ฉด ์œ„ํ—˜ํ•˜๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ์ค„์ด๋ ค๊ณ  ์—‘์…€์„ ์‹ค์ œ API์™€ ๋˜‘๊ฐ™์€ ๋ชจ์–‘์œผ๋กœ ๋‚ด๋ณด๋‚ด๋Š” ๋ฐ๋ชจ ์„œ๋ฒ„๋ฅผ ๋‘๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

๊ตฌ์กฐ๋Š” ์ด๋ ‡์Šต๋‹ˆ๋‹ค. ํ˜ธ์ถœํ•˜๋Š” ์ชฝ(์ˆ˜์ง‘ ๋ชจ๋“ˆ, Postman)์€ ๋ฐ๋ชจ API๋ฅผ ์ง„์งœ DPM API์ฒ˜๋Ÿผ ํ˜ธ์ถœํ•˜๊ณ , ๋ฐ๋ชจ API๋Š” ๋’ค์—์„œ ์—‘์…€์„ ์ฝ์–ด ๊ฐ™์€ ํ˜•ํƒœ์˜ JSON์œผ๋กœ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค.

Postman / collector
        โ”‚  POST /data/metrics
        โ–ผ
   demo_api.py  โ”€โ”€โ–ถ  ์—‘์…€(data/{db}/*.xlsx) ์ฝ๊ธฐ
        โ”‚  ์‹ค DPM๊ณผ ๋™์ผํ•œ JSON
        โ–ผ
   { data: [ { metrics: [ { values: [[ts, val], ...] } ] } ] }

 

2. ๋งž์ถฐ์•ผ ํ•  ์š”์ฒญ·์‘๋‹ต ํ˜•ํƒœ

๋ฐ๋ชจ์˜ ์ „์ œ๋Š” "์‹ค์ œ DPM API์™€ ๋˜‘๊ฐ™์ด"์ž…๋‹ˆ๋‹ค. ๋ฐ›์€ API ์ƒ˜ํ”Œ์„ ๋ถ„์„ํ•ด ํ˜•ํƒœ๋ฅผ ๊ทธ๋Œ€๋กœ ๋”ฐ๋ž์Šต๋‹ˆ๋‹ค.

์š”์ฒญ (POST ๋ณธ๋ฌธ, JSON ๋ฐฐ์—ด):

[{
  "dataId": "db_oracle_cpu_usage",
  "targetIds": ["์ธ์Šคํ„ด์Šค ์‹๋ณ„์ž"],
  "fromTime": "2026-06-06 00:00:00",
  "toTime":   "2026-06-06 23:59:00",
  "summaryType": "avg"
}]

์‘๋‹ต (JSON):

{
  "status": "success",
  "data": [{
    "dataDefinition": { "dataId": "db_oracle_cpu_usage", "displayName": "(OS) Cpu Usage", "category": "oracle" },
    "metrics": [{ "targetId": "...", "values": [
      ["2026-06-06T00:00:00", 12.51],
      ["2026-06-06T00:01:00", 12.48]
    ] }]
  }]
}

ํ•ต์‹ฌ์€ data[].metrics[].values๊ฐ€ [[์‹œ๊ฐ, ๊ฐ’], ...] ํ˜•ํƒœ๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—‘์…€์˜ 1๋ถ„ ์‹œ๊ณ„์—ด์„ ์ด ํ˜•ํƒœ๋กœ ๋ฐ”๊ฟ” ์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

3. ๊ธฐ์ˆ  ์„ ํƒ, ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ http.server

๋ฐ๋ชจ๋Š” ๊ฐœ๋ฐœ์šฉ์ด๋ผ ๊ฐ€๋ฒผ์šด ๊ฒŒ ๊ฐ€์žฅ ์ข‹์Šต๋‹ˆ๋‹ค. Flask๋‚˜ FastAPI๋ฅผ ์“ธ ์ˆ˜๋„ ์žˆ์ง€๋งŒ ์˜์กด์„ฑ์ด ๋Š˜์–ด๋‚ฉ๋‹ˆ๋‹ค. ํŒŒ์ด์ฌ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ http.server๋งŒ์œผ๋กœ ์ถฉ๋ถ„ํ•ด์„œ ์™ธ๋ถ€ ํŒจํ‚ค์ง€ ์—†์ด ๋‹จ์ผ ํŒŒ์ผ๋กœ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

์—”๋“œํฌ์ธํŠธ๋Š” ์‹ค์ œ DPM ๊ฒฝ๋กœ๋ฅผ ๊ทธ๋Œ€๋กœ ์”๋‹ˆ๋‹ค. ํ˜„์žฅ์—์„œ ์ฃผ์†Œ(base_url)๋งŒ ๋ฐ”๊พธ๋ฉด ๋˜๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด์„œ์ž…๋‹ˆ๋‹ค.

HOST, PORT = "0.0.0.0", 8081
API_PATH = "/exemone/api/v1/data/metrics"

4. ํ•ต์‹ฌ ์„ค๊ณ„, ์ˆ˜์ง‘ ๋ชจ๋“ˆ์˜ ์ฝ๊ธฐ ๋กœ์ง ์žฌ์‚ฌ์šฉ

์—ฌ๊ธฐ๊ฐ€ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒฐ์ •์ž…๋‹ˆ๋‹ค. ๋ฐ๋ชจ API๊ฐ€ ์—‘์…€์„ ์ž๊ธฐ ๋ฐฉ์‹์œผ๋กœ ๋”ฐ๋กœ ์ฝ์œผ๋ฉด, ๋‚˜์ค‘์— ์ˆ˜์ง‘ ๋ชจ๋“ˆ(collector)๊ณผ ๋ฏธ๋ฌ˜ํ•˜๊ฒŒ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์—‘์…€์„ ์ฝ๊ณ  ์ง€ํ‘œ ์ด๋ฆ„์„ ํŒŒ์ผ์— ๋งคํ•‘ํ•˜๋Š” ๋กœ์ง์„ collector์—์„œ ๊ณต์šฉ ํ•จ์ˆ˜๋กœ ๋นผ๋‚ด, ๋ฐ๋ชจ API์™€ collector๊ฐ€ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์“ฐ๊ฒŒ ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

์ง€ํ‘œ ์ด๋ฆ„((OS) Cpu Usage)๊ณผ ์‹ค์ œ ํŒŒ์ผ๋ช…(db_oracle_os.cpu_usage.xlsx)์ด ๋”ฑ ๋งž์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, ์ด ๋งคํ•‘ ํ•จ์ˆ˜๊ฐ€ ์ž๋™ ์ •๊ทœํ™”์™€ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

# collector.py — ์—‘์…€/๋ฐ๋ชจ API ๊ณต์šฉ ๋งคํ•‘ ํ•จ์ˆ˜
def resolve_source_to_file(db_name, wanted_metrics, data_dir):
    """config ์ง€ํ‘œ๋ช… → ์‹ค์ œ ํŒŒ์ผ๋ช… ๋งคํ•‘๊ณผ ๋ฏธ์ œ๊ณต ๋ชฉ๋ก ๋ฐ˜ํ™˜."""
    dir_path = os.path.join(data_dir, db_name)
    files = [f for f in os.listdir(dir_path) if f.lower().endswith(".xlsx")]
    norm_to_file = {_norm(metric_part(f)): f for f in files}
    explicit = EXPLICIT_FILE_MAP.get(db_name, {})
    exclude  = EXCLUDE_METRICS.get(db_name, set())
    resolved, unmapped = {}, []
    for source in wanted_metrics:
        if source in exclude:   unmapped.append(source); continue
        if source in explicit:  resolved[source] = explicit[source]; continue
        ns = _norm(source)
        # ์ •๊ทœํ™” ์ผ์น˜ → ๋ถ€๋ถ„ ์ผ์น˜ ์ˆœ์œผ๋กœ ํŒŒ์ผ ์ฐพ๊ธฐ
        ...
    return resolved, unmapped

๋ฐ๋ชจ API๋Š” ์„œ๋ฒ„๋ฅผ ์ผค ๋•Œ ์ด ํ•จ์ˆ˜๋กœ dataId ์นดํƒˆ๋กœ๊ทธ๋ฅผ ํ•œ ๋ฒˆ ๋งŒ๋“ค์–ด ๋‘ก๋‹ˆ๋‹ค. dataId(์š”์ฒญ์— ์˜ค๋Š” ์ง€ํ‘œ ์‹๋ณ„์ž)๋กœ ์–ด๋–ค ์—‘์…€ ํŒŒ์ผ์„ ์ฝ์„์ง€, ์‘๋‹ต์— ๋„ฃ์„ ํ‘œ์‹œ ์ด๋ฆ„(displayName)์ด ๋ฌด์—‡์ธ์ง€ ๋ฏธ๋ฆฌ ์ •๋ฆฌํ•ด ๋‘๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

# demo_api.py — ๊ธฐ๋™ ์‹œ dataId → (ํŒŒ์ผ๊ฒฝ๋กœ, ํ‘œ์‹œ์ด๋ฆ„) ์นดํƒˆ๋กœ๊ทธ ๊ตฌ์„ฑ
def build_catalog(config):
    excel_cfg = config["datasource"].get("excel", {"data_dir": "data"})
    catalog = {}
    for db_name, db_cfg in config["databases"].items():
        source = ExcelMetricSource(db_name, db_cfg, excel_cfg)
        for src_name, path in source._resolve_files().items():
            data_id = os.path.splitext(os.path.basename(path))[0]
            catalog[data_id] = {"db": db_name, "displayName": src_name, "path": path}
    return catalog

5. ์š”์ฒญ ํ•œ ๊ฑด์„ ์‘๋‹ต์œผ๋กœ ๋ฐ”๊พธ๊ธฐ

์š”์ฒญ ๋ณธ๋ฌธ์˜ ๊ฐ ํ•ญ๋ชฉ์„ ์‘๋‹ต ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ํ๋ฆ„์€ ๋‹จ์ˆœํ•ฉ๋‹ˆ๋‹ค. dataId๋กœ ์นดํƒˆ๋กœ๊ทธ์—์„œ ์—‘์…€ ๊ฒฝ๋กœ๋ฅผ ์ฐพ๊ณ , ๊ทธ ์—‘์…€์„ ์‹œ๊ณ„์—ด๋กœ ์ฝ์€ ๋’ค, ์š”์ฒญํ•œ ๊ธฐ๊ฐ„๋งŒ ์ž˜๋ผ [[์‹œ๊ฐ, ๊ฐ’], ...]๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

 

def make_entry(item):
    data_id = item.get("dataId")
    info = _CATALOG.get(data_id)
    entry = {"dataDefinition": {"dataId": data_id,
                "displayName": info["displayName"] if info else data_id,
                "category": info["db"] if info else None},
             "status": "success", "metrics": []}
    if not info or not os.path.exists(info["path"]):
        entry["status"] = "error"; entry["reason"] = "dataId not found"
        return entry

    series = _load_series(info["path"])          # ์—‘์…€ → (์‹œ๊ฐ, ๊ฐ’) ์‹œ๊ณ„์—ด
    from_t = pd.to_datetime(item.get("fromTime"))
    to_t   = pd.to_datetime(item.get("toTime"))
    sliced = series.loc[from_t:to_t]             # ์š”์ฒญ ๊ธฐ๊ฐ„๋งŒ ์Šฌ๋ผ์ด์‹ฑ
    values = [[ts.isoformat(), float(v)] for ts, v in sliced.items()]
    entry["metrics"] = [{"targetId": (item.get("targetIds") or [None])[0],
                         "values": values}]
    return entry

์—‘์…€์„ ์ฝ๋Š” _load_series๋Š” collector์˜ ์ฝ๊ธฐ ํ•จ์ˆ˜๋ฅผ ๊ทธ๋Œ€๋กœ ํ˜ธ์ถœํ•˜๊ณ , ๊ฐ™์€ ํŒŒ์ผ์„ ๋ฐ˜๋ณต ์ฝ์ง€ ์•Š๋„๋ก ๊ฐ„๋‹จํ•œ ์บ์‹œ๋ฅผ ๋‘ก๋‹ˆ๋‹ค.

def _load_series(path):
    if path not in _SERIES_CACHE:
        _SERIES_CACHE[path] = ExcelMetricSource._read_series(path)
    return _SERIES_CACHE[path]

๋ฏธ์ œ๊ณต ์ง€ํ‘œ(์˜ˆ: scatter ํƒ€์ž…)๋Š” ์นดํƒˆ๋กœ๊ทธ์— ์—†๊ฑฐ๋‚˜ ์‹œ๊ณ„์—ด์ด ์•„๋‹ˆ๋ฏ€๋กœ status: error๋กœ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ API๊ฐ€ ์ผ๋ถ€ ์ง€ํ‘œ๋ฅผ ์•ˆ ์ฃผ๋Š” ์ƒํ™ฉ๊นŒ์ง€ ํ‰๋‚ด ๋ƒ…๋‹ˆ๋‹ค.

6. HTTP ํ•ธ๋“ค๋Ÿฌ

POST ์š”์ฒญ์„ ๋ฐ›์•„ ๋ณธ๋ฌธ(JSON ๋ฐฐ์—ด)์„ ํŒŒ์‹ฑํ•˜๊ณ , ๊ฐ ํ•ญ๋ชฉ์„ make_entry๋กœ ๋ณ€ํ™˜ํ•ด ๋ฌถ์–ด ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค. ์ธ์ฆ์€ ์‹ค์ œ API ํ‰๋‚ด๋งŒ ๋‚ด๊ณ (ํ—ค๋”๋งŒ ๋ฐ›์Œ) ๋ฐ๋ชจ์—์„œ๋Š” ํ†ต๊ณผ์‹œํ‚ต๋‹ˆ๋‹ค.

class DpmDemoHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        if self.path.rstrip("/") != API_PATH:
            self._send_json(404, {"status": "error", "reason": "unknown path"}); return
        length = int(self.headers.get("Content-Length", 0))
        raw = self.rfile.read(length).decode("utf-8") if length else "[]"
        requests = json.loads(raw)
        if isinstance(requests, dict): requests = [requests]
        data = [make_entry(item) for item in requests]
        self._send_json(200, {"status": "success", "data": data})

์ƒํƒœ ํ™•์ธ์šฉ GET /health๋„ ๋‘์–ด, ์„œ๋ฒ„๊ฐ€ ๋–  ์žˆ๋Š”์ง€์™€ ์„œ๋น™ ์ง€ํ‘œ ์ˆ˜๋ฅผ ๋ฐ”๋กœ ๋ณผ ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ์Šต๋‹ˆ๋‹ค.

7. ์‹คํ–‰๊ณผ ์‹ค์ œ ์‘๋‹ต

์‹คํ–‰์€ ํ•œ ์ค„์ž…๋‹ˆ๋‹ค.

python demo_api.py
# [demo_api] DPM ๋ชจ์˜ ์„œ๋ฒ„ ๊ธฐ๋™: http://0.0.0.0:8081/exemone/api/v1/data/metrics
# [demo_api] ์„œ๋น™ ์ง€ํ‘œ 91๊ฐœ (config ๊ธฐ์ค€). Ctrl+C ์ข…๋ฃŒ.

Oracle CPU ์‚ฌ์šฉ๋ฅ ์„ ํ•˜๋ฃจ์น˜๋กœ ์š”์ฒญํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด 1๋ถ„ ๊ฐ„๊ฒฉ 1,440๊ฐœ ๊ฐ’์ด ์˜ต๋‹ˆ๋‹ค.

์š”์ฒญ body:
[{"dataId":"db_oracle_cpu_usage","targetIds":["t"],
  "fromTime":"2026-06-06 00:00:00","toTime":"2026-06-06 23:59:00","summaryType":"avg"}]

์‘๋‹ต(์ผ๋ถ€):
{ "status":"success", "data":[{
   "dataDefinition":{"dataId":"db_oracle_cpu_usage","displayName":"(OS) Cpu Usage","category":"oracle"},
   "metrics":[{"targetId":"t","values":[
     ["2026-06-06T00:00:00", 12.51],
     ["2026-06-06T00:01:00", 12.48]
   ]}]   // ... ์ด 1440๊ฐœ
}]}

๊ธฐ๊ฐ„์„ 5๋ถ„์œผ๋กœ ์ค„์ด๋ฉด 6๊ฐœ๋งŒ, ๋ฐ์ดํ„ฐ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚œ ๋‚ ์งœ๋ฅผ ๋„ฃ์œผ๋ฉด ๋นˆ ๋ฐฐ์—ด์ด ์˜ต๋‹ˆ๋‹ค. ์š”์ฒญํ•œ ๋Œ€๋กœ ์ •ํ™•ํžˆ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค.

8. ๊ฒ€์ฆ, ์—‘์…€ ๊ฒฝ๋กœ์™€ API ๊ฒฝ๋กœ๊ฐ€ ๊ฐ™์€๊ฐ€

๋ฐ๋ชจ API์˜ ์กด์žฌ ์ด์œ ๋Š” "ํ˜„์žฅ์—์„œ ์ฃผ์†Œ๋งŒ ๋ฐ”๊ฟ”๋„ ๋˜‘๊ฐ™์ด ๋™์ž‘"ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ™์€ ๋‚ ์งœ๋กœ ๋‘ ๊ฒฝ๋กœ์˜ ๊ฒฐ๊ณผ๋ฅผ ๋น„๊ตํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜๋Š” ์—‘์…€์„ ์ง์ ‘ ์ฝ๋Š” ๊ฒฝ๋กœ, ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ๋ฐ๋ชจ API๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ๋กœ์ž…๋‹ˆ๋‹ค(๋‘˜ ๋‹ค collector์˜ ํ‘œ์ค€ ์ถœ๋ ฅ์œผ๋กœ ๋ชจ์Œ).

DB           excel(ํ–‰x์—ด)        api(ํ–‰x์—ด)         ์ปฌ๋Ÿผ์ผ์น˜  ๊ฐ’์ผ์น˜
mysql        (900, 27)          (900, 27)          True     True
oracle       (900, 32)          (900, 32)          True     True
postgresql   (900, 31)          (900, 31)          True     True

3๊ฐœ DB ๋ชจ๋‘ ํ–‰·์—ด·๊ฐ’์ด ์™„์ „ํžˆ ์ผ์น˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰ ๋ฐ์ดํ„ฐ ์ถœ์ฒ˜๋ฅผ ์—‘์…€์—์„œ API๋กœ ๋ฐ”๊ฟ”๋„ ๊ฒฐ๊ณผ๊ฐ€ ๊ฐ™์œผ๋ฏ€๋กœ, ์ด์ƒ ํƒ์ง€·๋ฆฌํฌํŠธ ๊ฐ™์€ ๋’ท๋‹จ ๋ชจ๋“ˆ์€ ์†๋Œˆ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

9. ์ •๋ฆฌ

์—‘์…€ ์‹ค๋ฐ์ดํ„ฐ๋ฅผ ์‹ค์ œ API์™€ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ๋‚ด๋ณด๋‚ด๋Š” ๋ฐ๋ชจ ์„œ๋ฒ„๋ฅผ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋งŒ์œผ๋กœ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ํ•ต์‹ฌ์€ (1) ์‹ค์ œ API์™€ ์š”์ฒญ·์‘๋‹ต ํ˜•ํƒœ๋ฅผ ๋™์ผํ•˜๊ฒŒ ๋งž์ถ˜ ๊ฒƒ, (2) ์ˆ˜์ง‘ ๋ชจ๋“ˆ์˜ ์ฝ๊ธฐ ๋กœ์ง์„ ์žฌ์‚ฌ์šฉํ•ด ๊ฒฐ๊ณผ๊ฐ€ ์–ด๊ธ‹๋‚˜์ง€ ์•Š๊ฒŒ ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ๋ฐ๋ชจ๋Š” ๊ฐœ๋ฐœ์šฉ์ด๋ฉฐ ๋‚ฉํ’ˆ๋ฌผ์—๋Š” ํฌํ•จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ˜„์žฅ์—์„œ๋Š” ์ด ๋ฐ๋ชจ ๋Œ€์‹  ์‹ค์ œ DPM API๋ฅผ ์“ฐ๊ณ , ์„ค์ •์˜ ๋ฐ์ดํ„ฐ ์ถœ์ฒ˜ ์ข…๋ฅ˜์™€ base_url๋งŒ ๋ฐ”๊พธ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ๊ธ€์—์„œ๋Š” ์ด API ์‘๋‹ต์„ ์†Œ๋น„ํ•˜๋Š” ์ˆ˜์ง‘ ๋ชจ๋“ˆ์˜ API ๊ตฌํ˜„๋ถ€๋ฅผ ๋‹ค๋ฃจ๊ฒ ์Šต๋‹ˆ๋‹ค.