요약

  • POP3에서DELE는 잠긴 TRANSACTION 상태 안에서 메시지를 표시할 뿐이며, 메일드롭(maildrop)에서 메시지를 제거하지 않습니다. 세션이 종료를 확정하기 전에는RSET가 모든 표시를 철회할 수 있습니다.
  • TRANSACTION 상태에서 클라이언트가QUIT를 발행해야만 UPDATE로 진입합니다. 연결이 끊어진 경우 메시지를 삭제해서는 안 되지만, UPDATE는 원자적이지 않아 오류가 발생하면 표시된 메시지 중 일부만, 전부, 또는 하나도 제거되지 않을 수 있습니다.

긍정적 응답이 여전히 “아직 아님”을 뜻할 수 있었다

가정해 봅시다. 가정용 컴퓨터가 메일 서버에 전화 접속하여 세 개의 메시지를 내려받고 원본을 삭제해 달라고 요청합니다. 서버는 각 요청마다 긍정적으로 응답합니다. 컴퓨터가 마지막 메시지를 안전하게 디스크에 저장하기도 전에 전화 회선이 끊어집니다.

방금 일어난 일에는 두 가지 그럴듯한 해석이 있습니다. 서버는 각 삭제 요청이 수락된 순간 최종적인 것으로 처리할 수 있습니다. 그러면 사용자는 다시 접속했을 때, 로컬 저장을 막았던 바로 그 장애 속에서 어떤 메시지의 유일한 사본이 사라졌다는 사실을 발견하게 됩니다. 아니면 서버는 클라이언트가 합의된 마무리에 도달하지 않는 한 모든 원본을 보존할 수 있습니다.

POP3는 두 번째를 선택했습니다.DELE명령은 메시지를 지우지 않았습니다. 현재 세션에서 해당 메시지를 삭제됨으로 표시했을 뿐입니다. 사용자 에이전트는 여전히RSET을 보내 표시 전체를 철회할 수 있었습니다. 세션이 작업 상태에 있는 동안 발행된QUIT만이 프로토콜을 UPDATE로 이동시키고 서버가 물리적 제거를 시도하게 만들었습니다.

이는 사소한 명령 순서 규칙처럼 들립니다. 그러나 실제로는 불확실성의 배분이었습니다. 서버는 클라이언트가 다운로드를 요청했다는 사실은 알 수 있었지만, 클라이언트가 그 결과를 지속적으로 저장했는지는 알 수 없었습니다. 정상적인 작별 고함은 대화가 서버가 보류 중인 의도를 실행할 만큼 충분히 잘 끝났다는 클라이언트의 제한적 선언이 되었습니다.

이 아이디어는 POP3가 이름을 갖기 전에 시작되었다

1984년 10월의 첫 Post Office Protocol인RFC 918은 이미 삭제를 검색 시작과 묶는 것을 피했습니다. 클라이언트는RETR로 읽기 전용 트랜잭션을,RDEL로 읽고-삭제하는 트랜잭션을 시작했습니다. 그런 다음 데이터를 받고RCVD를 보냈습니다. 이 확인 이후에만 서버가 삭제를 시도했습니다.RSET는 진행 중인 트랜잭션을 중단하고 메일박스를 올바르게 닫고 잠금을 해제할 것을 요구했습니다.

RFC 937, 1985년 2월의 POP2 개정판은 이 아이디어를 이후 설계에 더 가깝게 이동시켰습니다.ACKD명령은 수신을 확인하고 현재 메시지를 삭제 대상으로 표시했습니다. 사양은 실제 메일박스 변경이 세션 종료 시 또는 다른 메일박스를 선택할 때 메일박스가 해제될 때까지 기다린다고 강조했습니다.

이 초기 프로토콜들은 살아남은 정확한 POP3 기계를 제공하지 않았습니다. 그러나 하나의 지속적인 관심사를 확립했습니다: 바이트를 검색하는 것과 서버 사본을 내어주는 것은 관련된 이벤트이지만 같은 순간이어서는 안 된다는 것. 간헐적인 네트워크에서는 둘 사이의 간격이 운영상 의미를 갖습니다.

POP3는 그 간격을 세 개의 상태로 만들었다

1988년 11월에 발표된RFC 1081은 AUTHORIZATION, TRANSACTION, UPDATE를 통해 POP3를 정의했습니다. 인증 후 서버는 사용자의 메일드롭과 배타적 접근 잠금을 확보합니다. TRANSACTION 안에서 클라이언트는 메시지를 나열, 검색, 표시합니다.QUIT가 오면 세션은 UPDATE로 진입하고, 서버는 표시된 메시지를 제거하고 잠금을 해제하며 연결을 닫습니다.

세 가지 상태는 서로 다른 종류의 권한을 분리했습니다. AUTHORIZATION은 누가 메일드롭에 접근할 수 있는지 결정했습니다. TRANSACTION은 삭제 표시가 쌓이는 안정적이고 배타적인 뷰를 제공했습니다. UPDATE는 되돌릴 수 없는 작업을 수행하고 자원을 해제했습니다. 인증 전에QUIT를 보내면 단지 세션이 끝날 뿐이며, 커밋할 인증된 트랜잭션이 없으므로 UPDATE로 진입하지 않았습니다.

메시지 번호는 작업 뷰의 임시성을 강화했습니다. 번호는 메일드롭이 열릴 때 할당됩니다. 메시지가DELE로 표시되면, 그 트랜잭션의 이후 명령들은 물리적 메시지가 아직 제거되지 않았음에도 더 이상 그 번호를 성공적으로 참조할 수 없습니다. 세션에는 삭제된 것처럼 동작했고, 저장소에는 경계선까지 복구 가능한 상태로 남았습니다.

RSET는 의도가 가시적으로 되돌릴 수 있음을 만들었다

RSET는 프로토콜 밖의 비상 명령이 아니었습니다. 필수 최소 POP3 명령 중 하나였습니다. TRANSACTION에서 모든 삭제 표시를 제거하고 긍정 응답을 반환합니다. 클라이언트는 어떤 개별DELE요청을 뒤집어야 하는지 기억할 필요가 없고, 서버도 사용자의 동기를 재구성할 필요가 없었습니다.

세션은 평범한 이유로 마음을 바꿀 수 있기 때문에 이것이 중요합니다. 사용자는 로컬 폴더가 가득 찼음을 알아차릴 수 있습니다. 클라이언트는 한 메시지의 파싱에 실패할 수 있습니다. “서버에 메일 남기기” 설정은 검색 후 결정을 바꿀 수 있습니다.QUIT이전에는 표시들이 배타적 대화 안의 제안으로 남아 있습니다.

잠금은 이 제안들에 안정적인 맥락을 부여했습니다.RFC 1725는 나중에 그 잠금이, 필요에 따라, UPDATE 전에 메시지가 수정되거나 제거되는 것을 방지하기 위해 존재한다고 명확히 했습니다. 두 번째 클라이언트는 첫 번째 클라이언트가 무엇을 유지할지 결정하는 동안 그 번호 매긴 뷰의 기반을 다시 써서는 안 됩니다.

이것은 풍부한 트랜잭션 시스템이 아니었습니다. UPDATE 이후 메시지별 실행 취소도, 분산 합의도, 충돌한 서버가 저널을 재생할 수 있다는 보장도 없었습니다. POP3의 경제성은 하나의 좁은 되돌릴 수 있는 구간을 잘 정의한 데서 나왔습니다.

끊어진 대화에는 삭제할 권한이 없었다

초기 POP3 개정판들은 상태 전이를 기술했지만 끊어진 연결을 덜 명시적으로 다뤘습니다. RFC 1725의 개요는 변경 사항 중 “끊어진 연결에 대한 동작 명확화”를 나열합니다. 규칙은 직접적입니다: 클라이언트가 발행한QUIT이외의 어떤 이유로든 세션이 끝나면 UPDATE로 진입하지 않고 메시지를 제거해서는 안 됩니다. 비활성 자동 로그아웃조차 삭제 없이 TCP 연결을 닫습니다.

1996년 5월에 STD 53으로 발행된RFC 1939는 이 규칙을 보존했습니다. 그 운영 설명은 인간적인 이유를 제공합니다. 다운로드-후-삭제 동작을 구현하는 서버는 비정상 종료 후 메시지를 제거해서는 안 됩니다. 클라이언트가 성공적으로 수신하거나 저장하지 못했을 수 있기 때문입니다.

구별은 신중합니다. 프로토콜은 정상적인QUIT가 모든 바이트가 안전히 백업되었음을 증명하지 않습니다. 끊어진 연결이 아무것도 도착하지 않았음을 증명하지도 않습니다. 양측 모두에 사용 가능한 보수적 신호를 선택한 것입니다. 완료된 대화는 보류된 행동을 허가하고, 미완료된 대화는 허가를 보류합니다.

이것은 침묵을 안전으로 변환합니다. TCP 소멸은 동의로 해석되지 않습니다. 시간 초과는 작별 고함의 대체가 아닙니다. 마지막 명령이 없으면, 클라이언트가 이미 여러 성공적인DELE명령을 보냈더라도 서버 사본은 그대로 유지됩니다.

UPDATE는 경계였지 원자적 기적이 아니었다

QUIT를 커밋이라 부르고 거기서 멈추고 싶어집니다. RFC 1939는 그 유비가 일정 지점까지만 유용하다고 만듭니다. UPDATE에서 서버는 삭제됨으로 표시된 모든 메시지를 제거하려 시도합니다. 자원 부족이나 다른 오류가 발생하면 그 메시지들 중 일부, 전부, 또는 하나도 제거되지 않을 수 있습니다. 서버는 일부 삭제된 메시지가 제거되지 않았다고 응답한 뒤, 어느 쪽이든 잠금을 해제하고 연결을 닫습니다.

하나의 불변식은 절대적입니다: 표시되지 않은 메시지는 결코 제거해서는 안 됩니다. 그러나 표시된 메시지 집합이 저장소를 한꺼번에 바꾼다는 보장은 없습니다. 마지막 응답을 기다리다 시간 초과된 클라이언트도 닫힌 연결만으로 어떤 제거가 일어났는지 정확히 추론할 수 없습니다.

따라서 프로토콜은 원자적 커밋 의미론이 아니라 커밋게이트를 제공합니다. 게이트 앞에서 삭제 표시는 되돌릴 수 있고 비정상 종료는 모든 메시지를 보존합니다. 게이트가 열린 후에는 되돌릴 수 없는 작업이 부분적으로 성공할 수 있습니다. 이는 단순한 메일드롭 프로토콜과 다양한 저장 백엔드가 신뢰할 수 있게 제공할 수 없는 보장을 수입하는 것보다 정직한 설계입니다.

이 역사는 또한 “삭제 성공”이DELE응답의 위험한 표현인 이유를 설명합니다. 그 순간 서버는 표시를 수락했을 뿐입니다. 제거 결과를 아직 보고하지 않았습니다.

이후의 정책도 UPDATE를 통해 들어왔다

POP3는 주로 메일을 다운로드하고 보통 삭제하도록 설계되었지, 서버에서 광범위한 조작을 제공하도록 설계되지 않았습니다. 시간이 지나면서 사용자와 클라이언트는 점점 메시지를 메일드롭에 남겼습니다. 확장은 상태 경계를 깨지 않으면서 보존 정책을 기술해야 했습니다.

1998년 POP3 확장 메커니즘인RFC 2449는EXPIRE기능을 정의했습니다.EXPIRE NEVER는 서버가 그 정책 아래 메시지를 삭제하지 않는다는 뜻이고,EXPIRE 0은 클라이언트가 메시지를 서버에 남겨둘 수 없다는 뜻입니다. 그럼에도 서버는세션이 UPDATE로 진입할 때성공적으로 검색된 메시지를 암묵적으로 삭제 대상으로 표시된 것으로 처리할 수 있습니다. 정책은 어떤 메시지가 표시되는지를 바꿀 뿐, 비정상 종료의 의미를 바꾸지 않습니다.

이 확장은 작은 상태 기계의 강함을 드러냅니다. 새로운 보존 동작은 기존의 효과 경계에 부착될 수 있었습니다. 모든 검색이 즉시 파괴적이 될 필요는 없었습니다.

작별 고함은 예법이 아니라 보관권을 보호했다

프로토콜의 마무리는 의례적이라고 종종 일축됩니다. POP3의 마무리는 권한을 실었습니다. 클라이언트는 되돌릴 수 있는 요청들이 서버 측 제거 시도가 되는 순간을 통제했습니다. 서버는 각 시도가 성공하는지를 통제했습니다. 전송 계층은 어느 쪽이든 중단할 수 있었지만, UPDATE로 진입하는 데 필요한 빠진 승인을 만들어낼 수는 없었습니다.

설계는 모호성의 비용을 손실이 아닌 복제에 두었습니다. 끊어진 세션 후 클라이언트는 같은 메시지를 다시 검색할 수 있습니다. 중복 메일은 불편하고 로컬 조정이 필요할 수 있습니다. 사라진 유일한 사본은 복구가 더 어렵습니다. POP3는 되돌릴 수 있는 오류를 선호했습니다.

이 우선순위는 전화 접속 회선, 작은 디스크, 짧은 세션, 서버에 지속적으로 접속할 수 없는 클라이언트라는 인터넷의 단절된 기계들의 역사에 속합니다. 그러나 교훈은 향수적이지 않습니다. 신뢰할 수 없는 채널 위에서 파괴적인 의도를 받아들이는 모든 시스템은 “요청이 기록됨”과 “효과가 완료됨”을 구분해야 하며, 사라진 연결이 무엇을 의미하는지 명시해야 합니다.

POP3의 답은 겸손했습니다. 먼저 표시하라. 재설정을 허용하라. 명시적인 경계 통과를 요구하라. 비정상 종료 시 보존하라. 경계 통과 후의 부분 실패를 인정하라. 삭제는 작별 고함에서만 실제가 되었다 — 그리고 그때조차 프로토콜은 실제가 항상 전 아니면 전무라고 가장하기를 거부했다.

출처와 한계

초기 확인 및 지연 변경 계보는RFC 918과RFC 937에서 나옵니다. 최초의 POP3 상태 기계는RFC 1081에 있으며, 표준 트랙 연속성은RFC 1225와RFC 1460에 있습니다. 명시적인 끊어진 연결 규칙은RFC 1725에 나타나며,RFC 1939가 현재의 규범적 동작, 부분 실패 규칙 및 보관권 근거를 제공합니다.RFC 2449는 이후 EXPIRE 상호작용을 제공합니다. 이 RFC들은 현재 배포 점유율, 어떤 구현의 충돌 복구 동작, 또는 원자적이고 정확히 한 번의 삭제를 확립하지 않습니다.