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
의 경우9003
port,XDebug 버전 2
의 경우9000
port 를 기본 값으로 사용한다.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
프로젝트를 열면PHP
bin 등록하라고 경고가 나오는데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의 구성 방식에 대해 많이 배울 수 있었다. 언어 기능이 당연한 것이라고 생각했는데 그렇지 않다는 것도 느끼었고 현대적인 언어가 얼마나 친절하게 제공되고 있는지 감사함을 느낄 수 있었다.
처음에 이런 환경을 만들기 위해 너무 막막했는데 누군가에게는 도움이 되었으면 좋겠습니다.