Contents 호환성 문제의 정의와 증상 분류 즉시 조치 체크리스트(빠른 복구) 파일 형식별 특성과 선택 기준 버전 차이로 인한 기능 손실과 대체 전략 조직 환경 차이: 32/64비트, 추가기능, 보안 정책 CSV·텍스트 파일 호환성: 인코딩·구분 기호·서식 날짜·숫자 변형 방…
글 전체 보기- 공유 링크 만들기
- X
- 이메일
- 기타 앱
Contents 호환성 문제의 정의와 증상 분류 즉시 조치 체크리스트(빠른 복구) 파일 형식별 특성과 선택 기준 버전 차이로 인한 기능 손실과 대체 전략 조직 환경 차이: 32/64비트, 추가기능, 보안 정책 CSV·텍스트 파일 호환성: 인코딩·구분 기호·서식 날짜·숫자 변형 방…
글 전체 보기이 글의 목적은 Microsoft Excel에서 여러 스레드 계산(Multi-threaded Calculation) 사용 시 간헐적으로 발생하는 충돌·멈춤·응답없음 문제를 체계적으로 진단하고 재발을 방지하는 실무 절차를 제공하는 것이다.
다중 스레드 계산 충돌은 보통 다음과 같은 형태로 나타난다.
영향 범위를 먼저 구분해야 한다.
| 구분 | 확인 질문 | 의미 |
|---|---|---|
| 파일 한정 | 특정 통합문서에서만 발생하나? | 수식·UDF·모델 구조 문제 가능성이 높다. |
| 프로필 한정 | 다른 OS 사용자·계정에서도 동일하나? | Excel 전역 옵션·애드인·드라이버 영향 가능성이 있다. |
| 환경 의존 | 코어 수·RAM·버전이 다르면 빈도가 변하나? | 멀티스레드 설정·하드웨어 가속·CPU 마이크로코드 영향 가능성이 있다. |
Excel의 다중 스레드 계산 옵션 위치는 버전에 따라 경로가 다르다. 두 경로를 모두 확인한다.
권장 초기값은 다음과 같다.
Win + R → excel /safe 실행 후 재현을 시도하다. 재현되지 않으면 애드인 또는 개인용 매크로가 원인일 가능성이 높다.Ctrl + Alt + Shift + F9로 전체 계산 종속성 그래프를 강제로 재작성하다.| 원인 | 설명 | 주요 징후 | 대응 |
|---|---|---|---|
| 휘발성 함수 남용 | OFFSET, INDIRECT, TODAY, RAND 등은 변경 전파 범위가 넓다. | 사소한 편집에도 대규모 재계산 발생 | INDEX 기반 참조로 치환, 구조화 참조 사용, 동적 배열 활용 |
| UDF 비스레드 안전 | VBA UDF는 기본적으로 단일 스레드이며, 상태 공유 시 교착·경쟁이 생기다. | UDF 포함 범위에서만 충돌 | 상태 제거, 전역 변수 금지, XLL로 마이그레이션, 재진입 안전 설계 |
| RTD/외부 연결 | RTD 서버·쿼리가 계산 타이밍과 충돌하다. | 네트워크 변동 시 급증 | RTD 업데이트 간격 조정, 오프라인 캐시, 계산 이벤트 분리 |
| 원형 참조+반복 계산 | Iterative Calculation이 여러 스레드와 맞물려 수렴이 불안정하다. | 값이 진동하거나 수렴 시간이 길다 | 모델 재구성, 수렴 기준·최대 반복 제한 재설정 |
| 동적 배열 스필 충돌 | 스필 영역과 다른 수식이 경합하다. | #SPILL! 간헐 발생 | 스필 영역 확보, LET/TAKE/CHOOSECOLS로 중간 단계 분리 |
| 애드인 경쟁 | 여러 애드인이 계산 이벤트에 동시에 개입하다. | 안전 모드에서 재현 안 됨 | 문제 애드인 격리·업데이트·대체 |
| 대용량 공동 편집/AutoSave | 클라우드 저장소 동기화와 계산 타이밍 충돌 | 저장 순간 멈춤 | AutoSave 임시 해제 후 저장 주기 수동 관리 |
VBA는 본질적으로 단일 스레드로 실행되며 재입력이 안전하지 않다. 다음 원칙을 따른다.
' 비재진입·부작용 없는 UDF 예시 Option Explicit
' 순수 계산: 입력만으로 결과를 결정
Public Function SafeSumProduct(ByVal rngA As Range, ByVal rngB As Range) As Double
Dim i As Long, n As Long
n = Application.WorksheetFunction.Min(rngA.CountLarge, rngB.CountLarge)
Dim a As Variant, b As Variant
a = rngA.Value2: b = rngB.Value2
Dim acc As Double
For i = 1 To n
acc = acc + CDbl(a(i, 1)) * CDbl(b(i, 1))
Next i
SafeSumProduct = acc
End Function
C/C++ XLL을 사용한다면 다음을 확인하다.
// Pseudo-code: 스레드 로컬 컨텍스트 thread_local Context tls;
extern "C" __declspec(dllexport)
double __stdcall SafeUdf(double* x, int n) {
// 로컬 상태만 사용
double acc = 0.0;
for (int i = 0; i < n; ++i) acc += x[i];
return acc;
}
재현 테스트 자동화를 위해 다음 매크로를 활용하다.
Sub SetCalcThreads(ByVal useAll As Boolean, ByVal threads As Long) With Application .ScreenUpdating = False .Calculation = xlCalculationAutomatic With .MultiThreadedCalculation .Enabled = True If useAll Then .ThreadCount = .ThreadCount ' 시스템 최대 유지 Else .ThreadCount = Application.WorksheetFunction.Max(1, threads) End If End With .ScreenUpdating = True End With End Sub
Sub RebuildDependencyGraph()
' 전체 계산 체인 강제 재작성
Application.CalculateFullRebuild
End Sub
원형 참조가 필요하면 다음 절차를 따른다.
' 간단한 DAMP 적용 예 '=λ*신규값 + (1-λ)*이전값 ' λ=0.7 추천 @ 암시적 교차를 의도적으로 사용해 스칼라화하다.RTD나 외부 쿼리가 자주 업데이트되면 계산 스레드와 경합한다.
측정 가능한 기준이 있어야 개선 효과를 검증할 수 있다.
Sub BenchMarkCalc() Dim t As Double Application.CalculateFullRebuild t = Timer Application.CalculateUntilAsyncQueriesDone Application.CalculateFull Debug.Print "Full Calc(sec) = " & Format(Timer - t, "0.000") End Sub 동일 시나리오에서 스레드 수 1, 2, 4, 최대로 각각 측정하여 최적점을 선택하다.
Application.EnableEvents가 False로 남지 않도록 On Error 블록에서 복구 코드를 넣다.Calculate 호출을 중첩하지 않다.Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range) On Error GoTo ExitHandler Application.EnableEvents = False ' 처리... ExitHandler: Application.EnableEvents = True End Sub | # | 점검 항목 | 기준 | 상태 |
|---|---|---|---|
| 1 | 다중 스레드 사용 | 사용, 스레드 수 최적점 반영 | □ |
| 2 | 휘발성 함수 제거 | OFFSET/INDIRECT 미사용 | □ |
| 3 | UDF 순수성 | 전역상태·부작용 없음 | □ |
| 4 | RTD/외부연결 관리 | 주기 제한·비동기 분리 | □ |
| 5 | 반복 계산 안정화 | 수렴 보장·DAMP 적용 | □ |
| 6 | 스필 충돌 제거 | 스필 영역 확보 | □ |
| 7 | 애드인 검증 | 문제 애드인 격리 | □ |
| 8 | 그래픽 가속 | 안정 모드와 동일 결과 | □ |
| 9 | 전체 재계산 테스트 | F9/FullRebuild 통과 | □ |
| 10 | 벤치마크 기록 | 시간·재현율 기록 | □ |
그렇지 않다. 의존성이 높은 체인, I/O 대기, UDF 비스레드 안전, RTD 혼재 환경에서는 임계 이상에서 오히려 지연이 늘어날 수 있다. 측정 후 최적점을 선택해야 한다.
일반적으로 아니다. VBA 런타임은 단일 스레드로 동작하다. XLL 또는 외부 연산 서버로 포팅해야 멀티스레드 이점이 있다.
가능하다. 다만 수렴 보장이 우선이다. 최대 반복·최대 변경값을 보수적으로 설정하고, 스필·외부 연결·UDF와 분리하여 수렴을 안정화해야 한다.
설계에 따라 다르다. 스필 영역 충돌과 대량 재계산이 겹치면 불안정해질 수 있다. 스필 영역을 확보하고 중간 계산을 LET로 캐시하면 안정화된다.
그래픽 드라이버 문제로 창 그리기와 계산 스케줄링이 간섭할 때 효과가 있다. 재현 테스트에서 차이를 확인한 뒤 정책화한다.