🍎 원시 데이터(이하 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 예시>
위 테이블은 두 가지 문제점이 있습니다.
- 다양한 값을 갖는 Raw Data를 value Column에 저장하는 것이 좋은 설계인가?
- Json으로 정의된 `value` column을 사용하지 못하는 것은 아니지만 정보를 생성할 때마다 가공 레벨에서 파싱 프로세스가 필수적으로 들어갑니다.
- 두 번째는 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>
🍎 문제의 원인을 되돌아보니, 겉모습이 같다는 이유만으로 동일한 방식으로 처리한 것이 문제의 핵심이라고 생각했습니다. 이번 정리를 통해 비슷한 형태라도 각각의 고유한 정체성을 고려해야 한다는 점을 다시 한 번 깨닫게 되었습니다.
'TIL' 카테고리의 다른 글
[Kotlin] List가 MutableList를 사용하는 이유 (0) | 2025.03.30 |
---|---|
Nginx Basic (0) | 2025.03.06 |
[Tip]비즈니스 로직은 무엇인가요? (1) | 2024.09.05 |
Redis Container vs Embedded Redis 어떤 것을 선택해야 할까요? (0) | 2023.06.07 |
[Python] Multi Processing과 [Java] Multi Processing 차이 (0) | 2023.04.24 |