피닉스(Phoenix)는 엘릭서(Elixir) 언어로 작성된 웹 애플리케이션 프레임워크입니다. 피닉스를 구성하는 많은 컴포넌트는 루비 온 레일즈(Ruby on Rails) 같은 다른 웹 애플리케이션 프레임워크와 유사한 점이 많습니다. 이 글에서는 레일즈 개발자에게 익숙한 개념과의 비교를 통해 간단한 블로그 웹 애플리케이션을 만들어 보면서 피닉스를 알아보겠습니다.
그에 앞서 피닉스 애플리케이션을 개발하기 위해서는 몇 가지 용어와 개념에 대한 이해가 필요합니다. 이를 위해서 긴 설명을 할 수도 있지만, 이 글에서는 루비 온 레일즈 개발자들이 쉽게 이해할 수 있도록 엘릭서/피닉스에서 사용하는 용어, 또는 개념과 대응하는 레일즈의 용어, 또는 개념을 표 형태로 확인해 보겠습니다.
표에서도 확인할 수 있지만, 피닉스의 많은 용어와 개념, 그리고 명령어들은 레일즈와 대응됨을 알 수 있습니다. 피닉스를 이용한 웹 애플리케이션 개발 과정을 간단히 설명하면서 대응하는 레일즈의 명령어, 또는 개념을 덧붙여 설명합니다. 글의 내용 중 잘못된 부분이 있다면 언제든지 지적해주시면 감사하겠습니다.
개발환경 설정
엘릭서 설치 for 맥 OS X
앞에서 설명했지만, 피닉스는 엘릭서로 작성된 프레임워크며 이 글에서는 엘릭서 언어를 이용해 블로그 웹 애플리케이션을 만듭니다. 이를 위해서는 엘릭서가 설치되어 있어야 합니다. 맥 OS X에서는 홈브루(Homebrew)를 통해서 간단하게 엘릭서를 설치할 수 있고, 맥 OS X 이외의 플랫폼에 엘릭서를 설치하는 방법은 이 링크에서 확인할 수 있습니다.
엘릭서로 작성된 코드는 얼랭(Erlang) 바이트 코드로 컴파일된 후 얼랭 VM 위에서 실행됩니다. 즉, 엘릭서로 작성된 코드를 실행하기 위해서는 얼랭 또한 필요합니다. 하지만, 위의 과정에서 brew 명령어를 통해 엘릭서를 설치했다면 얼랭 역시 함께 설치되기 때문에 이 과정을 생략하실 수 있습니다. 아래의 명령어를 이용해서 얼랭이 제대로 설치되어있는지 확인해보실 수 있습니다. (얼랭의 버전 확인)
헥스(HEX) 설치
헥스는 피닉스 애플리케이션을 실행하는 데 필요한 디펜던시(dependency)로 레일즈의 젬(gem)과 유사한 개념이라고 생각할 수 있습니다. 믹스(mix)는 이런 헥스의 디펜던시를 손쉽게 설치할 수 있도록 돕는 일종의 패키지 매니저로 레일즈의 레이크(rake), 또는 번들러(bundler)와 유사한 개념이라고 생각하시면 이해가 쉽습니다. 엘릭서 설치가 완료되었다면 믹스를 이용해서 헥스를 설치해보겠습니다.
피닉스 설치
이제 피닉스 프레임워크를 설치해보겠습니다. 피닉스는 믹스 아카이브(Mix archive) 형태로 설치하는데 여기서 믹스 아카이브란 피닉스 애플리케이션과 이를 컴파일한 BEAM 파일이 압축된 Zip 파일입니다. 아래의 명령어를 이용해서 피닉스 믹스 아카이브를 설치해보겠습니다.
이제 피닉스 애플리케이션을 개발할 준비를 모두 마쳤습니다. 그럼 실제 피닉스 애플리케이션 개발을 시작하겠습니다.
애플리케이션 생성
새로운 애플리케이션 생성
새로운 피닉스 애플리케이션을 생성하는 것은 매우 간편합니다. 새로운 레일즈 애플리케이션을 개발하기 위해서 레일즈 뉴 명령어를 이용하듯 피닉스 역시 아래와 같이 간단한 명령어 하나로 새로운 애플리케이션을 생성할 수 있습니다.
피닉스는 기본적으로 포스트그레SQL(PostgreSQL)을 데이터베이스로 사용하는 것을 가정합니다. 이 글에서는 데이터베이스를 MySQL로 이용할 수 있도록 –database mysql 옵션을 추가해 새로운 애플리케이션을 생성해보겠습니다.
설치 과정에서 “Fetch and install dependencies?”라는 질문을 듣는데 특별한 경우가 아니라면 “Y”를 입력해서 관련된 디펜던시를 함께 설치하겠습니다.
데이터베이스 환경 설정
피닉스는 레일즈와 달리 환경(environment)별 설정 파일을 별도로 관리합니다. 개발 환경에서의 데이터베이스 커넥션 정보를 설정하기 위해 config/dev.exs 파일을 열어 하단에 위치한 MySQL 커넥션 정보를 수정합니다. 아래의 내용에서 필요한 정보를 자신의 데이터베이스 환경에 맞도록 수정하면 됩니다.
여기에서 주의할 점은, 개발환경의 데이터베이스 설정 정보가 외부에 노출되지 않게 하기 위해서는 config/dev.secret.exs 파일에 환경설정 내용을 입력하고 이 내용을 config/dev.exs 파일에서 import 해야 한다는 점입니다.
.exs 파일 확장자는 .ex 파일과 마찬가지로 엘릭서 파일을 나타내는 확장자입니다. 다만, .ex 파일은 컴파일된 코드를 의미하지만 .exs 파일은 컴파일이 필요 없는 스크립트 파일을 의미합니다.
데이터베이스 환경을 정확히 설정했다면 이제 아래의 명령어를 이용해서 데이터베이스를 생성해보겠습니다. (피닉스 애플리케이션을 처음 만들어본다면 데이터베이스를 설치하는 과정에서 Rebar를 설치할 것인지를 묻는 프롬프트를 마주하게 됩니다. “Y”를 입력해서 Rebar를 함께 설치하도록 합니다.)
만약, Access denied for user ‘your_user_name’@’localhost’ to database ‘피닉스_blog_dev’ 오류 메시지가 출력되면 아래와 같이 GRANT 명령을 통해 해당 사용자에게 privilege를 부여하고 mix ecto.create 명령어를 다시 실행하도록 합니다.
애플리케이션 실행
데이터베이스까지 정상적으로 생성되었다면 이제 피닉스 애플리케이션을 실행할 수 있습니다. 아래와 같이 mix phx.server 명령어를 통해 피닉스 서버를 실행해보겠습니다.
피닉스 웹 애플리케이션을 기본적으로 4000번 포트를 이용합니다. http://localhost:4000 에 접속해 서버가 정상적으로 실행되었는지 확인해보겠습니다. 아래와 같은 화면을 웹 브라우저에서 볼 수 있다면 애플리케이션 생성과 서버의 실행이 정상적으로 되었다는 것을 알 수 있습니다.
컨텍스트 모듈 생성
레일즈 개발자라면 스캐폴드(scaffold) 생성에 매우 익숙할 것입니다. 레일즈에서 스캐폴드는 빠른 개발은 물론, 리소스를 RESTful한 방식으로 제어하는 방법을 이해하는 데 필수적이라고 할 수 있습니다. 피닉스 역시 스캐폴드를 생성하는 방식이 레일즈와 매우 유사합니다. 다만, 피닉스에서는 이를 컨텍스트 모듈(Context module)이라고 부르며 아래와 같은 방식으로 생성할 수 있습니다.
mix phx.gen.html 명령어의 첫 번째 인자로 나오는 Blog가 바로 컨텍스트 모듈의 이름이며 뒤에 따라오는 Post가 스키마의 모듈 이름입니다. 피닉스에서 컨텍스트 모듈은 특정 리소스(resource)에 대한 API 바운더리(boundary)를 제공하는 일종의 엘릭서 모듈입니다. 뒤에 따라 나오는 posts 인자는 스키마 모듈(schema module)의 복수형으로 리소스 이름이며 테이블의 이름으로 사용됩니다.
레일즈의 스캐폴드, 또는 모델 생성과 마찬가지로 스키마 모듈 뒤에 이어지는 인자들은 모두 모델의 필드와 데이터 타입을 나타냅니다. 피닉스에서는 특별히 필드의 데이터 유형을 지정해주지 않는 경우 해당 필드의 데이터 타입이 string이라는 것을 의미합니다. (우리는 아직 사용자 컨텍스트 모듈이 없기 때문에 작성자를 author라는 이름의 문자열 필드로 처리하겠습니다.)
만약 컨텍스트 모듈의 생성이 정상적으로 이루어졌다면 우리는 아래와 같은 결과를 확인할 수 있고, 이 과정을 통해 컨트롤러(controller)와 뷰(views), 그리고 HTML 리소스를 위한 컨텍스트(Context)가 생성되었음을 확인할 수 있습니다.
피닉스가 레일즈와 다른 점은 리소스에 대한 routes 설정을 자동으로 해주지 않는다는 점입니다. 컨텍스트 모듈 생성의 출력화면에서 확인할 수 있듯이 Post 리소스에 대한 routes 설정을 lib/Phoenix_blog_web/router.ex 파일에 추가해주겠습니다.
여기에서 주의할 점은 해당 routes 정보를 defmodule PhoenixBlogWeb.Router do 블록이 아닌, scope “/”, PhoenixBlogWeb do 블록에 추가해 주어야 한다는 점입니다. 여기에서 scope는 레일즈의 namespace와 유사한 개념이지만 레일즈의 routes.rb 파일과 달리 피닉스에서는 routes 정보를 최상위 블록이 아닌 scope 블록 내에 적어주어야 합니다.
레일즈와 마찬가지로 피닉스 애플리케이션을 실행하기 위해서는 pending 상태의 마이그레이션이 존재해서는 안 됩니다. 이를 위해서 아래와 같은 명령어로 마이그레이션을 실행해보겠습니다.
마이그레이션이 정상적으로 실행되었다면 이제 블로그의 콘텐츠 목록을 조회하고 생성/수정/삭제할 수 있는 컨텍스트 모듈을 웹 브라우저에서 확인할 수 있습니다. 웹 브라우저의 주소창에 http://localhost:4000/posts 주소를 입력하고 아래와 같이 Post 리소스의 index 화면에서 리소스에 대한 CRUD가 정상적으로 이루어지는지 확인해 보겠습니다. 정상적으로 컨텍스트 모듈이 생성되었다면 레일즈 개발자에게 너무나도 익숙한 화면들을 확인할 수 있습니다.
정리
이번 글에서는 레일즈 개발자들이 이미 익숙한 개념들과 비교를 통해서 피닉스 프레임워크를 이용한 웹 애플리케이션 개발하는 방법을 알아보았습니다. 먼저 엘릭서를 비롯한 피닉스 애플리케이션에 필요한 환경을 설치하고, 피닉스 애플리케이션의 생성 및 기본적으로 필요한 설정을 간단히 살펴보았습니다. 끝으로 레일즈의 스캐폴드 제너레이션(scaffold generation)과 대응하는 개념으로 피닉스의 컨텍스트 모듈을 생성하는 방법을 알고 피닉스를 이용한 기본적인 웹 애플리케이션 개발 방법을 알아보았습니다.
이번 글에서는 주로 웹 애플리케이션 프레임워크로서 피닉스와 레일즈의 개념을 비교하며 알아보았기 때문에 엘릭서 프로그래밍 언어 자체에 대한 내용은 깊이 있게 다루지 못했습니다. 다음 포스팅에서는 이 글에서 생성한 웹 애플리케이션의 일부 기능들을 수정 및 보완하면서 엘릭서 프로그래밍 언어를 어떻게 작성하고 동작시키는지 좀 더 자세히 살펴보겠습니다. 마지막으로, 이 글에서 작성된 모든 코드는 이 링크에서 확인하실 수 있습니다.