inlee's blog

회고 - Laravel 게시판 패키지 구현 과정과 고민들

· inlee

2022.08: 게시판 개선이 있었으며 후기는 이곳을 참조 바랍니다.


BBS(Bulletin Board System) 라고도 부르는 게시판은 웹 어플리케이션의 기본 중의 기본이기 때문에 웹 어플리케이션 개발자라면 자신만의 게시판을 가지고 있을 것이다. 이 글은 Laravel 에서 사용할 게시판을 패키지 형태로 만든 방법과 만든 과정과 그 여정에서 했던 고민들에 대한 내용이다.

개요

회사를 그만두고 포트폴리오 겸 추후에 Laravel에서 사용할 게시판을 패키지 형태로 만들었다. 충분한 시간이 있었기 때문에 충분히 쉬며 생각한 것과 고민했었던 것들을 모두 해보고 싶었다. 기간은 2달 정도 걸렸는데, 생각보다 많은 시간이 소요되었지만 이 과정에서 코드 구현에만 시간을 쏟지 않았고 고민들의 해결을 위해 구조 변경을 여러번 했다. 완성을 하고 돌이켜보니 아쉬운 부분들이 많고 만족하지는 못하지만 해왔었던 고민들 중 많은 부분을 해결할 수 있었다.

이어지는 내용은 패키지 개발 설정 및 구현과 게시판을 개발하며 하였던 고민들에 대한 회고이다.

Laravel 패키지 개발 설정

단독으로 동작하는 PHP composer 패키지 개발은 여러번 해봤지만 이번에 구현한 게시판 패키지는 Laravel의 일부로 동작하기 때문에 만드는 과정에서 테스트가 반드시 필요했다. 그래서 Laravel 패키지 개발 설정을 어떻게 해야 하는지에 대해 찾아보았으며 그 중 링크에 있는 방법을 이용하였다. 설정 방법을 정리하자면 아래와 같다.

  1. Laravel 프로젝트 생성 후 packages`라는 디렉터리를 생성한 후 개발할 패키지가 저장될 디렉터리 생성
  2. 1에서 생성한 디렉터리에 Laravel이 패키지를 읽어 실행할 수 있도록 ServiceProvider 클래스 생성.
  3. 1의 생성된 디렉터리에 compose.json 파일을 생성하고 autoload, extra 항목에 패키지 정보 입력(ServiceProvider 위치, branch alias 지정)
  4. Laravel 프로젝트의 composer.json 내 require 항목에 패키지 이름과 버전(2의 branch alias에 입력한 정보), repositories 항목에 3의 패키지 정보 입력
  5. composer install 명령으로 개발할 패키지 디렉터리를 심볼릭 링크로 vendor 디렉터리에 설치하여 패키지 개발 설정 완료

게시판 패키지 구현

개발범위

구현하고자 하는 게시판은 기본 게시판 개발 범위 + 간단한 통계를 위한 기능 구현을 목표로 했다. 게시판 기능을 위주로 진행했기 때문에 파일 업로드 기능은 제외하였다.

  • 사용자 인증은 Laravel 인증 스캐폴딩을 이용하며 해당 기능은 수정을 최소한으로 하고 게시판 사용이 가능해야 함
  • 회원가입 시 게시판 사용자 등록이 가능해야 함
  • 게시판 사용자마다 게시판 사용 권한이 주어져야 함
  • 게시판 정보 저장 시 게시글 페이징 / 댓글 페이징 수, 게시판 게시글 및 댓글 역할 (읽기 / 쓰기) 설정 정보 포함
  • WYSIWYG 적용, 2 Depth 댓글 적용
  • User Agent 기반 통계 정보 산출 (사용자 접속한 OS, Browser 정보)
  • 패키지를 사용하는 사용자가 게시판 설정을 유연하게 할 수 있도록 config 제공

구현

개발 범위의 내용을 토대로 게시판 환경설정, 게시판 Controller, View(Blade), Model, Database 설정을 포함한 구현 하였으며 결과는 Github 리파지토리 에 업로드 하였다. 게시판 구현과 관련된 내용은 링크를 참조 바란다.

구현 후: 되돌아보기 (회고)

게시판 구현을 완료한 후 그 내용에 대해 되돌아 보면 아직 많이 부족하다는 것을 느꼈다. 아래는 구현 과정과 구현 완료 후에 대한 되돌아보고자 하는 글이다.

구현 과정

패키지 or 스캐폴딩

가장 고민했던 것은 ‘게시판을 패키지로 만들 것이냐 스캐폴딩(Scaffolding) 형태로 만들 것이냐’ 였다. 일반적인 경우라면 패키지 형태로 만들었겠지만 Laravel에서 제공하는 사용자 인증 스캐폴딩을 보고 생각을 해 보니 게시판도 마찬가지로 Route, Controller, View 등이 프로젝트에 직접적으로 사용되기 때문에 스캐폴딩 형태로 제작을 진행했었다.

그러나 버전관리 측면에서 패키지 형태가 용이하다고 판단했기 때문에 최종적으로 스캐폴딩 대신 패키지 형태로 구조를 변경하여 제작하였다. Laravel 패키지 제작 가이드에 보면 Laravel 패키지는 Laravel 애플리케이션의 기능을 사용하는 Route, Controller, View 설정들을 가질 수 있다고 명시하고 있으며 이를 ServiceProvider에 정의하여 사용하는 방법들을 제시하고 있다. 또한 가급적이면 다른 개발자가 Laravel 공식 문서와 본인이 만든 게시판 코드를 쉽게 알아볼 수 있도록 하고자 하였기 때문에 스캐폴딩에서 패키지 형태로 개발을 변경하여 진행하였다.

그러나 이 결정은 구현 완료 후 후회를 가져왔다. #

View

Laravel 공식 View template은 Blade 다. 그리고 Blade 내에서 Vue, React를 사용할 수 있도록 제공 프론트엔드 스캐폴딩을 제공하며 이들을 사용할 경우 npm 패키지 정보와 webpack 설정이 추가된다.

처음 개발 당시 자바스크립트와 레이아웃을 구조적으로 구성하여 사용하고자 Vue 컴포넌트를 이용해 개발했지만 이 과정에서 Vue 컴포넌트에 렌더링 대상 데이터를 전달(passing) 하는 과정에서 필요한 데이터만 전달하기 위해 별도의 처리가 필요했다. 또한 이 내용은 진행했던 Laravel 프로젝트에서도 했었던 고민이였다.

  • 최종 렌더링(Rendering) 결과인 HTML내 Vue 컴포넌트에 전달할 데이터는 렌더링에 필요한 데이터만 전달되어야 함
  • Controller에서 전달받은 데이터를 그대로 사용하면 필요하지 않은 데이터도 같이 HTML 파일에 출력되며 웹 사이트의 공격 대상이 될 수 있음

이 문제는 Controller에서 필요한 데이터만 출력 하거나 Blade에서 직접 가공해서 Vue 컴포넌트에 넘기는 방법 등을 통해 해결이 가능했다.

  • 필요한 데이터 가공을 Controller에서 처리할 경우 별도의 View 데이터의 가공 프로세스가 추가되나 추후 Controller를 API 용으로 사용 가능
  • 필요한 데이터 가공을 Blade에서 처리할 경우 View 데이터는 View에서 처리가 가능하며 Controller는 View 데이터 가공이 필요하지 않음

그러나 본 게시판 패키지를 사용하는 개발자가 프로젝트에서 Vue를 사용할지 하지 않을지 알 수 없기 때문에 최종 View 구현은 Blade로 구현하였다.

게시판 사용자 등록

게시판은 사용자 인증과 뗄레야 뗄 수 없다. 그래서 게시판 구현 시 사용자 인증도 같이 구현을 하는데, 본 게시판 구현에서는 기본으로 제공하는 Laravel의 인증을 이용하였다. 추가로 개발 시 게시판 패키지 삭제를 염두해 인증 기능을 최대한 수정하지 않고 사용하는 것을 목표로 하였기 때문에 게시판 사용자 정보는 별도의 테이블에 등록하는 방식으로 구현하였다.

문제는 게시판 사용자를 등록하는 방법을 어떻게 처리할지 였는데, 인증 스캐폴딩의 사용자 등록을 담당하는 RegisterController에 게시판 사용자 추가 trait을 추가하는 것으로 구현하였다.

  • 이 trait은 영문 사용자 이름을 소문자와 공백을 언더바(_)로 치환하여 닉네임으로 만들고 게시판 환경 설정 파일 내 중복방지여부에 설정이 되어 있으면 닉네임 뒤에 hash 코드를 추가하여 자동으로 닉네임을 생성한다.

현재 구현은 사용자 닉네임을 자동으로 생성하지만 추후 사용자가 입력할 수 있도록 view와 처리를 위한 trait을 구현여 적용을 해 볼까 한다.

댓글 구현

댓글 Depth 를 어디까지 허용할 것인가에 대한 고민을 하였다.

댓글 구현을 위해 여러 사이트를 탐색해보았는데 개인적인 기준으로 3 Depth 이하로 댓글이 있을 경우 가독성이 떨어졌다.

구현도 고려할 사항이였다. 일반적인 방법으로 2 Depth 구현은 부모-자식 댓글 ID를 이용해 정렬을 하면 쉽게 가져올 수 있지만 3 Depth 이상부터는 댓글에 순서를 붙여서 처리를 해야 하므로 구현이 번거로워진다. 조금 더 쉽게 해결하는 방법으로 MySQL에서 WITH RECURSIVE 문을 통한 Recursive Query를 이용할 수는 있지만 MySQL 8 버전 이상부터 지원하며 본 게시판 패키지를 사용할 개발자가 MySQL을 사용할 경우 어떤 버전을 사용할 지 알 수 없기 때문에 이 기능은 배제하였다.

위와 같은 이유로 댓글 Depth는 부모-자식 2단계로만 구현하였다.

WYSIWYG Editor

게시글, 댓글에 모두 적용할 수 있는 WYSIWYG Editor를 찾던 중 네이버가 개발한 Toast UI 를 이용했다가 게시글 수정 시 WYSIWYG Editor에 문서에 출력된 게시글 삽입이 쉬운 Quill.js 로 바꾸었다.

개인적으로 느꼈던 점을 추가하자면 Toast UI는 문서 보기가 어려웠고 Editor에 버튼 배치가 불가능했는데(Toast UI 문서를 제대로 보지 못해 관련 기능을 찾지못한 것일 수도 있다) Quill.js는 문서보기도 쉬었으며 버튼도 내가 원하는 방식으로 추가, 삭제, 배치가 가능했다.

게시판 구현하면서 WYSIWYG Editor를 직접 제작 해 보는 것도 많은 도움이 될 것 같다는 생각이 들었고 진행을 해 보려 한다.

구현 완료 후

스캐폴딩

결국 스캐폴딩 형태로 만들었어야 했다는 생각이 들었다. 패키지 개발 가이드에 있는 것처럼 Laravel 애플리케이션의 기능을 사용하는 Route, Controller, View 설정들을 가질 수 있다고 명시하고 있으나 다시 생각을 해 보니 개발자 입장에서는 게시판과 같이 Route, Controller, View 설정 등이 필요할 경우 패키지 내에서 동작하는 것이 아닌 Laravel 프로젝트에 포함되는 것이 관리 측면에서 매우 유리하다는 결론을 내리게 되었다.

그래서 스캐폴딩으로 프로젝트를 수정을 할 예정인데, 아래와 같은 내용들에 대한 고민을 하였으며 해결 또한 아래와 같이 하려 한다.

  • 스캐폴딩 파일 Publish 방법은 어떻게 할 것인가
    • 패키지의 ServiceProvider 내 publish 정의를 하면 쉽게 해결이 됨
      • 그러나, 정확히 기억나지는 않지만, 예전 스캐폴딩으로 구현할 당시 Route 메소드를 web.php에 파일 입출력으로 삽입하였는데 cache 삭제 시 해당 내용이 삭제되었음
        • 그래서 ServiceProvider 내에 파일 publish 메소드를 넣지 않고 별도의 명령어로 만들어야 함
        • 그런 이유에서인지 Laravel 사용자 인증 스캐폴딩도 vendor/laravel/ui/src/AuthCommand.php 에 정의된 내용을 별도의 command를 이용해 실행
  • 게시판 관련된 파일을 어느 것까지 publish 할 것인가
    • Config, Controller, Database (Migration), Model 파일 Publish
    • Middleware, 게시판 Core 코드는 Controller가 아닌 Trait 으로 분리하여 구현 후 패키지 내 저장
테스트 케이스

게시판 패키지를 구현하면서 시간이 소요된다는 핑계로 별도의 테스트 코드를 만들고 진행하지 않았는데 테스트케이스를 정의하여 진행할 예정이다.

관리자

공지글 등 작성 시 관리자 모드가 필요하지만 시간이 소요된다는 이유로 진행하지 않았다 (현재 공지글은 사용자 역할이 관리자일 경우에만 작성 가능). 기회가 된다면 관리자 로그인을 위한 별도의 가드(Guard) 추가 및 관리자용 페이지를 제작을 고려하고자 한다.

그 외

View

구현을 완료한 후 Vue 파일을 곧바로 Controller에서 사용할 수 없을까 해서 찾아보다 v8js 를 이용해 SSR(Server Side Rendering)을 하는 글을 발견했다. 조금 더 검토해 봐야겠지만 짧게 본 것으로는 PHP와 V8 Javascript 엔진을 동시에 설치해서 사용하는 방법으로 보이며 PHP v8js 객체를 생성해 Vue 를 번들링(Bundling) 없이 사용하는 것으로 보인다.

개인적인 의견으로는 이 방법도 프로젝트에 따라 필요하고 사용할 수 있겠지만, blade 템플릿에서 vue 컴포넌트에 전달할 데이터를 정리하여 전달하고 webpack으로 번들링 하여 사용하는 것이 쉽게 사용할 수 있을 것으로 생각된다. 혹은 backend(Laravel, Express, Django 등)와 frontend(Nuxt, Next 등) 를 분리한 후 GraphQL이나 Restful API를 이용해 개발하는 것이 서비스 확장에 훨씬 도움이 될 것으로 생각된다.

마치며

게시판 패키지를 구현하며 Laravel에 대해 몰랐던 것들에 대한 학습과 충분한 고민, 그리고 그동안 했었던 고민들 일부 해결을 할 수 있었다. 물론 완벽한 코드는 만들 수는 없지만, Controller를 포함한 서버 코드들은 최대한 깔끔하게 작성하려고 노력했다.

그리고 구현하면서 개발자 1년차, 5년차, 10년차 코드를 모두 경험했다. 처음부터 의욕적으로 했던 탓인지 소스코드가 물에 담가놓은 미역 줄기처럼 불어났고 이를 정리하는 과정에서 많은 코드와 파일들을 삭제하고 통합하였다. 결과적으로 너무 많은 모듈을 정리하고 통합한 것은 유지보수나 가독성 측면에서 잘 했다고 생각한다.

마지막으로 게시판 패키지를 스캐폴딩으로 전환하고 테스트케이스 구현을 하며 WYSIWYG Editor 구현 또한 추후 해 보려 하며 블로그를 통해 어떻게 했는지 작성해 보려 한다.