데이터 이력 관리, 느린 변경 차원(SCD)으로 해결하기

시간에 따라 변하는 데이터
Section titled “시간에 따라 변하는 데이터”데이터 분석을 하다 보면 작년 이맘때 우리 VIP 고객은 주로 어떤 지역에 살았을까? 혹은 특정 상품의 카테고리가 변경된 이후 매출은 어떻게 변했을까?와 같은 비즈니스 질문에 답해야 할 때가 있습니다.
고객의 주소나 상품의 카테고리 등의 데이터는 처음에는 고정된 값처럼 보이지만, 시간이 지나면서 천천히 변하는 데이터들이죠.
이런 데이터들을 차원(Dimension) 데이터라고 부르는데, 이 차원 데이터의 변경 이력을 제대로 관리하지 않으면 과거 시점의 정확한 분석은 불가능하게 됩니다.
바로 이러한 문제를 해결하기 위한 데이터 관리 전략이 느린 변경 차원(SCD, Slowly Changing Dimension) 입니다.
SCD는 단순히 최신 정보만 저장하는 것이 아니라, 데이터의 변경 이력을 어떻게 보존하고 활용할 것인지에 대한 다양한 방법을 제시합니다.
이 글에서는 주요 SCD 유형들은 무엇이 있고, 각 유형별 장단점은 무엇인지, 그리고 우리 시스템에는 어떤 유형이 적합할지 판단하는 데 도움이 될 만한 내용들을 담아보았습니다.
SCD (Slowly Changing Dimension)란 무엇이며 왜 중요할까요?
Section titled “SCD (Slowly Changing Dimension)란 무엇이며 왜 중요할까요?”앞서 언급했듯이, SCD는 데이터 웨어하우스(Data Warehouse) 환경에서 시간에 따라 변하는 차원 속성을 어떻게 다룰 것인가에 대한 일련의 기법들을 의미합니다.
여기서 차원 속성이란, 예를 들어 고객 테이블의 주소, 결혼 여부, 직업이나 상품 테이블의 카테고리, 가격 등이 될 수 있습니다.
만약 이런 변경 이력을 관리하지 않고 단순히 새로운 정보로 덮어쓰기만 한다면 어떻게 될까요?
지난 분기 A 지역 고객 대상 프로모션의 효과가 어땠지?라는 질문에 답하기 위해 과거 데이터를 보려 해도, 이미 고객 주소 정보가 현재 기준으로 다 바뀌어 있기 때문에 정확한 분석이 불가능하게 됩니다.
SCD를 통해 얻을 수 있는 가장 큰 가치는 다음과 같습니다.
- 정확한 이력 분석: 과거 특정 시점의 데이터를 마치 스냅샷처럼 정확하게 재현하여 신뢰도 높은 분석 결과를 얻을 수 있습니다. 예를 들어, 특정 직원의 과거 소속 부서나 직급 정보를 바탕으로 과거 특정 시점의 조직도를 그려볼 수도 있죠.
- 더 나은 의사결정 지원: 시간에 따른 데이터 변화 추이를 세밀하게 파악함으로써, 과거의 패턴을 이해하고 미래를 예측하여 더 현명한 비즈니스 의사결정을 내릴 수 있습니다.
- 데이터 무결성 유지: 차원 데이터 변경에 대한 일관된 규칙을 시스템 전체에 적용함으로써 데이터 웨어하우스의 전반적인 데이터 품질과 무결성을 높일 수 있습니다.
결국 SCD를 도입할지 말지를 결정하는 가장 핵심적인 질문은 “과거 특정 시점의 사실을 정확하게 알아야 하는가?” 입니다.
만약 이 질문에 대한 답이 그렇다라면, SCD를 통한 과거 데이터 관리는 선택이 아닌 필수가 됩니다.
주요 SCD 유형 파헤치기: 우리 팀에 맞는 방법은?
Section titled “주요 SCD 유형 파헤치기: 우리 팀에 맞는 방법은?”SCD에는 여러 유형이 있지만, 가장 기본적이면서 널리 알려진 것은 Type 0부터 Type 3까지이며, 이 외에도 특정 상황에 맞춰 변형된 Type 4, 5, 6, 7 등이 존재합니다.
각 유형은 데이터 변경 이력을 얼마나 자세히 보존할 것인지, 시스템 구현은 얼마나 복잡한지, 그리고 저장 공간은 얼마나 효율적으로 사용할 것인지 등에서 서로 다른 특징을 가집니다.
SCD Type 0: 변경 없음 (Retain Original)
Section titled “SCD Type 0: 변경 없음 (Retain Original)”Type 0은 아무것도 하지 않아도 되는 가장 간단한 방식입니다.
이 타입에 어울리는 속성들은 최초 계약일, 생년월일, 입사일 등이 있는데요, 최초에 적재된 값을 그대로 유지하고 어떠한 변경도 반영하지 않기 때문에 “변경 불가능한 차원(Unchanged Dimension)” 이라고도 불립니다.
SCD Type 1: 덮어쓰기 (Overwrite)
Section titled “SCD Type 1: 덮어쓰기 (Overwrite)”Type 1은 기존 값을 새로운 값으로 그냥 덮어쓰는 방식입니다.
이 방식은 과거 데이터가 전혀 보존되지 않고 항상 최신 값만 유지한다는 특징이 있습니다. 또한 차원 테이블의 크기가 증가하지 않기 때문에 저장 공간을 효율적으로 사용할 수 있다는 장점이 있습니다.
보통 사용자의 이메일 주소나 전화번호의 경우 일반적으로 최신 정보가 중요하기 때문에 이 타입이 어울릴 수 있습니다.
이 방식의 단점은 예상하셨겠지만 과거의 데이터를 완전히 잃어버린다는 점입니다. 만약에라도 과거 시점의 데이터 기반 분석이 필요해진다면 Type 1 방식으로는 해결할 수 없습니다.
SCD Type 1 예시: 고객 주소 변경
고객 홍길동의 주소가 서울시 강남구에서 경기도 성남시로 변경되었다고 가정해 봅시다.
변경 전 (Customers 테이블)
| CustomerID | Name | Address | LastUpdated |
|---|---|---|---|
| 101 | 홍길동 | 서울시 강남구 | 2023-01-15 |
SCD Type 1을 적용하면, Customers 테이블은 다음과 같이 업데이트됩니다.
변경 후 (Customers 테이블)
| CustomerID | Name | Address | LastUpdated |
|---|---|---|---|
| 101 | 홍길동 | 경기도 성남시 | 2024-05-24 |
보시다시피 서울시 강남구라는 이전 주소 정보는 완전히 사라지고, 경기도 성남시라는 최신 정보만 남게 됩니다.
LastUpdated 컬럼을 통해 언제 정보가 변경되었는지는 알 수 있지만, 무엇이 변경되었는지에 대한 이력은 알 수 없죠.
SCD Type 2: 새로운 행 추가 (Add New Row)
Section titled “SCD Type 2: 새로운 행 추가 (Add New Row)”Type 2는 데이터 변경 시 기존 데이터를 덮어쓰거나 수정하는 대신, 변경된 내용을 담은 새로운 행(Row)을 테이블에 추가하는 방식입니다.
이 방식은 이전 데이터는 그대로 보존하면서 해당 데이터가 유효한 기간(예: 유효 시작일, 유효 종료일)과 현재 유효한 레코드인지 여부(예: 현재 여부 플래그) 등을 함께 관리하여 전체 변경 이력을 추적합니다.
(각 행을 고유하게 식별하기 위한 별도의 키(대리 키, Surrogate Key)를 사용하는 경우도 많습니다.)
이 방식은 가장 널리 사용되는 방식 중 하나로, 모든 과거 정보를 정확하게 보존하여 시간에 따른 데이터 변화를 아주 상세하게 추적할 수 있다는 강력한 장점이 있습니다.
하지만 차원 데이터의 변경이 잦을 경우, 테이블의 크기가 빠르게 커져 저장 공간을 많이 차지하게 되고 이는 곧 쿼리 성능 저하로 이어질 수 있습니다.
또한, 데이터 변경 이력을 관리하고 새로운 행을 추가하며 기존 행의 유효 기간을 업데이트하는 등의 ETL/ELT(데이터 추출, 변환, 적재) 파이프라인 구현 로직이 다른 유형에 비해 상대적으로 복잡하다는 단점도 있습니다.
SCD Type 2 예시: 직원 부서 이동
김철수 직원이 2024년 6월 1일부로 영업팀에서 마케팅팀으로 부서를 옮겼다고 가정해 봅시다.
변경 전 (Employees 테이블)
| EmpKey | EmployeeID | Name | Department | StartDate | EndDate | IsCurrent |
|---|---|---|---|---|---|---|
| 1 | E1001 | 김철수 | 영업팀 | 2022-03-01 | 9999-12-31 | Y |
SCD Type 2를 적용하면, Employees 테이블은 다음과 같이 변경됩니다.
변경 후 (Employees 테이블)
| EmpKey | EmployeeID | Name | Department | StartDate | EndDate | IsCurrent |
|---|---|---|---|---|---|---|
| 1 | E1001 | 김철수 | 영업팀 | 2022-03-01 | 2024-05-31 | N |
| 2 | E1001 | 김철수 | 마케팅팀 | 2024-06-01 | 9999-12-31 | Y |
기존 영업팀 정보가 담긴 행(EmpKey=1)의 EndDate는 2024-05-31로, IsCurrent는 N으로 업데이트되었습니다.
그리고 마케팅팀으로 변경된 정보는 새로운 행(EmpKey=2)으로 추가되었으며, 이 행의 StartDate는 2024-06-01, EndDate는 9999-12-31, IsCurrent는 Y로 설정되며, 김철수 직원의 부서 이동 이력을 모두 보존할 수 있습니다.
SCD Type 3: 새로운 컬럼 추가 (Add New Attribute)
Section titled “SCD Type 3: 새로운 컬럼 추가 (Add New Attribute)”Type 3는 아주 제한된 변경 이력, 주로 현재 값과 바로 이전 값만을 저장하기 위해 테이블에 새로운 컬럼을 추가하는 방식입니다.
예를 들어, 고객의 현재 주소 컬럼 외에 이전 주소 컬럼을 두거나, 제품의 현재 가격 컬럼과 함께 이전 가격 컬럼을 만들어 이전 값을 기록하는 식입니다.
(언제 변경되었는지 알기 위해 변경 날짜를 기록하는 컬럼(예: PriceChangeDate)을 함께 사용하기도 합니다.)
이 방식은 현재 값과 바로 직전 값을 쉽게 비교하고 분석할 수 있으며, Type 2에 비해 구현이 상대적으로 간단하며 테이블 크기 증가에 대한 부담이 적다는 장점이 있습니다.
따라서 고객의 현재 상태와 이전 상태 정보만으로 특정 지표(예: 이탈률)를 계산하거나, 고객의 현재 등급과 이전 등급을 비교하여 구매 패턴 변화를 분석하는 등, 아주 제한된 과거 정보가 필요한 특정 시나리오에 유용하게 사용될 수 있습니다.
하지만 Type 3는 두 번 이상 변경된 이력은 추적할 수 없다는 명확한 한계를 가집니다.
즉, 이전-이전 값은 알 수 없습니다. 또한, 변경 이력을 추적해야 할 속성이 많거나 여러 단계의 과거 이력까지 알아야 하는 상황이라면 이 방식은 부적합합니다.
SCD Type 3 예시: 제품 가격 변경 (이전 가격 정보 보존)
A제품의 가격이 원래 10,000원이었는데, 2024년 5월 1일부로 12,000원으로 변경되었다고 가정해 봅시다.
변경 전 (Products 테이블)
| ProductID | ProductName | CurrentPrice | PreviousPrice | PriceChangeDate |
|---|---|---|---|---|
| P001 | A제품 | 10000 |
SCD Type 3를 적용하면, Products 테이블은 다음과 같이 업데이트됩니다.
변경 후 (Products 테이블)
| ProductID | ProductName | CurrentPrice | PreviousPrice | PriceChangeDate |
|---|---|---|---|---|
| P001 | A제품 | 12000 | 10000 | 2024-05-01 |
현재 가격(CurrentPrice)은 12,000원으로 업데이트되었고, 이전 가격이었던 10,000원은 PreviousPrice 컬럼에 저장되었습니다.
만약 여기서 가격이 한 번 더 변경되어 15,000원이 된다면, CurrentPrice는 15,000원이 되고 PreviousPrice는 12,000원이 되며, 10,000원이었던 정보는 사라지게 됩니다.
기타 SCD 유형 (고급 기법 및 변형)
Section titled “기타 SCD 유형 (고급 기법 및 변형)”앞서 설명한 기본 유형들 외에도, 특정 요구사항이나 복잡한 시나리오를 해결하기 위해 여러 변형된 SCD 유형들이 존재합니다.
SCD Type 4
Section titled “SCD Type 4”Type 4는 주 차원 테이블은 항상 현재 최신 데이터만 유지하고 (마치 Type 1처럼), 모든 변경 이전의 속성 값들은 별도의 히스토리 테이블이나 감사 테이블등에 시간 순서대로 저장합니다.
이렇게 하면 현재 데이터를 조회할 때는 주 테이블만 사용하기 때문에 성능이 빠르다는 장점이 있으며, 동시에 히스토리 테이블을 통해 전체 변경 내역을 추적할 수 있습니다.
다만, 특정 시점의 데이터를 보려면 주 테이블과 히스토리 테이블을 함께 조회하고 조합해야 하므로 쿼리가 복잡해질 수 있다는 단점이 있습니다.
SCD Type 5
Section titled “SCD Type 5”Type 5는 미니 차원(Mini-Dimension)과 Type 1 아웃리거(Outrigger)를 활용하는 기법입니다.
큰 차원 테이블 내에서 특히 자주 변경되는 속성 그룹(예: 고객 정보 기반의 세그먼트)을 별도의 작은 미니 차원 테이블로 분리하고, 이 미니 차원 테이블의 키를 팩트(Fact) 테이블에 직접 저장합니다.
주 차원 테이블에 있는 상대적으로 덜 변하는 속성들은 Type 1 방식으로 관리될 수 있습니다. 때로는 주 차원 테이블에 미니 차원의 현재 값에 대한 외래 키를 함께 저장하여(이를 아웃리거라고 부릅니다) 현재 값 조회 성능을 높이기도 합니다.
이 방식은 대규모 차원 테이블에서 일부 속성만 자주 변경될 때 Type 2 방식의 단점인 주 차원 테이블의 급격한 크기 증가를 막고 전반적인 성능을 개선할 수 있는 장점이 있습니다.
SCD Type 5 예시: 고객 정보 기반의 세그먼트 변경에 따른 판매 분석
고객 ‘김민지’(CustomerID: C001)의 결혼 상태가 변경된다고 가정해 보겠습니다.
김민지 고객은 26-30세, 중위 소득, 미혼이며 세그먼트 (DemoKey: D10)에 속합니다.
변경 전 (CustomerDemographicsMiniDim 테이블)
| DemoKey | AgeBracket | IncomeLevel | MaritalStatus | StartDate | EndDate | IsCurrent |
|---|---|---|---|---|---|---|
| D10 | 26-30세 | 중위 소득 | 미혼 | 2023-01-01 | 9999-12-31 | Y |
변경 전 (Customers 테이블)
| CustomerID | CustomerName | CurrentDemoKey |
|---|---|---|
| C001 | 김민지 | D10 |
2024년 6월 1일, 김민지 고객이 결혼하여 기혼 상태로 변경됩니다. 그리고 새로운 세그먼트 (DemoKey: D11)가 생성됩니다.
변경 후 (CustomerDemographicsMiniDim 테이블)
| DemoKey | AgeBracket | IncomeLevel | MaritalStatus | StartDate | EndDate | IsCurrent |
|---|---|---|---|---|---|---|
| D10 | 26-30세 | 중위 소득 | 미혼 | 2023-01-01 | 2024-05-31 | N |
| D11 | 26-30세 | 중위 소득 | 기혼 | 2024-06-01 | 9999-12-31 | Y |
변경 후 (Customers 테이블)
| CustomerID | CustomerName | CurrentDemoKey |
|---|---|---|
| C001 | 김민지 | D11 |
판매 데이터 예시
SalesFact 테이블
| SaleID | CustomerID | SaleDate | Amount | DemoKeyAtSale |
|---|---|---|---|---|
| S001 | C001 | 2023-10-15 | 50000 | D10 |
| S002 | C001 | 2024-07-20 | 75000 | D11 |
위와 같이 SalesFact 테이블은 각 판매가 발생했을 당시의 정확한 고객 인구 통계 세그먼트(DemoKeyAtSale)를 참조합니다.
이를 통해 결혼 전(D10)과 결혼 후(D11)의 김민지 고객의 구매 패턴을 정확하게 분석할 수 있게 됩니다.
추가로Customers 테이블의 CurrentDemoKey는 현재 시점의 세그먼트를 빠르게 조회하는 데 사용됩니다 (Type 1 아웃리거).
SCD Type 6
Section titled “SCD Type 6”Type6은 Type 1, Type 2, Type 3의 핵심 요소를 조합한 하이브리드 방식입니다.
기본적으로 Type 2처럼 새로운 행을 추가하여 전체 이력을 관리하면서, 동시에 현재 유효한 행에는 Type 1처럼 특정 속성(예: Current_Address)을 직접 업데이트하여 최신 값을 바로 확인할 수 있게 합니다.
또한, Type 3처럼 이전 값을 저장하는 별도 컬럼(예: Previous_Address)도 가질 수 있으며, Type 2의 StartDate, EndDate, CurrentFlag 등도 함께 사용됩니다.
이러한 구조 덕분에 하나의 행만 조회해도 현재 값과 직전 값을 빠르게 비교할 수 있고, 동시에 모든 과거 이력이 보존되어 매우 유연한 분석이 가능하다는 장점이 있습니다.
그러나 이 방식은 테이블 구조가 매우 복잡해지고 데이터 관리가 어려워질 수 있으며, 동일한 정보가 여러 형태로 중복 저장될 수도 있다는 단점이 있습니다.
SCD Type 7
Section titled “SCD Type 7”Type7은 Type 6와 개념적으로 유사하지만 데이터를 물리적으로 분리하여 관리합니다.
즉, 현재 유효한 데이터는 주 차원 테이블에 Type 1 방식으로 저장하여 항상 최신 값을 빠르게 조회할 수 있도록 하고, 모든 과거 이력은 별도의 히스토리 테이블에 대리 키를 사용하여 Type 2 방식으로 저장합니다.
이를 통해 현재 데이터 조회 성능이 매우 빠르다는 장점과 전체 이력을 보존한다는 장점을 모두 가질 수 있습니다.
하지만 현재 데이터와 과거 이력 데이터 간의 동기화 로직이 필요하며, 두 테이블을 함께 사용하여 특정 시점의 데이터를 재구성해야 할 때 쿼리 로직이 복잡해질 수 있다는 단점이 있습니다.
주요 SCD 유형 핵심 비교
Section titled “주요 SCD 유형 핵심 비교”SCD Type 1, Type 2, Type 3은 가장 기본적인 차원 데이터 변경 관리 방식으로, 각각 뚜렷한 특징과 장단점을 가지고 있습니다.
아래 표는 이 세 가지 핵심 유형을 주요 항목별로 비교하여 그 차이점을 명확히 보여줍니다.
SCD Type 1, 2, 3 핵심 비교
| 특징 | SCD Type 1 (덮어쓰기) | SCD Type 2 (새로운 행 추가) | SCD Type 3 (새로운 컬럼 추가) |
|---|---|---|---|
| 이력 보존 수준 | 보존 안 함 (항상 최신 값만 유지) | 모든 변경 이력 완벽 보존 | 제한적 이력 보존 (주로 현재 값과 바로 이전 값만) |
| 테이블 구조 변경 | 변경 없음 (기존 행 업데이트) | 행 수 크게 증가, 이력 관리를 위한 메타데이터 컬럼 추가 (예: 유효기간, 현재여부 플래그 등) | 이전 값을 저장하기 위한 새로운 컬럼 추가 |
| 구현 복잡성 | 매우 낮음 (단순 업데이트) | 높음 (이력 관리 로직 필요) | 중간 (컬럼 추가 및 업데이트 로직 필요) |
| 저장 공간 효율성 | 매우 높음 (테이블 크기 불변) | 낮음 (데이터 변경 빈도에 따라 테이블 볼륨 급증 가능성) | 중간 (컬럼 수 증가) |
| 과거 시점 분석 | 불가능 | 가능 (모든 과거 시점의 정확한 데이터 스냅샷 분석 가능) | 제한적 (주로 현재 값과 이전 값만 비교 가능, 그 이전 이력은 알 수 없음) |
| 주요 사용 사례 | 데이터 오류 수정, 과거 이력이 전혀 중요하지 않은 단순 속성 변경 | 거의 모든 종류의 차원 데이터 이력 관리 요구사항 (가장 일반적이고 강력한 방법) | 현재 값과 이전 값의 빠른 비교가 중요한 특정 분석 시나리오 (예: 고객 등급 변경 전후의 구매 패턴 비교) |
어떤 SCD 유형을 선택해야 할까요?
Section titled “어떤 SCD 유형을 선택해야 할까요?”그래서 우리 팀은 어떤 SCD 유형을 써야 하나요? 이 질문에 대한 정답은 상황에 따라 다릅니다 입니다.
최적의 SCD 유형을 선택하기 위해서는 현재 우리 비즈니스의 요구사항, 데이터 분석의 목적, 데이터 변경이 얼마나 자주 발생하는지, 우리가 감당할 수 있는 저장 용량과 시스템 성능 수준은 어느 정도인지 등을 종합적으로 고려해야하기 때문입니다.
아래는 다음은 각 SCD 유형별로 어떤 상황에서 고려해볼 수 있는지 정리한 가이드라인입니다.
SCD Type 1 (덮어쓰기) 고려 상황
- 과거 데이터의 이력이 비즈니스적으로 전혀 중요하지 않고, 항상 최신의 정확한 값만 필요한 경우 (예: 단순 오타 수정, 최신 연락처 정보 유지)
- 데이터의 사소한 오류를 수정하여 데이터 품질을 개선하는 것이 주 목적인 경우
- 구현을 최대한 단순하게 유지하고 싶고, 추가적인 저장 공간 사용을 최소화하고 싶을 때
SCD Type 2 (새로운 행 추가) 고려 상황
- 대부분의 경우 가장 일반적으로 권장되는 방식
- 현재 데이터뿐만 아니라 과거 데이터의 변경 이력 전체를 추적하고 분석하는 것이 매우 중요할 때 (예: 고객 행동 변화 분석, 상품 판매 추이 분석)
- 특정 시점의 정확한 데이터 스냅샷을 재현해야 하는 법적 규제 요건이나 내부 감사 요구가 있을 때
- 데이터 볼륨 증가와 그에 따른 잠재적인 성능 영향을 감당할 수 있거나, 파티셔닝, 인덱싱 등 다양한 최적화 기법을 통해 이를 관리할 수 있는 환경일 때
SCD Type 3 (새로운 컬럼 추가) 고려 상황
- 전체 변경 이력까지는 필요 없고, 최근 변경 이력 또는 제한된 과거 정보(주로 바로 이전 값)만 빠르게 비교하고 싶을 때
- 현재 값과 이전 값을 직접 비교해야 하는 특정 분석(예: 고객 등급 변경 전후의 구매 패턴 비교)이 주 목적일 때
- 저장 용량 절감과 처리 속도 향상이 중요하지만, Type 1처럼 이력을 완전히 버릴 수는 없을 때 (Type 2의 복잡성이나 비용이 부담스러울 때의 대안)
기타 고급 유형 (Type 4, 5, 6, 7 등) 고려 상황
- 기본 유형(Type 1, 2, 3)만으로는 해결하기 어려운 복잡한 비즈니스 시나리오나 특별한 성능 요구사항을 충족해야 할 때
- 예를 들어, 특정 속성 그룹만 매우 자주 변경되는 대규모 차원 테이블의 경우 Type 5 (미니 차원) 방식이 효과적일 수 있습니다.
- 매우 복잡한 이력 추적 요구사항과 동시에 현재 데이터에 대한 빠른 조회 성능 최적화 사이에서 균형을 찾아야 할 때 Type 6, Type 7과 같은 하이브리드 방식을 고려해볼 수 있습니다.
지금까지 느린 변경 차원(SCD)의 다양한 유형과 각 유형이 어떤 상황에 적합한지에 대해 자세히 살펴보았습니다.
결국 성공적인 데이터 웨어하우스를 구축하고 데이터로부터 진정한 가치를 이끌어내기 위해서는 비즈니스 목표와 현재 데이터의 특성, 활용 가능한 기술 스택 및 예산 등을 면밀히 검토하여 가장 적절한 SCD 유형을 신중하게 선택하는 것이 중요합니다.
이 글을 통해 데이터 이력 관리의 기본적인 개념과 다양한 유형을 이해하고 적절한 선택을 하는데에 도움이 되었기를 바랍니다.