Dico

PHP 7.2 마이그레이션 후기

  • Devellany

   PHP 7.2 마이그레이션은 지난 12월 초에 배포 되었으며(PHP Group이 어떻게 알았는지 배포 당일 PHP 7.3이 릴리즈 되었다!), 규모에 비하면 우려와 달리 적은 이슈를 가져왔다. 이 글은 마이그레이션에 대한 시행착오를 줄이기 위해 기록한다.

   프로그래머라면 땔 수 없는 두 가지가 존재한다. 바로 리팩토링과 마이그레이션이다. 프로그래밍을 하다보면 리팩토링과 마이그레이션을 해야만 하는 코드가 어느새 내 앞에 당당히 서있다. 마치 '네가 안 하고 배기겠어?' 라고 시위하는 것마냥 갑작스레 들이닥친다. 프로그래머 스스로 리팩토링과 마이그레이션을 피하고자 노력해도 소용 없다. 단지 잠복 기간만 길어질 뿐이다.(노력이 의미없다는 말은 아니다!) 그 중 프로그래밍 언어 버전 업그레이드를 위한 마이그레이션은 지속적인 지원을 받기 위한 프로그래머의 숙명이다.

programmer

   언어 마이그레이션은 상용화된 코드 전반을 갈아엎는 일이다. 당연하다시피 리스크도 크며, 범위도 넓다. 소규모라면 고작 몇 백 개 파일만 살펴보면 되지만, 이번 대상은 10년 넘게 유지된 몇 만 개 파일(과장을 더하면 1GB)을 가진 코드였다. 이걸 일일이 찾아가며 마이그레이션 하기에는 버겁다. 아니, 사실상 불가능하다고 단언할 수 있다. 어떤 이슈가 있는지 전부 파악하고 있어야 하는데, 이슈는 한둘이 아니다. 심지어 버전을 몇 단계 건너 점프하기라도 한다면 그 범위는 더더욱 커진다. 그나마 하위호환성에 신경을 쓰는 PHP일지라도 예외란 없다. 또한 투입 인력과 시간은 제한되어 있기 때문에 이처럼 접근하는 것은 프로그래머라 부를 수 없다. 우리가 개발하는 이유는 복잡한 세상을 조금이라도 편하게 살기 위한 발로라는 것을 잊지 말자.

hurdle

   앞서 이야기하였듯이 수작업으로 처리하기에는 방대하고 시간도 부족하다. 이를 해결하기 위해 각자에게 맞는 마이그레이션 정적분석도구를 찾아야 한다. 개인적으로 추천하는 정적분석도구는 세 가지다.

  • PHP 7 Compatibility Checker
  • PHP 7 Migration Assistant Report
  • PHP CodeSniffer + PHP Compatibility

   대표적으로 예를 들었을 뿐, 사실 무엇을 선택해도 큰 차이는 없다. 주의할 사항이 있다면 코드가 방대할수록 분석을 위한 메모리가 많이 필요하기 때문에 서버가 아닌 로컬에서 돌려야 한다. 성능이 부족하다면 부분적으로 정적분석 도구를 돌리는 것도 방안 중 하나다.

   정적분석 리포트를 파일로 만들어서 살펴보면 몇 가지 케이스가 존재한다. 리포트를 받고 나서 에러 케이스 별로 선별하고 정리하자. 다양한 이슈를 순서 없이 처리하는 것보다 효율도 좋으며, 해당 케이스를 처리한다면 더이상 그 해결법을 기억할 필요가 없다.(commit message도 깔끔하다!) 여러 명이 투입된다면 분업을 위한 준비라고 여기자. 컴퓨터 뿐만 아니라 우리도 메모리 제한치가 존재하니까 효율적으로 움직여야 한다. 우린 효율에 살고 효율에 죽는 개발자다.

   코드가 얼마 되지 않는다면 2~3일에 끝나겠지만, 방대하다면 2~3주, 더하면 2~3달이 걸릴 수도 있다. 조급한 마음을 가지지 않고 하나씩 해결해가면, 어느새 정적분석도구로 잡히는 수정사항은 하나도 남지 않는다. 따로 시간을 할애할 수 없다면 다른 프로젝트를 진행하며 틈틈이 시간을 내도 좋다.

start

   정적분석 리포트를 통한 수정이 끝났는가? 자, 이제 버전 업그레이드를 위한 본격적인 시작이다! QA를 통해 동적으로 발생하는 에러를 잡아야 한다. 필자가 겪은 문제는 크게 세 가지로 나뉜다.

   첫 째, 동적으로 변수를 할당 받을 때 타입이 다를 경우 오류가 발생한다. 변수 정적할당은 리포트를 통해 수정할 수 있지만, 동적할당은 잡을 수 없다. 그동안 Typeless Language를 사용하는 개발자가 잘못된 습관을 가지고 있다면 바로잡겠다는 PHP Group의 의지로 보인다.

   둘 째, 연산 시 숫자형 타입이 아닐 경우 오류가 발생한다. 첫 째와 유사한 문제로 Typeless Language가 가진 잘못된 개발 방식이다. 간단하게 형타입 변환만으로 해결할 수 있는 문제이지만, 테스트를 해야 발견할 수 있다. 두 가지 모두 PHP 7.1 이슈다.

   셋 째, 서버환경에 따라 접근자가 없는 static function을 읽지 못 한다. 해당 오류는 autoload 실패로 인하여 발생한다. PHP 7.2가 가진 문제인지, 이번에 Composer를 본격적으로 도입한 영향인지는 파악하지 못 하였다. 하지만 버전 업그레이드와 Composer 사용은 예정된 수순이므로 이곳에 기록한다. 이 오류는 정적분석도구가 잡아주지 않으며, PhpStorm이 가진 전체 파일 정규직 검색을 통하여 해결하였다.

^((?!public)\s)*static function

   번외로 마이그레이션 시 오랜 시간 고민한 부분은 바로 Mcrypt다. PHP 7.2에서 제거 되었으며, 보안 문제가 있는 Mcrypt를 Openssl로 변경하라는 권고안이다. Mcrypt가 가진 몇몇 알고리즘은 Openssl로 복호화가 가능하나, 일부에 국한되어 있다. 복호화가 되지 않는 알고리즘을 사용하고 있었다면 선택을 강요 받는다.

   deprecated 선언되어 아직 제거 되지 않은 PHP 7.1로 다운그레이드를 할지, 아니면 Mcrypt를 서버에 설치해서 기존 형태를 유지할지, Openssl로 전환하여 발생하는 문제를 정책적으로 해결할지 선택하여야 한다. 정적분석도구가 잡아주지만, 무엇을 선택할지 고민이 많았다. 이 부분은 각자 선택해야만 한다. 어느 하나가 답이라고 할 수 없다.

how to choose

   이 글을 올리는 시점에서는 PHP 5.6에 대한 보안 지원이 끝난 뒤다. 아직까지 PHP 7.1 이상 버전을 쓰고 있지 않다면 진지하게 마이그레이션을 고려해보자. 단순히 PHP Group 보안 지원을 받기 위해서 뿐만 아니라, 마이그레이션 전후 서버 성능을 사람이 직접 체감할 정도로 속도가 향상된다. 궁금하다면 벤치마크를 살펴보기 바란다.