콘텐츠로 이동

P3-2.1 저장된 기록은 왜 곧바로 데이터셋이 아닌가

Section ID: P3-2.1 Version: v2026.07.20

데이터 모델링을 처음 들으면 많은 사람이 데이터베이스 테이블 설계부터 떠올립니다. 실제로 데이터 모델링이라는 말은 저장 구조를 정리하는 맥락에서도 자주 쓰입니다. 이 배경에는 DSS/BI/DW/OLAP처럼 데이터를 모아 의사결정에 연결하던 데이터 기반 시스템 흐름도 함께 놓여 있습니다. 즉 데이터 모델링은 처음부터 AI만의 언어였다기보다, 저장된 데이터를 다시 묶고 비교해 판단에 연결하려는 흐름 속에서 자라난 표현이기도 합니다. 하지만 AI와 데이터 분석에서 필요한 데이터 모델링은 거기서 한 걸음 더 나아갑니다. 여기서는 데이터를 어디에 저장할 것인가보다 저장된 기록을 어떤 질문에 답하는 데이터셋 후보로 다시 볼 것인가가 더 중요합니다.

여기서는 저장된 기록데이터셋 후보를 구분하는 데 집중합니다. 데이터셋(dataset)은 학습이나 평가를 위해 같은 질문에 답하도록 묶어 둔 샘플과 변수의 집합이라고 먼저 잡으면 됩니다. 뒤 절에서는 샘플, 특징, 기준선, 출력 구조를 한 번에 펼쳐 보겠지만, 여기서는 아직 그 용어를 길게 정의하기보다 왜 저장 구조만으로는 그 단계에 바로 들어갈 수 없는지를 먼저 고정합니다.

도입부에 나오는 용어도 같은 무게로 읽지 않는 편이 좋습니다. DSS, BI, DW, OLAP는 데이터 활용 맥락을 보여 주는 배경 약어이고, 이 절의 핵심 개념은 저장 구조, 데이터셋 후보, 샘플 단위, 문제 표현 구조입니다.

구분 여기서 어떻게 읽는가
DSS/BI/DW/OLAP 데이터를 모아 의사결정에 연결해 온 배경 맥락
저장 구조 기록을 빠짐없이 보존하기 위한 표
데이터셋 후보 같은 질문에 답하도록 샘플을 다시 묶은 비교 가능한 표
샘플 단위 무엇을 한 건으로 셀지 정하는 기준

즉 데이터셋은 그냥 행이 많은 표가 아닙니다. 같은 질문에 답하도록 정한 샘플들이 모여 있고, 그 샘플을 설명하는 열이 함께 정리된 표에 더 가깝습니다. 그래서 저장 구조의 한 행이 곧바로 데이터셋의 한 샘플이 되는 것은 아닙니다.

예를 들어 자동으로 실행되는 동작의 원천데이터가 있다고 하겠습니다. 시간 순서대로 쌓인 제어 파라미터와 센서 값은 저장용 테이블에 바로 담을 수 있습니다. 한 행마다 시점, 센서 이름, 측정값, 제어 설정값을 넣으면 됩니다. 이 구조는 기록을 보존하고, 문제가 생겼을 때 세부 흐름을 다시 보는 데 적합합니다.

하지만 이 표를 그대로 보고 이번 동작은 평소보다 길었는가, 후반 하강이 유난히 느렸는가, 최근 20건은 기준선과 비교해 달라졌는가 같은 질문에 바로 답하기는 어렵습니다. 왜냐하면 저장 구조의 한 행은 보통 한 시점의 기록이고, 지금 질문이 요구하는 비교 단위는 동작 1회여러 동작을 묶은 최근 구간이기 때문입니다. 즉 저장된 기록이 있다는 사실만으로 아직 데이터셋이 생긴 것은 아닙니다.

이 차이를 분명히 보기 위해 저장 구조와 문제 표현 구조를 나란히 놓고 보겠습니다.

구분 한 행이 뜻하는 것 주된 목적
저장 구조 한 시점의 기록, 센서 측정, 제어 설정 원천데이터 보존과 추적
문제 표현 구조 동작 1회 요약, 최근 구간 비교, 기준선 집계 비교, 해석, 학습 준비

이 구분을 실제 표에 적용하면, 먼저 아래 세 질문으로 행의 의미와 비교 가능성을 확인할 수 있습니다.

처음 표를 받았을 때 먼저 묻는 질문 이 질문이 필요한 이유
한 행은 한 시점 기록인가, 동작 1회 요약인가 행 의미가 다르면 바로 뒤의 샘플 단위도 달라지기 때문
지금 이 표로 바로 비교가 가능한가 저장 구조는 기록 보존에는 강하지만 비교에는 약할 수 있기 때문
이상해 보이는 값이 나오면 다시 어디로 돌아갈 것인가 문제 표현 구조만으로는 세부 원인을 다 설명하지 못하기 때문

이 세 질문은 지금 손에 있는 기록이 이미 데이터셋인가, 아니면 아직 데이터셋 후보인가를 빠르게 가르는 기준입니다. 첫 질문은 행의 뜻을 묻고, 둘째 질문은 비교 가능성을 묻고, 셋째 질문은 원시 로그를 언제 다시 열어야 하는지 묻습니다. 데이터 모델링은 이 세 질문에 답할 수 있게 저장된 기록을 다시 표현하는 일입니다.

저장 구조에서는 빠짐없이 남기는 것이 중요합니다. 반면 문제 표현 구조에서는 무엇을 남길 것인가무엇을 버릴 것인가를 판단해야 합니다. 예를 들어 동작 1회 전체를 샘플로 보겠다고 결정했다면, 시점별 수백 행을 그대로 두는 대신 총 동작 시간, 초반 평균, 후반 하강률, 추종 오차 같은 요약값을 새 열로 만들 수 있습니다. 이것은 저장 구조를 훼손하는 일이 아니라, 다른 질문에 답하기 위해 새로운 표현을 설계하는 일입니다.

아래 작은 표를 보면 같은 원천데이터도 목적에 따라 어떻게 다르게 읽히는지 바로 드러납니다.

구조 예시 열 한 행이 뜻하는 것
저장 구조 timestamp, sensor_name, value 한 시점 기록
문제 표현 구조 event_id, mid_flow_mean, late_drop_rate 동작 1회 요약

작은 도식으로 보기

저장된 기록이 바로 데이터셋이 되지 않는다는 점은, 아래처럼 기록 보존질문에 맞는 재묶음이 어디서 갈리는지로 읽으면 더 분명해집니다.

flowchart TD
    A[저장된 기록이 시점별로 쌓인다] --> B{지금 한 행은 무엇을 뜻하는가}
    B --> C[한 행은 기록된 한 시점일 뿐이다]
    C --> D[질문에 맞는 샘플 단위로 다시 묶는다]
    D --> E[비교 가능한 파생 열을 만든다]
    E --> F[그때 데이터셋 후보가 된다]

문제 상황: 같은 원천 기록이 저장 구조에서는 시점별 행으로 남고, 데이터셋 후보에서는 동작 1회 요약 표로 다시 묶인다는 점을 확인합니다.

입력(input): event_id별 시점 기록으로 저장된 유량 로그 표와 동작 1회로 인정할 최소 시점 수 min_points_per_event

기대 출력(output): 같은 기록이 stored time-step recordsevent-level dataset candidate라는 두 다른 표 역할로 나뉘고, 기준을 채우지 못한 사건은 비교 후보에서 빠지는 출력

확인할 개념: 저장된 기록이 있다는 사실과 질문에 답할 수 있는 데이터셋 후보가 준비되었다는 사실은 같지 않다. min_points_per_event를 바꾸면 어떤 기록을 동작 1회 샘플로 인정할지도 달라진다.

# 저장된 시점별 기록을 event 단위 데이터셋 후보로 다시 묶는 예제입니다.
import pandas as pd

pd.set_option("display.max_columns", None)
pd.set_option("display.width", 120)

min_points_per_event = 3

storage_table = pd.DataFrame(
    [
        {"event_id": "A", "second": 0, "flow": 0.8},
        {"event_id": "A", "second": 1, "flow": 1.4},
        {"event_id": "A", "second": 2, "flow": 1.2},
        {"event_id": "B", "second": 0, "flow": 0.7},
        {"event_id": "B", "second": 1, "flow": 1.1},
        {"event_id": "B", "second": 2, "flow": 0.6},
        {"event_id": "C", "second": 0, "flow": 0.9},
        {"event_id": "C", "second": 1, "flow": 1.0},
    ]
)

dataset_candidate = (
    storage_table.groupby("event_id")
    .agg(
        point_count=("second", "count"),
        duration_seconds=("second", "max"),
        mean_flow=("flow", "mean"),
        late_drop_rate=("flow", lambda values: values.iloc[-1] - values.iloc[-2]),
    )
    .reset_index()
)
dataset_candidate["usable_as_event_sample"] = (
    dataset_candidate["point_count"] >= min_points_per_event
)
usable_candidate = dataset_candidate[dataset_candidate["usable_as_event_sample"]]

print("1) stored time-step records")
print(storage_table)
print()
print(f"2) event-level dataset candidate when min_points_per_event = {min_points_per_event}")
print(dataset_candidate.round(2))
print()
print("3) usable event-level rows for comparison")
print(usable_candidate.round(2))

예상 출력:

1) stored time-step records
  event_id  second  flow
0        A       0   0.8
1        A       1   1.4
2        A       2   1.2
3        B       0   0.7
4        B       1   1.1
5        B       2   0.6
6        C       0   0.9
7        C       1   1.0

2) event-level dataset candidate when min_points_per_event = 3
  event_id  point_count  duration_seconds  mean_flow  late_drop_rate  usable_as_event_sample
0        A            3                 2       1.13            -0.2                    True
1        B            3                 2       0.80            -0.5                    True
2        C            2                 1       0.95             0.1                   False

3) usable event-level rows for comparison
  event_id  point_count  duration_seconds  mean_flow  late_drop_rate  usable_as_event_sample
0        A            3                 2       1.13            -0.2                    True
1        B            3                 2       0.80            -0.5                    True

출력에서 먼저 봐야 할 것은 같은 기록을 그대로 본 표질문에 맞게 다시 만든 표의 차이입니다. 첫 표에서는 한 행이 한 시점 기록이라서 이번 동작의 평균 유량이나 후반 하강률이 아직 보이지 않습니다. 둘째 표로 다시 묶고 나서야 비로소 동작 1회가 한 행이 되고, 비교에 바로 쓸 수 있는 열이 생깁니다. 여기서 조작할 값은 min_points_per_event입니다. 값을 3으로 두면 C는 저장된 기록이 있어도 비교 가능한 동작 1회 샘플에서 빠집니다. 값을 2로 낮추면 C도 후보가 되지만, 후반 하강률을 같은 의미로 비교해도 되는지는 다시 물어야 합니다. 저장된 기록이 있다는 사실과, 질문에 답할 수 있는 데이터셋 후보가 준비되었다는 사실은 같은 말이 아닙니다.

같은 데이터를 저장 구조 그대로 들고 가면 실제로 어디서 막히는지도 짧게 확인해 볼 수 있습니다.

바로 묻고 싶은 질문 저장 구조를 그대로 쓸 때 생기는 문제
이번 동작 1회는 평소보다 길었는가 한 행이 시점 기록이라 동작 1회 길이가 바로 보이지 않는다
후반 하강이 느린 동작만 고를 수 있는가 후반 구간을 먼저 묶어 요약하지 않으면 비교 열이 없다
최근 20건과 이전 200건을 바로 비교할 수 있는가 저장 구조에는 동작 1회최근 구간을 가리키는 비교 단위가 없다

즉 저장 구조는 무슨 일이 기록되었는가를 잘 보여 주지만, 무엇을 한 건으로 비교할 것인가를 자동으로 정해 주지는 않습니다. 데이터셋 후보를 다시 만든다는 말은 바로 이 빈칸을 채운다는 뜻입니다.

여기서 주의할 점이 있습니다. 문제 표현 구조가 저장 구조를 대체하는 것은 아닙니다. 요약 표를 만들었다고 해서 원시 로그가 필요 없어지는 것이 아닙니다. 오히려 요약 표에서 이상한 변화가 보이면 다시 저장 구조로 돌아가 세부 시점을 확인해야 합니다. 즉 저장 구조는 근거를 보존하고, 문제 표현 구조는 비교를 가능하게 만듭니다. 둘은 경쟁 관계가 아니라 역할이 다른 연결 구조입니다.

이 관계를 더 짧게 정리하면 다음과 같습니다.

질문 저장 구조가 강한가 문제 표현 구조가 강한가
실제로 어떤 값이 기록되었는가 부분적으로만
이번 동작 1회는 어떤 구조였는가 어렵다
최근 구간이 평소와 달라졌는가 어렵다

이 표를 보면 저장 구조와 문제 표현 구조의 차이가 단지 테이블 모양 차이가 아니라 답할 수 있는 질문의 차이라는 점이 드러납니다. 표를 어떻게 저장했는지와, 표로 어떤 질문에 답할 수 있는지는 같은 문제가 아니기 때문입니다. 그래서 Part 3 앞단에서 먼저 해야 할 일은 기록을 보며 모델 이름을 떠올리는 것이 아니라, 이 기록이 어떤 데이터셋 후보로 다시 읽혀야 하는지 묻는 일입니다.

더 넓게 보면 이 절은 원천 기록 보존, 분석 단위 재설정, 파생 표현 생성이 서로 다른 층위의 일이라는 점을 구분해, 기록 구조를 문제 표현 구조로 승격시키는 출발 조건을 정리합니다.

따라서 저장된 기록이 곧바로 데이터셋이 아니라는 말은 형식이 다르다는 뜻보다 질문에 답할 단위와 파생 표현이 아직 정해지지 않았다는 뜻에 가깝습니다.

출처와 참고 자료

  • Google for Developers, Machine Learning Glossaryexample, labeled example, feature. example 단위와 feature 역할을 분리해 설명하므로, 저장된 행과 비교 가능한 샘플 행이 다를 수 있다는 이 절의 핵심을 뒷받침합니다. https://developers.google.com/machine-learning/glossary / 확인일: 2026-07-20
  • Oracle, Introduction to Data Warehousing Concepts. 데이터웨어하우스가 비즈니스 인텔리전스 활동, 질의와 분석, 기록 유지, 데이터 분석을 위해 설계된 구조라고 설명하므로, DSS/BI/DW/OLAP가 저장된 데이터를 의사결정과 분석에 연결해 온 배경 맥락이라는 도입부 설명을 보강합니다. https://docs.oracle.com/en/database/oracle/oracle-database/26/dwhsg/introduction-data-warehouse-concepts.html / 확인일: 2026-07-20
  • W3C, PROV-Overview. provenance, derivation, traceability를 함께 다루므로, 저장 구조는 원시 근거를 남기고 문제 표현 구조는 다른 질문에 맞는 파생 표현을 만든다는 상위 프레임을 보강합니다. https://www.w3.org/TR/prov-overview/ / 확인일: 2026-07-20
  • Hadley Wickham, Tidy Data, Journal of Statistical Software 59(10), 2014. 변수, 관측치, 표 구조의 관계를 정리하므로, 저장 구조의 한 행과 분석용 표의 한 행이 같은 뜻이 아닐 수 있다는 설명의 일반 원리를 제공합니다. https://www.jstatsoft.org/article/view/v059i10 / 확인일: 2026-07-20