이번 포스팅은 최신기술과는 거리가 멀다. 하지만, 여전히 시장에서는 카페24와 같은 웹호스팅 서비스를 사용하여 서비스를 배포하는 일이 자주 발생하는 만큼, 누군가에게 이 글은 도움이 되리라 생각한다. 나도 내 의지와는 상관없이 카페24에서 프로젝트를 할 일이 생긴데다가, 어떻게하면 카페24 환경에 라라벨 프로젝트를 간편하게 배포할 수 있을까 고민해본 결과 몇가지 가능성에 도달했다.
과거에 카페24를 사용하여 프로젝트를 진행했던 것은 레거시가 대부분이었기 때문에 그냥 아날로그식으로 FTP 를 연결해서 파일을 배포하면 그만이었다만, 라라벨을 할 때는 차마 그러고 싶지 않았다. 이제는 그러한 배포방식에서 벗어나야만 한다.
라라벨 프로젝트를 배포하는 것은 Laravel Envoyer, Laravel Forge 등이 있지만 유료다.
카페24 웹호스팅 환경
이 글을 작성하는 시점에서 카페24 웹호스팅 환경의 몇가지 특징이 존재한다. 단순 PHP 웹호스팅인 만큼 제한이 있다.
- 컴포저(Composer)가 지원되지 않는다.
- PHP 7.4 를 선택해도 CLI 로 구동되는 것은 7.0.0, 구동 버전만 7.4 이다.
- 깃(Git) 사용에 어느정도 제약이 있다.
컴포저가 없다는 것은 배포에 치명적이며, 실제로 구동되는 버전이야 어찌되었든 CLI 가 7.0.0 으로 구동된다는 것은 라라벨의 버전에도 영향이 가게된다.
Composer
Composer 는 PHP 패키지 매니저이고, 라라벨을 비롯한 PHP 프레임워크에는 각종 패키지가 모여있는 vendor 가 있다. vendor 는 파일이 보통많은게 아니다. FTP 로 통째로 업로드하는 것은 할 짓이 아니다. 따라서 composer 를 통해 직접 설치해야하는데, 문제는 카페24 웹호스팅 환경에는 없다는 것이다.
$ composer
bash2: composer: command not found
사실 composer 는 까보면 그냥 PHP 파일이다. 따라서 installer 를 다운받고 스크립트를 실행해주면 composer 를 얻을 수 있다. 다운로드에서 Command-line installation 을 참고하자. 다만 그대로하기보다는 아래의 명령어로 설치할 수 있다. 이 작업은 웹호스팅 SSH 로 진입해서 하는 것이다.
$ curl -o composer-setup.php https://getcomposer.org/installer
$ ls
composer-setup.php www
composer-setup.php 이 있는 것을 확인했다면, 이제 설치하자. allow_url_fopen 은 원래 보안상 설정되어 있지 않은 것이 일반적이나 설치를 위해 일시적으로 활성화한다.
$ php -d "allow_url_fopen=On" composer-setup.php
All settings correct for using Composer
Downloading...
Composer (version 2.2.5) successfully installed to: /user/composer.phar
Use it: php composer.phar
$ ls
composer-setup.php composer.phar www
이제 설치가 끝났다. composer.phar 로 실행할 수 있다. 컴포저가 동작한다!
$ php composer.phar --version
Composer version 2.2.5 2022-01-21 17:25:52
컴포저가 해결되었기 때문에 이 부분은 어떻게든 될 것같다. 이제는 무식하게 vendor 를 직접 업로드하는 행위는 하지 않아도 된다.
Version
카페24에서는 PHP 7.4 를 설정하도록 해도 CLI 로 구동되는 버전은 PHP 7.0.0 으로 고정된다. 그러나 실제로 구동되는 것은 7.4 이다.
$ php --version
PHP 7.0.0p1 (cli) (built: May 10 2016 13:43:32) ( NTS )
Copyright (c) 1997-2015 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2015 Zend Technologies
with the ionCube PHP Loader (enabled) + Intrusion Protection from ioncube24.com (unconfigured) v6.1.0 (), Copyright (c) 2002-2017, by ionCube Ltd.
이게 의미하는 것이 무엇이냐면, 실제 서비스에서 구동되는 버전이 PHP 7.4 이므로 Laravel 8 버전을 구동하는 것은 가능하지만, CLI 는 PHP 7.0.0 이 기준이기 때문에 아티즌(Artisan) 등의 명령줄 모음을 사용하려면 Laravel 5.5 를 사용해야 함을 말한다. 컴포저를 통해 설치하려고 시도해도 7.0.0 을 기준으로 설치되므로 7.1 이상을 요구하는 패키지는 설치되지 않는다.
Laravel 5.5 는 LTS(Long Term Support)이었기 때문에 안정적이고 자료도 많은 편이라 서비스를 구축하는 것에는 큰 무리가 없어서 그나마 다행인데, 최신버전은 고사하고 7.4 에 대응하는 Laravel 8 을 사용할 수 없다는 점은 감수해야될 부분이기도 하다.
무식한 방법으로 라라벨 사용하기: 라라벨을 로컬에서 생성해서 FTP 로 때려박으면 Laravel 8 을 사용할 수 있다. 이 경우 아티즌 명령줄을 사용하는 것은 포기해야한다.
Git
먼저, git pull
은 사용할 수 없다. git 자체는 설치되어있지만 일부 명령어에 대해서는 막혀있다고 볼 수 있다. 다른 방법을 강구해야만 한다.
$ git pull
fatal: Uh oh. Your system reports no Git commands at all.
git 명령어를 사용하여 배포를 처리하고 싶지 않다면 이 부분은 넘어가도 된다. Github Action 에서 FTP 로 배포하는 방법도 간단하게 이야기해볼 예정이다.
git clone
하지만 방법이 있는데, 바로 git clone
은 가능하다는 점이다. 이를 사용하면 프로젝트를 복사할 수 있고, 비공개 레포를 대상으로도 가능하다. 서버에서 깃허브에 있는 비공개 레포를 얻어오려면 SSH 키를 생성해서 등록하는 과정이 필요하다. 하지만 카페24 웹호스팅에는 ssh-keygen
이 없다.
$ ssh-keygen
bash2: ssh-keygen: command not found
이 역시 방법이 있는데, 바로 SSH 키는 온라인에서도 생성이 가능하다는 점이다. Online SSH Key Pair Generator 를 검색해보면 여러 개가 나올텐데 여기서는 아래의 사이트를 이용했다.
생성된 키는 어디에 등록해야하는가? 그건 바로 레포지토리 내부에 있는 Deploy Keys 에 등록하면 된다.
Deploy Keys 에 SSH 키를 등록하면 해당 레포에 대한 접근 권한이 생성된다. 개별 레포지토리에 대한 접근 권한을 설정할 수 있기때문에 계정에 SSH Key 를 설정하는 것보다 훨씬 나은 방법이라고 볼 수 있다. 등록할 때 키 이름은 임의로 주면 되는데, 그 내용은 반드시 공개키(Public Key)의 값을 넣어야한다. 공개키는 생성한 알고리즘의 이름으로 시작한다.
이제 다시 호스팅 서버로 이동해서 작업을 해보자. 사용자의 홈 디렉터리에서 .ssh 를 생성하고 권한을 설정하자.
$ cd ~
$ mkdir .ssh
$ chmod 700 .ssh
이제 id_rsa 파일을 만들어야하는데, 그 내용은 아까 생성해두었던 개인키(Private Key)가 입력되어 있어야한다. 권한 설정은 중요하다. 하지않으면 에러를 유발하게 될 것이다.
$ cd ~/.ssh
$ touch id_rsa
$ chmod 600 id_rsa
$ vi id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQSSlU/oOkjemUgJt1pF2p1K/Wap98So
erG/p8+udVETQuAoMhIcc/6Da3e1bmHP2kPpUCC2ZAnLKWVkIy5nP6IxAAAAoG/vGkBv7x
pAAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJKVT+g6SN6ZSAm3
WkXanUr9Zqn3xKh6sb+nz651URNC4CgyEhxz/oNrd7VuYc/aQ+lQILZkCcspZWQjLmc/oj
EAAAAhAKTspB3538ZThYhqnLBTfzR4z6UP6dWKuqnFZsel864OAAAABm5vbmFtZQE=
-----END OPENSSH PRIVATE KEY-----
이제 git clone
을 하면 잘 된다.
$ git clone git@github.com:pronist/my-project.git
Cloning into 'my-project'...
warning: templates not found /usr/share/git-core/templates
remote: Enumerating objects: 3590, done.
remote: Counting objects: 100% (3590/3590), done.
remote: Compressing objects: 100% (2084/2084), done.
remote: Total 3590 (delta 2335), reused 2479 (delta 1390), pack-reused 0
Receiving objects: 100% (3590/3590), 34.83 MiB | 9.07 MiB/s, done.
Resolving deltas: 100% (2335/2335), done.
Github Action
깃허브에는 CI/CD 를 위한 Github Action 이라는 것이 존재한다. Github Action 을 사용하면 프로젝트를 Push/Release 하기만해도 테스트를 진행하고 알아서 배포까지 할 수 있다. 테스트는 넘어가도록 하고, 배포만 살펴보자면 위에서 이야기했던 git clone
을 사용해볼 수도 있고, 또는 FTP 를 사용하는 것도 가능하다. Github Action 에서는 각 작업에 대해 Workflow 라는 단위로 사용된다. 예를 들어 테스트와 배포를 위한 각각의 워크플로우를 작성할 수 있다.
Action secrets
Github Workflows 를 작성하기 전에 Github Action 에서 사용되는 민감한 값들에 대해 Secrets 에 몇가지 값을 만들어줄 필요가 있다. 각 값은 SSH 에 대한 호스트, 사용자이름, 비밀번호에 해당한다.
Github Workflows
Github 에서 자동으로 배포하려면 Workflow 를 먼저 만들어야할 필요성이 있다. 프로젝트에서 .github/workflows 폴더를 만들자.
$ cd my-project
$ mkdir .github
$ mkdir .github/workflows
$ cd .github/workflows
배포를 위한 Workflow 인 deployment.yml 파일을 만들고 작성해야한다.
$ touch deployment.yml
appleboy/ssh-action
Github workflows 에서 원격서버에 배포를 실행하려면 SSH 명령어를 실행할 수 있는 appleboy/ssh-action 을 사용하는 것이 좋다. Laravel Envoy 를 사용하면 비슷한 일을 할 수 있을지도 모르지만, 나는 그다지 선호하는 편은 아니다.
host, username, password
에는 Action secrets 에 저장한 값을 사용하는 것을 볼 수 있다.
name: Deployment
on:
release:
types: [ released ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Execute commands
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
password: ${{ secrets.PASSWORD }}
script: |
cd ~/releases
git clone git@github.com:pronist/my-project.git ${{ github.ref_name }}
cd ~/releases/${{ github.ref_name }}
php ~/composer.phar install -q --no-ansi --no-interaction
php artisan cache:clear
php artisan config:cache
php artisan route:cache
php artisan storage:link
php -r "copy('.env.example', '.env');"
shared=(storage bootstrap/cache)
for dir in ${shared[@]}
do
src=~/releases/${{ github.ref_name }}/${dir}
dst=~/releases/shared/${dir}
[ -f ${src} ] && rm ${src}
[ -d ${src} ] && rm -rf ${src}
ln -nfs ${dst} ${src}
done
ln -nfs ~/releases/${{ github.ref_name }}/public ~/www
간단하게 이야기해보자면 on - release - released
이기때문에 프로젝트가 깃허브상에 릴리즈되면 워크플로우가 동작하게 처리되어있다. steps
에는 각 워크플로우의 작업 단위인 job
이 나열되어있으며 당연히 살펴보아야하는 부분은 appleboy/ssh-action
이 사용된 부분에서 script
쪽의 코드다.
releases
가 이미 생성되어있다고 가정하고, git clone
으로 프로젝트를 복사한다. 여기서 사용된 ${{ github.ref_name }}
은 Github Action 에서 사용할 수 있는 Contexts 값이다.
cd ~/releases
git clone git@github.com:pronist/my-project.git ${{ github.ref_name }}
복사한 프로젝트 내부에서 진행하는 일들이 몇가지 있다. 먼저 컴포저를 사용하여 각종 패키지를 설치하고, php artisan route:cache, config:cache
같은 명령어를 사용하여 최적화를 진행해준다. 그 외에 공개 스토리지가 있다면 링크를 생성하는 등의 일을하면 되고, 마지막에는 .env.example 을 .env 로 복사한다. 그 이유는 로컬에서 개발할 때는 .env 를 사용하고 실서버에 사용되는 설정은 .env.example 에 작성했기 때문이다.
cd ~/releases/${{ github.ref_name }}
php ~/composer.phar install -q --no-ansi --no-interaction
php artisan cache:clear
php artisan config:cache
php artisan route:cache
php artisan storage:link
php -r "copy('.env.example', '.env');"
버전을 나누어서 관리할 때 중요한 것은 공유폴더를 어떻게 할 것이냐는 것이다. 예를 들어 사용자가 업로드한 파일이나 캐시 등은 버전에 관계없이 동일하게 유지되어야 할 필요가 있다. 그래서 공유폴더를 위한 심볼릭(Symbolic Link)를 지정해줄 필요가 있는데, 그 대상은 /releases/shared/storage, /releases/shared/bootstrap/cache
다.
shared=(storage bootstrap/cache)
for dir in ${shared[@]}
do
src=~/releases/${{ github.ref_name }}/${dir}
dst=~/releases/shared/${dir}
[ -f ${src} ] && rm ${src}
[ -d ${src} ] && rm -rf ${src}
ln -nfs ${dst} ${src}
done
이제 공개(Public) 폴더만 링크만 연결해주면 끝이다. 단순하게 링크를 연결하는 방식으로 하게되면 배포를 위해 어플리케이션을 중단하지 않아도 배포 할 수 있게된다.
ln -nfs ~/releases/${{ github.ref_name }}/public ~/www
SamKirkland/FTP-Deploy-Action
git clone
이 아닌 FTP 를 사용하여 배포해보고 싶다면 바로 SamKirkland/FTP-Deploy-Action 가 있다. 이를 사용하면 Github Action 에서 FTP 를 연결하여 프로젝트를 배포할 수 있다. 이 프로젝트는 git-ftp 을 기반으로 작성된 것으로 알고 있으므로 Github Action 을 사용하기 싫다면 사용해보는 것도 나쁘지 않을 것이다.
FTP 를 사용할 때 주의해야할 점은 카페24 에서 FTP 로 바로 연결하면 Document Root 인 www 로 연결하기 때문에 라라벨 프로젝트는 바로 위에다가 두어야 할 필요가 있다는 점이다. 배포 디렉터리는 server-dir
에서 설정한다.
name: Deployment
on:
release:
types: [ released ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Sync files
uses: SamKirkland/FTP-Deploy-Action@4.2.0
with:
server: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
password: ${{ secrets.PASSWORD }}
server-dir: ../my-project/
- name: Execute commands
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
password: ${{ secrets.PASSWORD }}
script: |
cd ~/my-project
php ~/composer.phar install -q --no-ansi --no-interaction
php artisan cache:clear
php artisan config:cache
php artisan route:cache
php artisan storage:link
php -r "copy('.env.example', '.env');"
ln -nfs ~/my-project/public ~/www
워크플로우 코드가 약간 바뀌었다. my-project
는 미리 생성해둘 필요가 있다. 마찬가지로 SSH 는 사용했지만, 이번에는 Github Action Contexts 를 사용한 버저닝(Versioning)은 하지 않았다. 그 이유는 매 버전에 따라 FTP 를 사용하여 배포하기엔 너무 업로드 속도가 느리기 때문이다. 대신 하나의 프로젝트에서 git pull
과 유사하게 파일 내용이 바뀐부분은 수정하고 삭제된 파일은 제거한다는 점이 있다.
마치며
여기까지 카페24에서 라라벨 프로젝트를 배포하는 방법을 알아보았다. 가상서버를 사용하거나 클라우드를 사용하는 것이 좋겠지만, 때때로 그러지 못하는 경우가 있고, 마침 그 환경을 마주했기 때문에, 이 기회에 고민을 해보게 되었다. 레거시는 싫고 라라벨을 사용하고 싶은데 카페24에 배포하는 경우, 또는 비슷한 환경이라면 참고하자.