TIL

원시 데이터가 DB에 존재하는 모습

친환경사과 2025. 3. 5. 15:26

🍎 원시 데이터(이하 Raw Data)를 내부 DB에 저장할 때 어떤 모습으로 담겨야 하는지 생각한 부분을 정리합니다.


- 가공되기 전 데이터인 Raw Data는 비즈니스에 사용되기 전까지 한 번 이상의 가공을 거쳐야 하는 데이터입니다.

- Raw Data가 중요한 이유는 가공되지 않기 때문에 중요하다고 생각합니다. 가공된 후 다양한 모습으로 비즈니스 데이터가 될 수 있으며 혹시나 가공 처리 과정에 오류가 있어 오염이 될 경우, 근원 데이터로 오류 추적, 개선을 할 수 있기 때문입니다.

 

❓ 어떻게 Raw Data를 저장해야 할까?

- Raw Data의 모습은 규정할 수 없이 다양한 형태로 존재합니다. 외부 API에서 제공하는 데이터가 Raw Data가 될 수 있고 운영되는 서비스의 사용자 활동 이력도 Raw Data가 존재합니다.

 

🤔 큰 범주로 카테고리화해서 외부에서 제공되는 데이터, 서비스 내부에서 얻을 수 있는 데이터를 나눠 두 개의 Raw Data Table에 데이터를 적재하면 될 수 있겠단 생각을 했습니다.

CREATE TABLE IF NOT EXISTS internal_raw_data (
    idx INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    type VARCHAR(255) NOT NULL, # 내부 서비스에서 데이터가 온 출처
    created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    value JSON NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE IF NOT EXISTS external_raw_data (
    idx INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    type VARCHAR(255) NOT NULL, # 외부 데이터 출처 (예: OpenAPI, Scraping)
    category VARCHAR(255) NOT NULL,
    created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    value JSON NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

<DB에 적재될 Table Schema 예시>

 

위 테이블은 두 가지 문제점이 있습니다.

  1. 다양한 값을 갖는 Raw Data를 value Column에 저장하는 것이 좋은 설계인가?
    • Json으로 정의된 `value` column을 사용하지 못하는 것은 아니지만 정보를 생성할 때마다 가공 레벨에서 파싱 프로세스가 필수적으로 들어갑니다. 
  2. 두 번째는 type에 comment 된 내용에서 볼 수 있듯이 비즈니스에 종속된 데이터가 아닌 Raw Data가 비즈니스 정보를 알고 있다는 것입니다. (알고 있다는 것은 바라보고 있다는 것이고 이는 종속을 나타냅니다.)

- 생각해 보면 Raw Data를 저장할 때, 어디서부터 데이터를 가져와 저장하는지는 관여할 바가 아닙니다. 다시 말해 책임이 없다는 것이죠.

- 또한, Raw Data를 저장한다는 의미만 같을 뿐 하나의 테이블이 갖는 의미가 무척 많습니다 (Raw Data의 Form은 다양하기 때문)

 

❗️ 출처가 어디든 어떤 값을 가지든 Raw Data 개별 테이블로 DB에 적재하는 방식으로 처리

 

📌 Raw Data를 개별 테이블로 관리하면 테이블 개수가 무한히 증가하지 않을까? 🤔

 

- 처음에는 Raw Data를 개별 테이블로 다룰 경우 테이블 개수가 끝없이 늘어날 것이라는 걱정이 들었습니다. 하지만, 실제로는 비즈니스에 필요한 데이터만 선별적으로 저장되므로 테이블이 무분별하게 증가하지 않습니다.

 

· 예를 들어, **“연령별 사용자 소비 금액”**을 비즈니스 데이터로 활용하려고 할 때, Raw Data에 포함된 **“사용자 평균 주차 시간”**과 같은 정보는 사용되지 않습니다. 즉, 비즈니스에 필요한 데이터만 저장되기 때문에 테이블 개수는 제한적으로 증가하게 됩니다.

 

📌 Raw Data에서 선별되어 저장하는 과정과 비즈니스 Raw Data에서 비즈니스 데이터로 가공하는 것은 어떤 차이가 있나요?

 

-Raw Data에서 비즈니스 데이터로 가공하는 것필요한 데이터만 선별하여 DB에 저장하는 것은 접근 방식이 다릅니다.

 

· 비즈니스 데이터로 가공 → Raw Data에서 특정 패턴을 추출하거나 분석하여 새로운 의미를 가진 데이터를 생성하는 과정.

    ex) “사용자별 평균 소비 금액” 계산, “주간 트렌드 분석” 수행

· 필요한 데이터만 저장 → Raw Data에서 비즈니스에 필요한 핵심 정보만 선별하여 DB에 저장하는 과정.

    ex) 사용자의 “구매 기록”은 저장하지만, “세부 접속 로그, 메타 데이터”는 저장하지 않음

 


🍎 정리

- 위에서 정리한 내용을 토대로 외부 API를 통해 가져온 데이터를 아래와 같은 Schema를 갖는 Table에 저장하게 되었습니다.

{
    "response": {
        "header": {
            "resultCode": "00",
            "resultMsg": "정상"
        },
        "body": {
            "items": [
                {
                    "bidNtceNo": "R25BK00553447",
                    "bidNtceOrd": "000",
                    "reNtceYn": "N",
                    "rgstTyNm": "조달청 또는 나라장터 자체 공고건",
                    "ntceKindNm": "등록공고",
                    "intrbidYn": "N",
                    "bidNtceDt": "2025-01-05 13:34:05",
                    ...
                }
            ],
            "numOfRows": 1,
            "pageNo": 1,
            "totalCount": 18558
        }
    }
}

<외부 API를 통해 받아온 Json Type Raw Data>

CREATE TABLE IF NOT EXISTS civil_engineering_bid_raw_data (
    idx INT AUTO_INCREMENT PRIMARY KEY,
    title TEXT NOT NULL COMMENT '입찰 공고 제목',
    id VARCHAR(255) NOT NULL UNIQUE COMMENT '유니크한 공고 ID',
    bid_started_date DATE NOT NULL COMMENT '입찰 시작 날짜',
    bid_ended_date DATE NOT NULL COMMENT '입찰 종료 날짜',
    bid_created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '입찰 공고 생성 날짜',
    institution VARCHAR(255) NOT NULL COMMENT '공고 기관',
    contact_person VARCHAR(255) COMMENT '담당자',
    bid_type VARCHAR(100) NOT NULL COMMENT '입찰 방식',
    bid_description TEXT COMMENT '공고 내용'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='토목 입찰 공고 Raw Data 테이블';

<내부에 저장될 입찰 공고 Raw Data Table Schema>

 

🍎 문제의 원인을 되돌아보니, 겉모습이 같다는 이유만으로 동일한 방식으로 처리한 것이 문제의 핵심이라고 생각했습니다. 이번 정리를 통해 비슷한 형태라도 각각의 고유한 정체성을 고려해야 한다는 점을 다시 한 번 깨닫게 되었습니다.