새소식

Welcome to the tech blog of Junior Backend Developer Myoungji Kim!

Development/PHP

PHP 설정에 따른 $_REQUEST의 동작 차이: variables_order, request_order

  • -

📝 배경

어느 날, DB에 이상한 값이 저장되어 있다는 확인 요청을 받았다. 쇼핑몰 관리자 페이지에서 결제 수단을 변경하였는데, 실제 DB에는 결제수단 정보 뿐만 아니라 브라우저 쿠키 값까지 저장되어 있었다. 이로 인해 주문 페이지에 진입할 때, 결제수단 정보를 제대로 파싱하지 못해 오류가 발생했고, 에러 페이지로 이어지고 있는 상황이었다. '최근에 관련 로직 개선이 아예 없었는데, 왜 갑자기?'라는 의문을 품고 로직을 다시 살펴보았다.

이게 무슨 일이야!

🔥 이슈

PHP에는 HTTP 요청으로 전달된 데이터를 처리하기 위한 주요 슈퍼 글로벌 변수로 $_GET, $_POST, $_REQUEST 3가지가 있다.

🔖 $_GET
- HTTP 요청 중 GET 메서드로 전달된 데이터를 가져옴
- URL 쿼리 문자열에 포함된 값에 접근할 때 주로 사용됨

🔖 $_POST
- HTTP 요청 중 POST 메서드로 전달된 데이터를 가져옴
- 주로 폼 데이터를 처리할 때 사용됨

🔖 $_REQUEST
- $_GET, $_POST, $_COOKIE 데이터를 모두 포함

 

실제 서비스 로직에서는 슈퍼 글로벌 변수를 직접 사용하는 대신, 이를 래핑한 메서드를 사용 중이다. 로직을 뜯어보니 결과적으로 결제수단 정보를 저장하는 과정에서 $_REQUEST 로 받은 값을 Call by Reference로 전달하여 직접 접근하여 수정한 뒤, DB에 저장하는 방식으로 구현되어 있었다. 폼 데이터를 저장하는 구간에서 굳이 $_POST 가 아닌 $_REQUEST 를 사용해 전체 데이터를 가져오고 있는 문제도 있었으나..🥺 (왜 이렇게 개발이 되어있을까?) 5년 넘게 유지보수가 되지 않았던 구간이라서 최근에 갑자기 불필요한 값이 저장되고 있다고 이슈업 된 점도 이상했다.

 

실제로 로컬에서 테스트했을 때도, 쇼핑몰 관리자 페이지에서 결제수단 설정을 변경하니 브라우저 쿠키 값을 포함한 데이터까지 그대로 받아와 DB에 저장하여 이슈가 재현되고 있었다.

잠시만,, 그럼 모든 상점이 결제수단 변경하면 지금 주문을 못하고 있는 거야?

 

하필 이 상황을 저녁 8시에 발견해버린 나.. 충격에 빠져있다가 황급히 다른 알파, 베타 스테이지의 테스트 상점들에서도 재현을 해보았다. 근데 다른 스테이지의 테스트 상점들은 같은 로직임에도 불구하고, 결제수단 정보를 변경하더라도 딱 결제수단 정보만 DB에 정상적으로 저장되고 있었다.. 

왜.. 돼.....?

 

혹시 개발 진행 중인 브랜치에 개선된 로직이 있는 것일까 싶어 브랜치 바꿔가며 소스코드도 확인해보고, 서버에 들어가서 git diff 까지 모두 확인해보았으나 소스코드는 확실히 똑같았다. 같은 $_REQUEST 임에도 가져오는 결과가 다른 상황이었다.

 

PHP 설정을 봐야겠다.

 

최근에 데봅스에서 OS 이전 작업을 하면서, 일부 서버에서 관련 PHP 도커 이미지도 같이 변경된 것으로 알고 있었는데 혹시 그 영향일까 싶어 서버별로 php 컨테이너에 들어가 php.ini 정보를 확인 및 비교해보았다. 그 결과, 설정값 차이로 인해 이슈가 있던 서버에서만 $_REQUEST 결과에 브라우저 쿠키 값이 포함되는 상황임을 발견하였다.

 

🚨 이슈가 발생한 서버의 phpinfo

$ php -i | grep "variables_order"
variables_order => EGPCS => EGPCS

$ php -i | grep "request_order"
request_order => no value => no value

 

문제가 없는 서버의 phpinfo

$ php -i | grep "request_order"
request_order => GP => GP

 

 

원인은 request_order 설정값의 차이였다. PHP에서는 request_order 값을 지정하지 않을 경우, 기본 설정인 variables_order 값(EGPCS: Environment, Get, Post, Cookie, Server)이 $_REQUEST에 포함된다.

> 관련 공식 문서 (PHP Manual - request_order)

 

PHP: Description of core php.ini directives - Manual

PHP is a popular general-purpose scripting language that powers everything from your blog to the most popular websites in the world.

www.php.net

 

request_order 가 설정되어 있다면 variables_order 보다 우선순위가 높기 때문에 request_order가 GP(GET, POST)로 설정되어 있던 서버는 문제가 발생하지 않았던 것이었다.

 

💭 마무리

다행히 원인을 잘 파악하여, 도커 이미지 유지보수 담당인 데브옵스 팀에 관련 내용을 공유하고 조치를 요청하여 이슈를 마무리하였다. 처음에는 ‘같은 로직인데 왜 결과가 다르지?’라는 생각에 놀라기도 했지만, 덕분에 request_order 설정값에 대해 더 자세히 알 수 있었다. 🙌

해결했으니 해피해피~

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.