월요일 아침의 전형적인 시나리오
Exchange 관리 센터(EAC)에서 IMAP 마이그레이션 배치가 오류 없이 완료됐어요. 사서함은 동기화됐고, 사용자들은 로그인할 수 있어요. 금요일 저녁, 일을 다 마쳤다는 뿌듯한 마음으로 노트북을 닫습니다.
월요일 아침, 티켓이 밀려들기 시작해요. "이메일이 전부 금요일 날짜로 표시돼요." "받은 편지함 기록이 엉망이에요." "오래된 이메일이 사라진 것 같아요." 사실 이메일은 사라진 게 아니에요. 다 있긴 한데, Outlook이 원래 발송일 대신 마이그레이션 날짜를 표시하는 거죠. 2019년에 받은 이메일이 지난 금요일 날짜로 떠 있어요. 결과적으로 사서함 전체가 최근 메시지만 잔뜩 들어있는 것처럼 보여요.
이건 Exchange Online으로의 IMAP 마이그레이션에서 가장 짜증스러운 문제 중 하나예요. 그리고 Microsoft가 거의 문서화하지 않는 문제이기도 하고요.
EAC 마이그레이션이 날짜를 망가뜨리는 이유
Exchange 관리 센터(EAC)를 사용해서 온프레미스 서버(Dovecot, Courier, Cyrus, UW-IMAP 등)에서 IMAP 마이그레이션을 구성하면, Exchange Online은 IMAP을 통해 소스 서버에 연결하고 메시지를 가져와서 내부 전송 파이프라인을 통해 대상 사서함에 주입해요.
문제는 바로 여기서 발생해요.
Exchange 전송 파이프라인을 통과하는 이메일은 자동으로 타임스탬프가 찍힌 Received: 헤더를 받아요. 수십 년 전부터 SMTP와 IMAP 서버의 표준 동작이에요. 메시지를 처리하는 모든 서버가 시간 서명을 남기는 거죠. 문제는 Outlook, 특히 최근 버전의 Windows용 Outlook이 다른 메타데이터가 모호할 때 가장 최근의 Received: 헤더를 표시 기준으로 사용한다는 거예요.
원본 Date: 헤더(이메일이 실제로 언제 발송됐는지를 나타내는, RFC 2822에서 정의된 헤더)는 메시지 안에 여전히 존재해요. 삭제되지 않았어요. 하지만 Exchange가 주입 과정에서 추가한 새로운 Received: 헤더에 가려지는 거예요.
거기에 더해, IMAP INTERNALDATE(서버가 내부적으로 메시지에 날짜를 부여하고, 대부분의 클라이언트에서 정렬을 제어하는 메타데이터)가 원래 이메일 날짜가 아닌 주입 날짜로 설정돼요. Exchange Online은 EAC를 통한 배치 마이그레이션 시 소스 서버의 INTERNALDATE를 보존할 수 있는 기본 방법이 없어요.
EAC vs. 서드파티 도구: 중요한 차이
BitTitan MigrationWiz나 CloudM Migrate 같은 도구를 쓸 때도 이 문제는 발생해요. 하지만 이런 도구들은 날짜 메타데이터를 어느 정도 보존하려는 구성 옵션을 제공하는 경우가 있어요. 문서화가 불완전하고 고급 설정 깊숙이 숨어 있지만요.
반면 EAC를 통한 네이티브 마이그레이션은 그런 옵션이 전혀 없어요. Microsoft는 배치 마이그레이션 파이프라인에서 INTERNALDATE 보존을 제어하는 파라미터를 제공하지 않아요. 완전한 블랙박스예요. 배치를 설정하고 실행하면, Exchange가 내부적으로 알아서 처리해요. 그리고 그 처리 결과는 항상 같아요. 메시지를 주입된 날짜로 날짜 표시하는 거죠.
(참고로, EAC를 통해 마이그레이션된 이메일의 원시 헤더를 읽어 본 적이 있다면, Exchange가 추가한 Received: 헤더가 얼마나 눈에 띄는지 알 거예요. *.protection.outlook.com이나 *.prod.exchangelabs.com 같은 Microsoft 내부 서버 참조가 포함되고, 타임스탬프는 정확히 마이그레이션 시간대와 일치해요.)
배치를 다시 만들어도 해결되지 않는 이유
이 문제에 직면한 많은 IT 관리자들이 본능적으로 이렇게 생각해요. "마이그레이션된 사서함을 삭제하고 처음부터 배치를 다시 실행하면 이번엔 날짜가 제대로 나오지 않을까?"
이해할 수 있는 반응이에요. 하지만 작동하지 않아요.
문제는 배치 구성에 있는 게 아니에요. 놓친 설정 때문도 아니고요. Exchange 전송 파이프라인의 아키텍처 자체에 있어요. 매번 마이그레이션을 실행할 때마다 동일한 파이프라인이 적용돼요. 배치를 다시 실행하면 똑같은 결과가 나와요. 새로운 마이그레이션 날짜가 찍힌 동일한 Received: 헤더, 동일하게 잘못된 INTERNALDATE. 시간을 낭비하고, 사용자들은 두 번이나 불편을 겪게 돼요. 얻는 건 없고요.
Outlook의 정렬 설정을 "받은 날짜" 대신 "보낸 날짜"로 바꾸려는 관리자들도 있어요. 이건 해결책이 아니에요. 임시방편이에요. 이 설정을 적용할 수 없는 클라이언트들, OWA, Outlook Mobile, 그리고 IMAP이나 EWS로 사서함에 접근하는 모든 서드파티 앱에서는 Date: 헤더와 INTERNALDATE가 여전히 잘못된 채로 남아 있어요.
헤더에서 실제로 무슨 일이 벌어지는가
EAC를 통해 마이그레이션된 이메일에 어떤 내용이 담겨 있는지 간단한 예를 들어볼게요. 원본 헤더는 이렇게 생겼어요:
Date: Thu, 14 Mar 2019 09:23:11 +0100
From: alice@oldcompany.com
Subject: 2019년 1분기 보고서
마이그레이션 후, 메시지 헤더 체인 맨 위에 이런 내용이 추가돼요:
Received: from DB7PR0101MB3304.eurprd01.prod.exchangelabs.com
by DB7PR0101MB3305.eurprd01.prod.exchangelabs.com
with HTTPS; Fri, 7 Jun 2024 22:41:03 +0000
Outlook은 헤더 블록 맨 위에 있는 이 Received: 헤더를 먼저 보고, 메시지의 가장 최근 처리 날짜로 해석해서 수신 날짜로 표시해요. 2019년 원본 Date: 헤더는 여전히 그 아래에 그대로 있어요. 하지만 Outlook은 메시지 목록 표시에 그 헤더를 사용하지 않아요.
정확히 말하자면, 동작은 Outlook 버전에 따라 조금씩 달라요. 2021년 이후 버전들, 특히 2023년 말부터 배포된 새로운 Windows용 Outlook은 이 문제에 특히 취약해요. 원시 Date: 헤더보다 Exchange Graph 메타데이터에 더 많이 의존하기 때문이에요. 즉, Outlook 2016에서는 아무 문제 없어 보이던 마이그레이션도 새 Outlook에서는 문제를 일으킬 수 있어요.
실제로 누가 영향을 받는가
이런 유형의 마이그레이션에서 가장 흔히 사용되는 소스 IMAP 서버는 Dovecot(Linux/cPanel 환경에서 널리 사용)과 Courier예요. 두 서버 모두 IMAP을 통해 INTERNALDATE를 제공하지만, EAC는 이를 보존하지 않아요. 온프레미스 Exchange 서버에서 Exchange Online으로 마이그레이션하는 경우(하이브리드 또는 컷오버 마이그레이션)는 동작이 달라요. Microsoft가 날짜 메타데이터를 더 잘 보존하는 내부 전송 프로토콜(MAPI/EWS)을 사용하기 때문이에요. 문제를 일으키는 건 EAC를 통한 일반 IMAP 마이그레이션이에요.
가장 큰 타격을 받는 사용자는 5년 이상의 긴 이메일 기록과 많은 메시지 양을 가진 사람들이에요. 사서함에 이메일이 300개 있는 사람은 금방 적응할 수 있어요. 하지만 고객과의 소통을 찾기 위해 날짜순으로 정렬된 12,000개의 이메일에 매일 의존하는 영업 이사는 그야말로 업무가 마비되는 거예요.
자체 스크립트가 좋지 않은 이유
기술적인 메커니즘을 이해한 일부 IT 관리자들은 PowerShell이나 Python 스크립트로 헤더를 직접 수정하고 싶어 해요. 원인을 파악하고 나면 기본 개념이 단순해 보일 수 있어요. 하지만 실제 운영 환경에서의 수정은 전혀 다른 문제예요.
먼저, 예외 케이스들이 있어요. S/MIME 서명 이메일과 PGP 암호화 메시지는 서명을 무효화하지 않고 헤더를 수정하는 것을 허용하지 않는 구조를 가지고 있어요. 잘못 형성된 MIME 경계를 가진 multipart/alternative 메시지(오래된 Courier 서버에서 자주 발생)는 구조를 제대로 재구성하지 않고 메시지를 수정하는 스크립트에 의해 손상될 수 있어요. RFC 2047에 따라 인코딩된 비-ASCII 헤더(악센트 문자나 한국어가 포함된 발신자 이름 등)는 고전적인 오류 원인이에요.
그다음, 규모 문제가 있어요. 개발 환경에서 테스트 이메일 50개에는 잘 작동하는 스크립트가 운영 환경에서 Exchange Online API의 속도 제한을 처리하지 못해요. 8,000개 메시지 배치 처리 중 새벽 2시에 발생하는 429 Too Many Requests 오류, 재시도 메커니즘 없이는 밤샘 작업에다가 메시지 중복 또는 손실로 이어질 수 있어요.
그리고 가장 중요한 것은, 수정된 각 이메일이 온전한지 어떻게 확인할 건가요? 첨부 파일이 잘리지 않았는지, 스레드가 깨지지 않았는지, 레이블과 폴더가 보존됐는지? 개별 검증 메커니즘 없이는 그냥 잘 됐기를 바라는 수밖에 없어요.
마이그레이션 후 날짜 수정은 50줄짜리 스크립트처럼 보이지만, 운영 환경에서 안정적으로 작동하려면 수천 줄이 필요한 문제예요.
Redate.io가 다르게 접근하는 방식
Redate.io는 Microsoft 365 API(Azure Active Directory, 테넌트 수준의 위임 권한)를 통해 Exchange Online에 연결하고, 마이그레이션으로 날짜 메타데이터가 손상된 이메일을 식별하기 위해 해당 사서함을 스캔해요. 이 스캔 단계는 무료이며, 문제의 정확한 범위를 파악할 수 있어요. 영향받은 메시지 수, 관련 사서함, 손상된 날짜 범위 등이요.
Redate.io의 독자적인 수정 엔진은 이후 각 이메일을 개별적으로 처리해요. 알려진 마이그레이션 도구 서명(Exchange Online 전송 파이프라인 포함)에 대한 패턴 매칭, RFC 준수 검증, 수정 전후 메시지 구조 무결성 검사를 포함한 다단계 분석 파이프라인을 통해서요. S/MIME 서명 이메일, 복잡한 MIME 구조, 비표준 인코딩, 이 모든 것이 각각의 전용 처리 경로로 처리돼요.
수정된 각 메시지는 개별적으로 검증돼요. 원본은 30일간 보이는 백업 폴더에 보존돼요. 특정 메시지에 문제가 생기면 수정하지 않고, Redate.io가 손상 위험 대신 이상을 보고해요.
요금은 사서함당 단건 결제로, 볼륨 기반으로 책정돼요. 구독이나 반복 요금은 없어요. 한 번 문제를 수정하면 끝이에요.
Exchange Online 마이그레이션의 경우, Redate.io는 Azure AD 애플리케이션 권한을 통한 연결을 지원해요(사서함마다 개별 자격 증명을 만들 필요 없이). 그래서 IT 관리자나 MSP가 대규모 사서함 그룹을 훨씬 쉽게 관리할 수 있어요.
여러 고객이 이런 유형의 마이그레이션을 거쳤다면, Microsoft 365 마이그레이션 후 날짜 수정 완전 가이드도 참고해보세요. 다양한 시나리오를 전반적으로 다루고 있어요.
이메일은 그대로 있어요. 원본 날짜도 마찬가지예요. Redate.io에서 무료 스캔을 시작해보세요. Exchange Online 사서함에서 영향받은 메시지가 정확히 몇 개인지 확인한 후에 어떻게 할지 결정하세요.