“지금 무슨 작업을 하고 있나”라는 질문에 지난 작업의 실적이 길게 돌아오면, 질문은 그대로 남는다. 도구를 쓰는 AI 에이전트가 앞서 무엇을 끝냈는지와 현재 무엇을 실행 중인지는 다른 정보다. 지금 실행 중인 작업이 없다면 없다고 먼저 답해야 한다. 그 대답이 짧다는 이유로 과거 성과를 보태면 현재 상태를 다시 찾아 읽어야 한다.
작업 이력은 현재 상태를 확인할 단서로 쓸 수 있다. 파일 변환을 시작했다는 기록이 있다면 그 실행이 아직 살아 있는지 확인하면 된다. 하지만 시작 기록만 보고 계속 변환 중이라고 답해서는 안 된다. 그사이에 끝났거나 실패했거나 멈췄을 수 있기 때문이다. 현재 실행을 확인하지 못했다면 모른다고 남겨야 한다. 실행이 없음을 확인한 것과 아직 확인하지 않은 것을 같은 답으로 묶어서도 안 된다.
미완료 목록도 실행 목록과는 다르다. 할 일이 남아 있다는 사실만으로 AI가 그 일을 처리하고 있는 것은 아니다. 반대로 실행 프로그램이 끝났어도 작업 전체는 외부 응답을 기다릴 수 있다. 파일 변환은 끝났고 사용자가 결과를 볼 차례인 상황이라면, 변환 완료와 확인 대기를 나눠 적으면 된다. 그러면 지금 자동으로 처리되는 부분과 다음 행동이 필요한 부분이 구별된다.
실행 중인 작업이 없다는 말이 맡은 일이 끝났다는 뜻도 아니다. 결과 검토가 남았거나 다음 단계를 아직 시작하지 않았을 수 있다. 이때는 실행 중인 작업은 없고 무엇이 남았는지 함께 답해야 한다. 남은 일이 있다는 이유로 진행 중이라고 쓰면 멈춘 상태를 가리고, 실행이 없다는 이유로 완료라고 쓰면 남은 일을 지운다.
반대로 이력 자체가 필요한 질문도 있다. 왜 멈췄는지, 앞선 답과 무엇이 달라졌는지, 다음 사람이 어디서 이어받아야 하는지를 묻는다면 과거 단계가 필요하다. 그때는 현재 상태를 먼저 밝히고 그 상태를 만든 변경이나 막힌 조건을 이어 주면 된다. 지금 하는 일을 묻는 질문과 경과를 설명해 달라는 질문에 같은 긴 보고서를 내놓을 이유는 없다.
진행 보고를 읽는 사용자는 기다리면 되는지, 자신의 확인이 필요한지부터 알아야 한다. 실행 중이라면 작업과 확인한 상태를 말하고, 실행이 없다면 남은 일이 있는지 구분하면 된다. 확인하지 못한 실행을 과거 기록으로 추정해 채우지 않는 것도 중요하다. 끝낸 일이 많다는 사실은 지금 답해야 할 상태를 대신하지 못한다.
개인 메모를 보관하는 AI 기억 서버에 공동 작업자를 초대하려면, 먼저 그 작업자에게 어디까지 읽혀도 되는지 정해야 한다. 프로젝트별로 문서를 나눠놓았다는 설명만으로는 답이 나오지 않는다. 문서를 어떤 이름으로 묶을지와 누가 그 문서를 읽을 수 있을지는 별개의 결정이다.
모든 문서를 함께 읽는 방식 자체가 잘못은 아니다. 같은 자료를 공유하려는 소규모 팀은 단순한 권한 구조를 택할 수 있다. 개인 메모와 공동 문서의 독자가 같다면 분류만 나눠도 된다. 분리가 필요한지는 프로젝트 수보다 독자가 다른지에 달려 있다. 모두가 읽어도 되는 문서만 있는 서버에 세밀한 권한 체계를 덧붙이는 것은 관리할 일만 늘릴 수 있다.
반대로 개인 메모는 나만 읽고 공동 문서는 함께 읽어야 한다고 가정해 보자. 로그인한 사용자라면 서버의 모든 문서를 읽을 수 있는 구조에서 개인 프로젝트와 공동 프로젝트를 만드는 것만으로는 이 요구를 만족하지 못한다. 공동 작업자의 기본 화면에서 개인 프로젝트가 빠지더라도, 문서 주소를 직접 열거나 검색 범위를 바꿔 내용을 받을 수 있다면 개인 메모는 그 계정에 공개된 상태다.
로그인은 계정이 없는 방문자를 구별하는 데 쓰인다. 로그인한 사용자 중 누가 어떤 문서를 읽을 수 있는지는 그다음 문제다. 계정 발급 기능이 있다는 설명과 문서별 읽기 권한이 나뉜다는 설명을 같은 말로 받아들이면, 초대받은 사용자가 읽을 수 있는 범위를 실제보다 좁게 생각하기 쉽다.
AI에게 공동 프로젝트만 참고하라고 지시하는 방법도 구별해서 볼 필요가 있다. 그 지시는 답변에 사용할 자료의 범위를 정한다. AI가 사용하는 계정에 개인 메모를 읽을 권한이 남아 있다면, 지시만으로 그 권한이 사라지지는 않는다. 사용자가 읽지 못해야 할 문서는 AI가 사용자를 대신해 조회할 때도 내용을 돌려주지 않도록 접근을 통제해야 한다.
분리가 됐다는 근거를 얻으려면 개인 메모를 읽지 못해야 하는 공동 작업 계정으로 확인할 수 있다. 목록에서 빠지는지와 별개로 직접 문서 열기, 검색, AI를 통한 조회에서도 내용이 나오지 않는지 보는 것이다. 이는 접근 확인 방법의 제안이며 특정 제품에서 수행한 시험 결과가 아니다. 검색 범위나 답변 지시가 잘 적용되는지만 확인하고 문서 접근까지 막혔다고 결론 내려서는 안 된다.
공동 작업 계정이 개인 메모를 읽을 수 있다면 선택은 구체적이다. 문서 읽기 권한을 나누거나, 함께 읽어도 되는 문서만 그 서버에 둔다. 개인 프로젝트라는 이름을 더 눈에 띄게 붙여도 초대한 계정이 읽을 수 있는 내용은 줄어들지 않는다.
성공한 작업만 남긴 AI 인수인계서는 읽기 편하다. 실패한 시도와 막힌 조건을 걷어내면 설명도 짧아진다. 하지만 다음 AI에게 필요한 정보 중에는 그 지운 내용이 있다. 어디까지 했는지만 알고 어디서 막혔는지 모르면, 이어서 일할 첫 방법으로 앞서 실패한 방법을 다시 고를 수 있다.
인수인계에 실패한 방법의 이름만 적어 두자는 뜻은 아니다. 어떤 목표로 무엇을 시도했고, 어떤 조건에서 어디까지 확인했으며, 무엇을 보고 중단했는지가 붙어 있어야 한다. 원인을 확인하지 못했다면 그 빈칸도 남겨야 한다. 관찰한 실패와 추측한 원인을 한 문장으로 묶으면 다음 AI는 아직 시험하지 않은 설명까지 사실로 물려받는다.
반대로 실패 기록이 영구 금지 목록이 되어도 곤란하다. 필요한 조건이 달라졌다면 같은 방법을 다시 시험할 이유가 생긴다. 앞선 시도와 이번 시도의 조건을 비교할 수 있어야 재시도를 판단할 수 있다. 실패했다는 표시만 남긴 기록은 불필요한 반복을 막는 데도, 정당한 재검토를 허용하는 데도 부족하다.
과거 대화에 있던 요청 역시 현재의 실행 허가와 구별해야 한다. 예전에 검토한 작업이 지금도 승인된 작업인지는 기록의 길이로 결정되지 않는다. 다음 AI는 당시의 설명을 참고할 수 있지만, 그 설명 속 명령을 모두 현재 지시로 받아들여서는 안 된다. 실패한 조건은 이어받되 끝난 요청까지 다시 실행하는 인수인계는 원하지 않는다.
인수인계를 읽는 쪽에는 지금 목표가 무엇인지, 마지막으로 확인된 상태가 어디인지, 이미 막힌 시도는 무엇인지, 다음에 할 한 단계는 무엇인지 물을 수 있다. 요약문을 매끄럽게 되풀이하는 것과 이 질문에 답하는 것은 다른 일이다. 이 질문들은 기록의 분량 대신 다음 행동을 판단하는 데 필요한 내용이 있는지 보려는 기준이다.
내용을 저장했다는 사실과 다음 AI가 그 내용을 읽고 올바르게 이어서 했다는 사실도 다르다. 저장 완료만 확인하면 실제 인수인계가 작동했는지는 아직 모른다. 이 기준이 재작업을 얼마나 줄이는지에 관한 수치도 여기서는 제시하지 않는다. 기록을 어떻게 쓸 것인가에 대한 주장과 효과를 측정한 결과를 섞을 이유가 없다.
확인하고 싶은 것은 다음 AI가 내놓은 첫 동작이다. 앞서 막힌 방법을 다시 제안했다면, 이번에는 어떤 조건이 달라졌는지 설명할 수 있어야 한다. 새 AI가 맡았다는 사실만으로 앞서 막힌 조건이 사라졌다고 볼 수는 없다.
PHP2Shell 소식을 접하고 개인적으로 운영하는 PHP 서비스들의 실행 환경을 정리했다. 보안 패치가 들어간 지원 버전으로 옮기면서 오래된 코드의 호환성을 고치고, 실제 웹 요청이 새 환경으로 연결되는지도 확인했다. 보안 업데이트와 레거시 유지보수가 함께 따라온 작업이었다.
대응 과정에서 손이 많이 간 부분은 오래된 서비스가 새 환경에서도 제 역할을 하는지 확인하는 일이었다. 내부 주소나 서버 구성도는 빼고, 비슷한 서비스를 운영할 때 참고할 만한 확인 과정을 남긴다.
PHP2Shell은 어떤 문제인가
PHP2Shell은 CVE-2026-109618과 CVE-2026-109619를 함께 부르는 이름이다. 인증되지 않은 원격 공격자가 코드를 실행할 수 있는 PHP 핵심부의 취약점 두 건으로, 공식 발표는 2026년 10월 21일에 나왔다. 싱가포르 사이버보안청은 두 건의 심각도를 CVSS v4.0 기준 9.2로 안내했다. 보안기관 공지
하나는 메모리 부족 오류를 처리하다가 내부 상태가 불완전하게 남는 문제이고, 다른 하나는 요청이 끝나 해제된 메모리를 다음 요청에서 다시 참조할 수 있는 문제다. 특정 게시판의 입력값 검증 실수에만 한정된 이야기가 아니다. PHP 자체가 요청을 처리하는 과정에 문제가 있다는 점 때문에 실행 환경부터 확인해야 했다. 메모리 부족 처리 취약점 · 요청 사이에 남는 상태의 취약점
PHP 공식 공지는 PHP-FPM을 포함한 여러 웹 실행 방식을 대상으로 명시한다. mod_php에서 위험이 특히 크다고 해서 다른 방식은 확인하지 않아도 된다는 뜻은 아니다. 이 두 취약점의 수정 버전은 PHP 8.2.35, 8.3.36, 8.4.27, 8.5.12다. 오래된 버전은 배포판이나 장기 지원 업체의 백포트 여부까지 확인해야 하므로, 버전 계열 이름만 보고 안전하다고 판단할 수 없다. PHP 공식 보안 공지
먼저 어느 PHP가 웹 요청을 처리하는지 봤다
한 서버에서 오래 운영한 서비스라고 해서 전부 같은 PHP로 동작하는 것은 아니었다. 기본 설정을 따라가는 사이트도 있고, 호환성 때문에 별도 버전을 지정해 둔 사이트도 있었다. 기본 PHP만 바꾸면 일부 서비스는 예전 실행 환경에 그대로 남을 수 있는 구조였다.
그래서 실제로 활성화된 웹서버 설정, 사이트별 처리 규칙, 실행 중인 PHP 프로세스를 함께 확인했다. 명령행에서 출력되는 버전과 브라우저 요청을 처리하는 버전은 따로 대조했다. 설치 파일이 남아 있는 것과 웹 요청에 사용되는 것도 구분했다.
이번 작업의 완료 기준은 대상 서비스가 패치된 지원 버전으로 연결되고, 구버전으로 웹 요청을 보내는 설정이나 실행 중인 구버전 처리기가 남지 않는 것이었다. 새 PHP가 설치됐다는 사실만으로 전환을 끝내지는 않았다.
원본을 기준으로 호환성을 비교했다
기존 소스와 설정을 먼저 보존하고 별도 시험 환경에서 실행했다. 처음부터 여러 부분을 한꺼번에 고치면 문제가 사라져도 무엇 때문인지 알기 어렵다. 우선 원본의 동작을 확인하고, 새 PHP에서 달라지는 부분을 좁혀 나갔다.
오래된 서비스에서는 제거된 문법이나 함수, 더 엄격해진 함수 호출과 타입 처리처럼 실행 환경 변화에 걸리는 부분이 나왔다. 실제로 필요한 호환성 수정을 적용했고, 기존 코드가 지키던 인증과 데이터 처리 동작도 함께 살폈다.
로그인, 글 편집, 첨부파일처럼 데이터를 쓰는 기능은 복제한 시험 환경에서 확인했다. 시험을 위해 운영 계정의 비밀번호를 바꾸거나 실제 게시물을 덮어쓰는 방식은 쓰지 않았다. 시험 환경의 DB 동작 조건도 운영과 맞춰, 환경 차이로 생긴 오류를 PHP 호환성 문제로 잘못 분류하지 않도록 했다.
이전부터 실패하던 경로와 새 버전에서 생긴 오류도 따로 비교했다. 이번 전환 때문에 생긴 문제는 수정했고, 별도로 손본 기존 오류는 그 사실을 구분해 기록했다. 오래된 서비스의 모든 오류를 업데이트 탓으로 돌리면 원인도 수정 범위도 흐려진다.
응답이 왔다는 것만으로는 부족했다
HTTP 200이 돌아와도 본문이 비어 있을 수 있다. JSON이어야 하는 응답에 다른 내용이 들어가도 상태 코드만 보면 놓친다. 실제로 데이터를 받아 쓰는 기능은 본문을 파싱하고 기대한 구조가 있는지 확인해야 했다.
반대로 인증되지 않은 요청에 접근을 거절하거나 잘못된 입력에 오류를 반환하는 것은 정상 동작일 수 있다. 성공 코드의 개수를 세기보다 원래 그 요청에서 기대한 결과와 맞는지를 봤다.
확인한 것
그 결과로 알 수 있는 범위
새 PHP의 설치와 구문 검사
실행 파일과 소스 문법의 준비 상태
실제 웹 요청의 실행 환경
사이트가 새 PHP로 연결됐는지
응답 본문과 기대한 데이터 구조
검사한 API가 필요한 결과를 돌려주는지
격리 환경의 로그인·편집·업로드
시험한 쓰기 흐름이 새 환경에서도 동작하는지
API 데이터가 나온 결과, 실시간 연결이 성립한 결과, 브라우저에서 기능을 끝까지 사용한 결과도 각각 구분했다. 어느 하나가 통과했다고 전체 기능을 확인한 것으로 묶지는 않았다.
후속 공지는 적용 조건을 다시 대조했다
10월 23일에는 세션 업로드 진행률 기능에 관한 후속 공지가 나왔다. 초기 세션 직렬화 설정과 애플리케이션 실행 중의 설정 변경이 특정하게 조합돼야 하는 문제였다. PHP 세션 업로드 진행률 후속 공지
이 부분은 현재 PHP 설정과 배포된 소스를 다시 읽고, 실행 중인 PHP에 보내는 비공개 진단 요청으로 확인했다. 점검한 운영·시험 환경에서는 공지의 발생 조건에 해당하지 않았다. 따라서 이 후속 문제 때문에 추가 설정을 바꾸거나 서비스를 재시작하지 않았다.
일반 파일 업로드와 PHP가 세션에 업로드 진행률을 기록하는 기능도 나눠서 봤다. 후속 점검에서는 작은 파일을 이용해 PHP의 기본 업로드 처리를 확인했으며, 이것을 운영 게시물에 첨부파일을 쓰는 전체 시험으로 표현하지는 않았다. 임시 진단 파일은 확인 후 제거했다.
이번 대응을 마친 기준
대상 서비스들을 보안 패치가 포함된 지원 PHP 환경으로 전환했고, 기존 구버전이 웹 요청을 계속 처리하지 않는 것까지 확인했다. 호환성 수정과 시험을 거쳐 운영에 반영했으며, 이후의 후속 공지도 현재 구성에 대조했다. 웹서버 보안 업데이트도 별도로 진행했다.
이 기록은 PHP2Shell 대응과 그에 따른 서비스 전환에 관한 것이다. 과거 침해가 없었다는 조사 결과나 모든 애플리케이션의 보안 감사를 뜻하지는 않는다. 운영 서버에 공격 코드를 실행해 확인하는 방식도 사용하지 않았다.
오래된 서비스는 실행 환경을 바꾸는 순간 코드의 호환성 문제가 한꺼번에 드러날 수 있다. 이번에는 원본과 바뀐 환경을 비교하고, 데이터를 쓰는 시험은 분리하고, 실제 웹 요청이 새 환경을 사용하는 데까지 확인했다. 변경 내역과 되돌릴 지점도 별도로 남겨 두었다.