PHP로 된 회사 제품 중 Debug 환경이 없어서 일일이 echo 으로 값을 찍으면서 디버깅을 하였다…
이 큰 코드 베이스를 이렇게 Debug 하는 것은 아니다 싶었다.
JetBrains의 PhpStorm을 사용하고 있는데 뭔가 방법이 없을까? 그동안 Debug 환경이 당연한 곳에서 하다가 만난 새로운 난관이었다.
여러 삽질을 하여 만든 Docker PHP 환경을 공유한다.
PHP 개발 환경 Insight
PHP 개발 환경은 내가 경험한 보편적인 개발 환경과 많이 달랐다. 이것에 대해 먼저 알고 넘어가는 것이 좋을 것 같다.
- 언어 기능이 빈약하거나 모든 기능 사용을 위해서는 유료다.
- 알게 모르게 우리는 자동 완성, 참조 추적, 리팩터링과 같은 언어 기능을 사용하고 있다.
- 언어 개발사에서 제공하거나 IDE를 개발한 곳에서 언어 기능을 제공하거나 오픈 소스로 개발되어 잘 사용하고 있던 것이다.
- 그런데… PHP 언어 기능은 시중에
PHP Intelephense가 나은데, 리팩터링 같은 기능을 쓰려면 유료 라이선스 사용이 필요하다. - PhpStorm도 유료이니… 사실상 실무 제품을 개발하려면 유료다.
- 언어 기능과 Debug 기능 따로 설치
- 언어 기능과 Debug 기능이 분리되어 있을 순 있다. Go의 Debug는 delve로 존재한다.
- 보통은 SDK 설치하면 한번에 딸려오고 손쉽게 설정할 수 있는데 PHP는 따로 설치하고, 소켓 통신을 위해서 설정 건드려야 하는 부분도 있었다.
- 모던 버전이 아니라 그런 것일 수 있겠지만 처음해보는 경험이었다.
Docker PHP 개발 환경 사용 방법
아래와 같이 Sample 코드를 만들어놓았다. 버전마다 차이가 있어서 모던 PHP@8 과 레거시 PHP@5 를 만들어놓았다. 자세한 실행 방법은 README.md 를 읽으면 되며 VSCode, PhpStorm 모두 언어 기능+디버깅을 사용할 수 있다!
- PHP@8: https://github.com/parkgang/concept-container/tree/main/php/dev-env/php-8-xdebug-on-docker
- PHP@5: https://github.com/parkgang/concept-container/tree/main/php/dev-env/php-5-xdebug-on-docker
만약, VSCode PHP Intelephense 를 쓴다면 확장 공식 문서에 작성된 대로 따라하면 된다.
친절하게 설명하자면 아래와 같다.
VSCode의 기본 제공 기능인PHP Language Features를 비활성화settings.json에 아래의 내용을 추가{
"files.associations": {
"*.module": "php"
}
}
만들면서 경험한 TMI
이 환경을 만들면서 별의 별 삽집을 다 해보았다. 정리되지 않은 TMI 내용은 더 있지만 공유될만한 내용을 공유해본다.
PHP 개발 환경 요약
PHP에서Debug를 위해서는XDebug를 설치해야한다.php -m,phpinfo();를 통해서 설치 여부, 설정 값을 확인할 수 있다.XDebug와소켓통신을 통해서Debug정보를 주고 받는다.XDebug 버전 3의 경우9003port,XDebug 버전 2의 경우9000port 를 기본 값으로 사용한다.VSCode,PhpStorm모두Xdebug의 정보를 받을 수 있도록listen중이고Xdebug가로컬 머신으로 정보를 보내면 그에 맞게Breaking Point가 걸리는 것이다.- 이 대전제를 두고
Docker실행 환경일 때,Remote실행 환경일 때 동작하는 것이다. - 그래서
VSCode에서F5으로Xdebug실행 중이거나PhpStorm이 실행된 상태에서lsof -i :9000명령을 통해listen중이라는 것을 확인할 수 있다.
- 이 대전제를 두고
Docker까지는HOST OS위에서 돌아가기 때문에로컬 머신과 통신이 어렵지 않지만Remote환경의 경우 말이 달라진다.공인 IP를 사용하는로컬 머신에 통신 하려면 귀찮은 과정이 필요하다. 이런 경우SSH 터널링을 이용해서 손쉽게로컬 머신에 통신할 수 있으니Remote환경에서Debug이 필요한 경우SSH터널링을 사용하면 된다.
VSCode PHP 언어 기능 종류 조사
- 기본적으로
VSCode에서PHP관련 확장을 지원합니다. 하지만 그럼에도 기본 기능이 너무 빈약합니다.변수 인텔리센스(되는거 같아 보이지만 선언된 변수만 나오는게 아니라 이전에 입력된 것들 하이라이팅 해주는 것 정도) ,참조기능조차 지원되지 않습니다. - 이외
PHP언어 서버 관련 확장은 아래 2개가 있었으며 특징은 아래와 같습니다.- PHP IntelliSense
PHP공식 확장 같아 보이긴 하지만 이상하게PHP Intelephense보다 압도적으로 다운로드수가 적더군요.- 해당 확장을 사용하면
참조추적 같은 것은 됩니다. - 하지만
참조추적에서도정의된 부분까지는 추적으로 안나오고정의를 호출해야지 추적이 됩니다. (참조추적에서정의부분과 함께 못 본다는 아쉬움)변수 인텔리센스가 구립니다.빌트인 PHP와 다를 것이 없습니다.기호,정의살펴보기가 안됩니다. (근데 확장 README에 보면 되는거 같긴 한데 이건PHP@8이라서 그런거 같기도 한데 최신 버전이라서 안되는 기능이 있다는 것이 자체가 아쉽습니다.)호버시 정보가 아쉽습니다.PhpStorm은 관련 링크 및 자세한 설명이 있는데 말이죠- 중복 변수 선언에 대해서 경고하지 않습니다.
- 무엇보다
README에 보면PHP@7.4이하에서는 동작하지 않는다고 하니 레거시 프로젝트 사용에 적합하지 않습니다.
- PHP Intelephense
PHP IntelliSense보다 앞도적으로 많은 다운로드가 있는 확장입니다.- 해당 확장은
참조추적에서정의와 함께 나와서 보기도 편하고변수관련 인텐리센스도 똑똑하게 되며기호,정의살펴보기도 되므로PHP확장 중 가장 스마트합니다.호버시PhpStorm처럼 디테일하게 나오고README설명 자체에도PhpStorm의 메타데이터를 읽는다고 나와있습니다.- 중복 변수 선언의 경우 린트로 경고해줍니다.
- PHP IntelliSense
- 결론적으로 가장 똑똑하고 기능이 좋은
PHP Intelephense확장을 사용하도록 합니다.PHP Intelephense확장을 사용하기 위해서는 확장 README 에 있는대로 하면 됩니다.PHP프로젝트를 열면PHPbin 등록하라고 경고가 나오는데PHP Intelephense를 사용하면서PHP Language Features를 비활성화 하므로bin등록도 해야 좋은거 아닌가? 라는 생각은 하지 않아도 될 거 같습니다.PHP버전에 맞게PHP Intelephense설정 변경 및라이브러리사용 시stub추가할 것이 있는지 찾아서 설명하면 됩니다.
VSCode PHP 환경의 아쉬운 기능들
그동안 VSCode 에서 매우 친화적인 TS + Node.js 를 사용하느라 못 느낀 것이지만 VSCode 에서 PHP 을 하려고 보니까 기능이 너무 빈약한 것을 느끼고 있습니다.
- 가볍게 편집하고 이런 것은 편해 보이는데, 확실히
리팩터링및 더 고급 기능을 위해서는PhpStorm을 쓰는 것이 맞아 보입니다. - PHP 확장 중 유료
PHP Intelephense말고는F2로 리팩토링 기능이 없습니다… 세상에… JS와PHP가 합쳐지는 것에 대해서는 참조 기능이 빈약합니다.PHP확장자이더라도HTML,JS를 작성할 수 있는데,JS에서 참조 조회 시VSCode는JS파일에 대해서만 생각하고 찾는 것 같습니다.PhpStorm은 나오는데VSCode는 안 나옵니다.
- 다른 확장도 그런지 모르겠지만, 정의되지 않은 변수에 대해서 경고를 표시하지 않습니다. (이건 조금 찾아보니까 LSP가 아니라 정적 도구를 통해서 해결해야 될 것 같더라고요)
- 아래와 같이 정의되지 않은 변수가 표시되어야 할 것 같지만
- 안나옵니다.
- 아래와 같이 정의되지 않은 변수가 표시되어야 할 것 같지만
PhpStorm은 폴더 이름 변경 시include경로도 찾아서 바꿔줍니다… 대박
VSCode CodeIgniter 설정
VSCode에서PHP Intelephense설정 후 CodeIgniter을 사용하는 제품을 열었더니this->Model으로 잡는 변수들에서 정의되지 않았다고 오류가 발생했습니다.- 관련해서 찾아보니
- 정의되지 않은 것에 대한 경고 비활성화 하는 방법 (기능을 깍아서 해결)
CodeIgniter관련Stub추가CodeIgniter관련 확장- 관련
Stackoverflow
- 결론적으로 손쉽게 해결하는 방법을 찾지 못했습니다.
- 이것이 왜 어려운 문제인지 살펴보면,
Model과 같은 정보가 정적으로 주입되는 것이 아니라RunTime에 주입되기 때문입니다. 그래서 정적 분석 도구가 이를 찾기 어렵다고 합니다. 이와 관련하여PHP와 같은 스크립트 언어의 이러한 불편함에 대해 다룬 글들도 있습니다.
마무리
실 개발 환경은 서버에서 실행되고 있어서 리버스로 찾아서 하느라 힘들었다.
덕분에 이런 환경도 경험해보게 되었는데 직접 만들면서 Debug의 구성 방식에 대해 많이 배울 수 있었다. 언어 기능이 당연한 것이라고 생각했는데 그렇지 않다는 것도 느끼었고 현대적인 언어가 얼마나 친절하게 제공되고 있는지 감사함을 느낄 수 있었다.
처음에 이런 환경을 만들기 위해 너무 막막했는데 누군가에게는 도움이 되었으면 좋겠습니다.