[Clone Coding] Make Wordle using Phoenix LiveView: Requirements Analysis & Project Setup

posted by donghyun

last updated

5 min read

태그

Phoenix LiveView로 wordle 만들어보기 2번째: 요구사항 분석 및 프로젝트 초기 세팅

이전 시리즈

  1. Make Wordle using Phoenix LiveView: Introduction

Requirements

Functional Requirements

  • 사용자가 5개 알파벳으로된 word를 맞추면 승리하는 게임
  • 6번의 시도 안에 맞춰야 한다.
  • 단어는 알파벳 26자로만 이루어져 있다.
  • 단어는 서버가 가진 별도의 사전에서 랜덤으로 뽑힌 단어이며, 사용자는 서버 사전에 존재하는 단어로만 입력을 시도할 수 있다.
  • 알파벳은 중복해서 쓰일 수 있다.
  • 사용한 알파벳에 대해 표식이 붙는데, 위치까지 일치하는 알파벳은 초록색, 위치는 맞지 않지만 정답에 존재하는 알파벳은 노란색, 존재하지 않는 알파벳은 회색으로 표시된다.
  • 사용한 알파벳중 회색표시된 알파벳은 다시 쓰일 수 없다.

Non-FR

  • 사용자마다 각각 게임 서버 프로세스를 띄우도록 할 예정
  • 게임 서버 프로세스, 단어 모음집, 웹 서버를 적절히 분리한다.

프로젝트 세팅

PreRequisite

  • elixir/OTP version: 13.3/24.1 (installed by asdf package manager)
  • phx_new: installed by mix archive.install hex phx_new
  • dependencies version
    • :phoenix: 1.6.6
    • :phoenix_live_view: 0.17.5
    • :tailwind: 0.1
    • :esbuild: 0.3

Project Structure

프로젝트를 생성하기에 앞서 어떤 구조로 만들것인지 먼저 생각해보고, 대략적인 구조를 잡아본다. 생각해볼 점은 비즈니스 로직인 게임 모듈과 게임에서 필요한 단어 모음집을 불러오는 저장소 모듈, 웹 인터페이스 모듈을 어떻게 적절히 분리해볼까에 대한 부분이다.

Dave Thomas의 ‘Elixir for Programmers, 2nd Edition’ 강의 에서 hangman 게임을 만들때 소개한 프로젝트 구조가 마음에 들어서, 그와 비슷하게 구조를 잡아보았다.

우선 단어 저장소 모듈을 Dictionary, 게임의 인터페이스 모듈은 MyWordle, 웹 모듈은 MyWordleWeb 이렇게 최상위 네임스페이스와 최상위 인터페이스 모듈들을 정의한다.

웹 인터페이스에서 유저가 게임을 실행하면 게임 인터페이스를 호출하고, 게임은 내부에서 자체 프로세스에서 실행되며, Dictionary에서 단어를 불러온다.

classDiagram
  Dictionary <|-- Runtime
  MyWordleWeb <|-- Runtime
  MyWordleWeb --|> MyWordle
  MyWordle --|> GameServer 
  Game <|-- GameServer
  GameServer <|-- Runtime
  MyWordle_Dictionary <|-- Game 
  Dictionary <|-- MyWordle_Dictionary 

  class Runtime~MyWordle~{
    Application
    GameSupervisor
  }

  class MyWordle{
  }
  class Game
  class Dictionary{
    Dictionary Server
  }
  class MyWordleWeb{
    Web Server
  }

최종적인 프로젝트 폴더 구조는 다음과 같이 만들어졌다.

my_wordle
├── lib
│   ├── dictionary
│   │   ├── server.ex
│   │   └── word_list.ex
│   ├── dictionary.ex
│   ├── my_wordle
│   │   ├── dictionary.ex
│   │   ├── game_type.ex
│   │   ├── impl
│   │   │   └── game.ex
│   │   ├── runtime
│   │   │   ├── application.ex
│   │   │   ├── game_supervisor.ex
│   │   │   └── server.ex
│   │   └── type.ex
│   ├── my_wordle.ex
│   ├── my_wordle_web
│   │   ├── controllers
│   │   │   └── page_controller.ex
│   │   ├── endpoint.ex
│   │   ├── gettext.ex
│   │   ├── live
│   │   │   ├── game
│   │   │   ├── game.ex
│   │   │   ├── game.html.heex
│   │   │   └── live_helpers.ex
│   │   ├── router.ex
│   │   ├── telemetry.ex
│   │   ├── templates
│   │   │   ├── layout
│   │   │   └── page
│   │   └── views
│   │       ├── error_helpers.ex
│   │       ├── error_view.ex
│   │       ├── layout_view.ex
│   │       └── page_view.ex
│   └── my_wordle_web.ex
├── mix.exs
├── mix.lock
...

강의에서처럼 아예 3개의 app을 결합하는 식으로 하면 더 경계가 분명하겠지만, 일단 한 프로젝트 내에서 최대한 처리해보고자 전부 lib 아래로 집어넣었다.

그럼 이제 프로젝트를 생성해볼 차례다.

Create New Project using mix phx.new

먼저 프로젝트를 생성한다. Phoenix LiveView 프로젝트이기 때문에 phx_new mix task를 활용한다.

원래 --live 옵션을 넣어야 phoenix_live_view 의존성이 들어갔었는데, 이젠 --no-live 옵션을 주지 않으면 default로 live_view 가 들어가는것 같다.

이 프로젝트에서 Database는 현재 고려대상이 아니므로, --no-ecto 옵션을 붙여서 Ecto 관련 의존성을 제거한다. 마찬가지로 mail 관련 기능 역시 --no-mailer 옵션으로 제거한다.

mix phx.new my_wordle --no-ecto --no-mailer --install

그럼 이제 다음처럼 프로젝트 생성 및 의존성 불러오기가 진행된다.

* creating my_wordle/config/config.exs
...
* creating my_wordle/lib/my_wordle/application.ex
* creating my_wordle/lib/my_wordle.ex
...
* creating my_wordle/mix.exs
* creating my_wordle/README.md
* creating my_wordle/.formatter.exs
* creating my_wordle/.gitignore
...
* creating my_wordle/assets/js/app.js
...
* running mix deps.get
* running mix deps.compile

We are almost there! The following steps are missing:

    $ cd my_wordle

Start your Phoenix app with:

    $ mix phx.server

You can also run your app inside IEx (Interactive Elixir) as:

    $ iex -S mix phx.server

Setup TailwindCSS for Phoenix

CSS 프레임워크인 tailwind를 세팅해보자. tailwind 공식문서 가이드에 Phoenix 프로젝트에 설치하는법이 친절하게 나와있으므로 보고 따라해보면 어렵지 않다.

Note

위 가이드를 보면 중간에 mix tailwin.install 하는 step이 있는데, 직접 해본 바로는 저 명령어 이후 step은 여기서 자동으로 이뤄지는것 같다.

page 템플릿 밑의 index.html.heex 파일을 수정해서 tailwind CSS가 잘 동작하는지 확인해본다.

 # lib/my_wordle_web/templates/page/index.html.heex
<section class="w-full text-center">
  <h1 class="text-3xl font-bold underline">
    <%= gettext "Welcome to %{name}!", name: "Phoenix" %>
  </h1>
</section>

mix phx.server 로 실행해보면 일단 다음과 같은 페이지를 볼 수 있다.

phoenix welcome

다음 포스트에서는 요구사항을 만족하는 Game 모듈을 만들어보도록 하겠다.