Skip to content
isdnetworks
Go back

고쳤는데 화면이 안 바뀌었다

한 줄을 고치고 새로고침했는데 그대로였다. 파일은 고쳐져 있고 서버에도 올라가 있는데 화면은 옛날 코드가 도는 것처럼 보였다.

Table of contents

Open Table of contents

코드가 캐시에 묶여 있었다

운영 서버 설정을 그대로 복사해 개발 서버를 만들었는데 거기 이 값이 있었다.

opcache.enable=1
opcache.validate_timestamps=0

opcache.validate_timestamps 가 0 이면 파일이 바뀌었는지 확인하지 않는다. 한 번 읽어 컴파일해 둔 것을 계속 쓴다.

매뉴얼도 이 지시어를 끄면 opcache_reset() 이나 opcache_invalidate() 를 부르거나 웹 서버를 다시 띄워야 파일시스템 변경이 반영된다고 적어 뒀다. 그 전까지는 옛 코드가 돈다.

운영에서는 그게 맞다

이 설정이 잘못된 것은 아니다. 요청마다 filemtime 을 확인하면 그만큼 디스크를 보는데 파일이 수백 개면 요청 하나당 수백 번이다. 운영에서는 배포하는 순간 말고 파일이 바뀔 일이 없으니 그 확인이 낭비가 된다.

개발에서는 반대다. 파일이 계속 바뀌므로 확인 비용보다 반영이 안 되는 손해가 훨씬 크다. 같은 설정이 환경에 따라 이득이 되기도 손해가 되기도 한다는 것을 여기서 봤다.

환경별로 나눴다

설정 파일을 나눠 넣되 개발에서 캐시를 아예 끄지는 않았다. 켜 둔 채로 확인만 하게 했다.

; 개발
opcache.enable=1
opcache.validate_timestamps=1
opcache.revalidate_freq=0

opcache.enable 을 0 으로 끄면 운영과 동작이 달라져서 캐시가 있을 때만 나오는 문제를 개발에서 못 본다. opcache.revalidate_freq 를 0 으로 둔 것은 고치고 바로 새로고침하는 흐름에서 기본값 2초가 헷갈리기 때문이다. 0 이면 매 요청마다 확인한다.

운영은 확인을 끄는 대신 배포 마지막에 opcache_reset() 을 부르거나 프로세스를 다시 띄우는 단계를 넣었다. 이걸 안 하면 파일은 새것인데 도는 것은 옛것인 상태가 된다. 개발에서 겪은 그것이 운영에서 일어난다.

층이 여럿인 캐시

코드 캐시를 잡고도 어떤 화면은 여전히 옛날 것이었다. 캐시가 한 층이 아니었다.

대상비우는 법
코드 캐시PHP 파일프로세스 재시작
애플리케이션 캐시조회 결과, 설정캐시 파일 삭제
브라우저 캐시CSS·JS·이미지강제 새로고침, 파일명에 버전
프록시 캐시정적 파일별도 무효화

안 바뀐다는 증상은 같은데 손볼 곳이 다르다. 어느 층인지 가르는 순서를 정해 뒀다. 서버에서 cat 으로 파일 내용을 직접 보고 프로세스를 재시작해 본다. 그다음 캐시 디렉터리를 비워 보고 브라우저에서 강제 새로고침을 한다. 위에서부터 내려가면 층이 겹치지 않는다.

정적 파일은 사용자에게 강제 새로고침을 시킬 수 없으니 주소에 버전 값을 붙였다. 값이 바뀌면 브라우저 입장에서 다른 파일이라 새로 받는다. filemtime 을 쓰면 파일마다 자동으로 갈린다.

<link rel="stylesheet" href="/css/style.css?v=<?= filemtime(DOCROOT.'/css/style.css') ?>">

정리


Share this post on:

Previous Post
세션을 DB에 넣었다
Next Post
상대가 실제로 보내는 것을 재서 고정했다