Contents 호환성 문제의 정의와 증상 분류 즉시 조치 체크리스트(빠른 복구) 파일 형식별 특성과 선택 기준 버전 차이로 인한 기능 손실과 대체 전략 조직 환경 차이: 32/64비트, 추가기능, 보안 정책 CSV·텍스트 파일 호환성: 인코딩·구분 기호·서식 날짜·숫자 변형 방…
글 전체 보기- 공유 링크 만들기
- X
- 이메일
- 기타 앱
Contents 호환성 문제의 정의와 증상 분류 즉시 조치 체크리스트(빠른 복구) 파일 형식별 특성과 선택 기준 버전 차이로 인한 기능 손실과 대체 전략 조직 환경 차이: 32/64비트, 추가기능, 보안 정책 CSV·텍스트 파일 호환성: 인코딩·구분 기호·서식 날짜·숫자 변형 방…
글 전체 보기이 글의 목적은 엑셀에서 수십만 행 이상의 대량 데이터를 안정적이고 빠르게 처리하기 위한 구조 설계, 도구 선택, 성능 최적화 절차를 체계적으로 제시하여 현장에서 즉시 적용 가능하도록 돕는 것이다.
엑셀에서 대량 데이터를 다룰 때 가장 중요한 것은 “어디서 연산할 것인가”를 먼저 결정하는 것이다. 동일한 결과라도 수식, 파워쿼리, 데이터 모델(파워피벗), 피벗테이블, VBA 등 여러 경로가 존재하며, 데이터 규모와 갱신 빈도에 따라 최적의 경로가 달라진다. 다음 원칙을 우선 적용한다.
파일 형식은 성능과 안정성에 직접적인 영향을 준다. 다음 표를 참고한다.
| 형식 | 특징 | 권장 용도 |
|---|---|---|
| .xlsx | 기본 Office Open XML, 압축 우수하나 재계산 시 느릴 수 있다 | 중소 규모 데이터, 수식 중심 작업 |
| .xlsb | 바이너리 저장, 열기/저장 및 계산 속도 유리 | 대용량 수식 통합문서, 반복 저장 환경 |
| .xlsm | 매크로 포함, 성능은 .xlsx와 유사 | VBA 자동화 포함 문서 |
파워쿼리는 대량 데이터 처리의 핵심 도구이다. 단계별 모범 절차는 다음과 같다.
증분 로드 패턴의 간단한 Power Query M 예시는 다음과 같다.
// 매개변수: P_StartDate, P_EndDate let Source = Sql.Database("SRV01","DWH", [Query=" SELECT OrderDate, CustID, SKU, Qty, Amount FROM FactSales WHERE OrderDate >= @P_StartDate AND OrderDate < @P_EndDate "]), #"Type" = Table.TransformColumnTypes(Source,{ {"OrderDate", type date},{"CustID", type text}, {"SKU", type text},{"Qty", Int64.Type},{"Amount", type number} }), #"RemoveErrors" = Table.RemoveRowsWithErrors(#"Type"), #"KeepCols" = Table.SelectColumns(#"RemoveErrors",{"OrderDate","CustID","SKU","Qty","Amount"}) in #"KeepCols" 데이터 모델은 열 지향 컬럼 저장소이므로 대량 집계에 강하다. 설계 요령은 다음과 같다.
대표적인 DAX 측정값 예시는 다음과 같다.
매출 := SUM ( FactSales[Amount] )
전년동기매출 :=
CALCULATE ( [매출], DATEADD ( 'DimDate'[Date], -1, YEAR ) )
고객당매출 :=
DIVIDE ( [매출], DISTINCTCOUNT ( FactSales[CustID] ) )
시트에서 직접 처리해야 한다면 다음 원칙을 따른다.
예시: 대량 매칭에서 VLOOKUP 대신 XLOOKUP과 동적 배열을 활용한다.
=XLOOKUP([@SKU], 제품표[SKU], 제품표[제품명], "없음", 0) 대량 필터링 출력은 다음처럼 스필한다.
=FILTER(판매표, (판매표[OrderDate]>=G1)*(판매표[OrderDate]<G2)*(판매표[지역]=G3)) | 항목 | 권장 조치 | 기대 효과 |
|---|---|---|
| 휘발성 함수 | NOW/TODAY/OFFSET/INDIRECT 제거, 값 고정 또는 매개변수화 | 불필요한 전체 재계산 방지 |
| 대량 조회 | XLOOKUP 또는 INDEX/MATCH, 정렬+XMATCH 바이너리 검색 | 대량 매칭 속도 향상 |
| 배열 연산 | BYROW/BYCOL로 행·열 단위 집계 | 명확한 계산 체인 구축 |
| 중복 연산 | LET로 중간 결과 캐시 | 반복 평가 감소 |
| 텍스트 처리 | TEXTSPLIT/TEXTAFTER로 전처리 단순화 | 복잡한 MID/SEARCH 중첩 감소 |
예시: LET로 중간 결과를 재사용한다.
=LET(r, 판매표[Qty]*판매표[UnitPrice], 세액, r*0.1, 합계, r+세액, 합계) 피벗테이블은 대량 데이터를 시트에 전개하지 않고도 요약할 수 있다. 설계 요령은 다음과 같다.
대량 작업 시 “수식→계산 옵션→수동”으로 설정하고, 완료 후 F9로 재계산한다. VBA로 일괄 제어할 수도 있다.
Sub BatchMode() Application.ScreenUpdating = False Application.Calculation = xlCalculationManual Application.EnableEvents = False ' 대량 처리 코드 작성 Application.EnableEvents = True Application.Calculation = xlCalculationAutomatic Application.ScreenUpdating = True End Sub 정규화된 대량 테이블 간의 조인은 데이터 모델 또는 파워쿼리에서 수행한다. 시트 수식으로 조인할 경우 카디널리티를 반드시 통제한다.
=LET( 키, 판매표[CustID]&"|"&판매표[SKU], 조인, XLOOKUP(키, 고객제품가격표[CustID]&"|"&고객제품가격표[SKU], 고객제품가격표[가격], NA()), IFERROR(조인, 0) ) 정렬된 키에서의 이진 탐색 매칭은 XMATCH의 match_mode=2를 사용한다.
=INDEX(가격열, XMATCH(찾을키, 정렬된키열, 0, 2)) 대량 파이프라인에는 검증 단계가 필수이다. 파워쿼리 끝단과 피벗 결과의 레코드 수를 비교한다.
=LET(a, ROWS(판매표[SKU]), b, SUM(피벗테이블1[Count of SKU]), a=b) VBA로 처리 시간을 기록해 병목을 식별한다.
Function Tick() As Double Tick = Timer End Function
Sub Measure()
Dim t As Double: t = Tick()
' 처리 블록
Debug.Print "elapsed(sec)=", Format(Tick() - t, "0.000")
End Sub
| 점검 항목 | 체크 방법 | 기준 |
|---|---|---|
| 원본 적재 경로 | 파워쿼리 사용 여부 | 시트 직접 적재 금지 |
| 모델 구조 | 스타 스키마 적용 | 사실-차원 분리 |
| 재계산 전략 | 수동 계산 모드 | 완료 후 F9 |
| 휘발성 함수 | 이름 관리자에서 검색 | 0개 권장 |
| 파일 형식 | 저장 형식 확인 | .xlsb 우선 |
| 조건부 서식 | 규칙 관리자 점검 | 최소 규칙 |
| 병목 | 원인 | 대안 |
|---|---|---|
| 시트 로딩 지연 | 수십만 행을 시트에 전개 | 데이터 모델에 로드 후 피벗 |
| 수식 전체 재계산 | 휘발성 함수 사용 | LET+값 고정, 파워쿼리 전처리 |
| 조회 느림 | VLOOKUP 다중 중첩 | XLOOKUP, INDEX/XMATCH, 정렬 후 이진 탐색 |
| 저장 시간 길어짐 | .xlsx 대형 파일 | .xlsb 전환 |
| 메모리 부족 | 32비트 엑셀 | 64비트 전환, 모델 분리 |
파워쿼리 새로 고침→피벗 새로 고침→보고서 저장까지를 VBA로 일괄 실행한다.
Sub RefreshAllAndSave() On Error GoTo EH Application.ScreenUpdating = False Application.Calculation = xlCalculationManual ThisWorkbook.RefreshAll DoEvents ThisWorkbook.Save EH: Application.Calculation = xlCalculationAutomatic Application.ScreenUpdating = True End Sub 보고서에 간단한 품질 지표를 포함해 이상을 즉시 감지한다.
=LET(t, 판매표[Amount], 합계, SUM(t), 음수건수, SUM(--(t<0)), "합계="&TEXT(합계,"#,##0")&" / 음수="&음수건수) 시트로 내리지 말고 파워쿼리에서 데이터 모델로 로드한 뒤 피벗테이블 또는 큐브함수로 표시한다. 필요 시 기간·지역 등으로 필터 매개변수를 두어 분할 로드한다.
정제·집계는 파워쿼리가 우수하다. 시트 수식은 뷰 층에서 최소한으로 사용한다. 다만 소규모 데이터에서 간단한 계산은 수식이 빠르다.
64비트 엑셀 전환이 최선이다. 당장 전환이 어렵다면 모델 분할, 불필요한 시트·서식 제거, .xlsb 저장, 피벗 캐시 공유로 메모리 사용을 줄인다.
필드 수를 줄이고, 계산열 대신 측정값을 사용한다. 필요 없는 세부 필드를 원본 단계에서 제거하고, 슬라이서는 핵심 차원만 유지한다.
XLOOKUP으로 교체하고, 키 열을 정렬한 뒤 XMATCH의 이진 탐색을 사용한다. LET로 중간 결과를 캐싱한다.