NDM

게시판을 만들어보자 1편 : 요구사항 분석과 ERD설계 본문

기타

게시판을 만들어보자 1편 : 요구사항 분석과 ERD설계

ndm.jr 2022. 6. 21. 23:17

게시판을 만들어 보는 실습을 진행해 보려 한다

 

이미 몇번 게시판을 만들어 보았으나,

이번 실습은 과거에 게시판을 만들며 고려하지 않았던 것을 고려하고

왜 이런 생각이나 고민을 했으며, 어떻게 그 해결방법에 도달했는지, 그 고민을 해결하는 과정에 무게를 실으려고 한다.

 

SpringBoot / MyBatis를 사용할 예정이고, MyBatis로 작성한 이후 JPA로 바꾸는 과정까지 실습하겠다

또한 화면은 구현하지 않고 API만 작성하도록 하겠다


 

요구기능

회원

  • 회원 가입을 할 수 있다
  • 로그인을 할 수 있다
  • 회원은 회원 게시글에만, 비회원은 비회원 게시글에만 접근이 가능하다

 

게시글

  • 게시글 CRUD  ( 회원 / 비회원 모두 가능 )
  • 댓글 CRUD ( 회원 / 비회원 모두 가능 )
  • 게시글에는 조회수를 나타낼 수 있도록 할 것
  • 게시글에는 작성한 댓글 수가 함께 나타나도록 할 것
  • 게시글에는 작성시간을 노출할 것

 

대략적으로, ERD에는 User / Post / Comment 정도의 테이블이 필요할 것 같다

이제 자세하게 들어가보자


 

설계 전 고민

 

1. 회원용과 비회원용 게시판을 어떻게 구분할 것인가??

 

  • 테이블에  회원 / 비회원 구분 컬럼을 추가할까 vs 회원과 비회원 테이블을 따로 만들까??

    쇼핑몰의 판매자 vs 구매자 같은 경우 같은 Member테이블에서 컬럼을 만들고 Consumer / Seller 등으로 구분하는 것보다 별도의 도메인을 가져가는것이 맞다고 생각한다. 관련 기능이 아얘 다르다고 생각하기 때문이다

    예를 들어, 구매자는 상품을 장바구니에 담고 / 결제를 하고 / 문의글에 질문을 한다
    하지만 판매자는 장바구니를 쓸필요가 없으며 / 결제를 하지도 않으며 / 문의글에 답변을 해야 한다
    또한 각 쇼핑몰이 가진 특성에 따라 판매자와 구매자 테이블에 필요한 데이터가 크게 다를 수도 있다

    이 밖에도 많은 상황이 있는데, 이 때마다 같은 도메인에서 관련 코드로 분기처리를 해야하는 것은 비효율적이라고 생각하며, 이렇게 기능이 크게 상이할 때는 별도의 도메인을 가져가는 것이 맞다고 생각한다

    하지만 이번 프로젝트의 회원 / 비회원은 로그인을 했냐 / 안했냐의 차이만 있고, 요구 기능이 완전히 같기 때문에 테이블에 구분 컬럼을 추가하는 방향을 생각했다.


  • 그렇다면 구분 컬럼을 어떤 테이블에 위치시킬 것인가??

    User테이블에  회원 / 비회원 구분 컬럼을 위치시킨다면

    비회원으로 게시글이나 댓글을 작성할 때, User테이블에 id / password / nickname 등 로그인한 유저와 관련된 컬럼들이 비워진 채로 데이터가 계속해서 insert되어야 한다. 이렇게 대부분의 데이터가 null인 상태인 row를 삽입하는것이 과연 맞을까? 라는 생각이 들었다.

    또한 비회원의 경우 구분 컬럼 외에 비회원끼리 구분할 수 있는 컬럼이 없다면 자신이 이전에 쓴 게시글이나 댓글에 대해 수정이나 삭제를 하기가 까다롭다고 생각했다.

    Client IP를 헤더에 담아서 request를 보낼까 했지만 보안과 직결된 이런 정보를 매번 request에 담아 요청하는게 맞을까 싶었고, 만약 실무라면 중간에 로드밸런서나 웹서버가 별도로 존재할 텐데, 그러면 WAS는 client ip가 아닌 로드밸런서나 웹서버의 ip만 받게 된다.(물론 별도의 헤더를 설정하면 clientip를 볼 수 있긴 하다)

    Post / Comment에 회원 / 비회원 구분 컬럼을 위치시킨다면

    느낌부터 쎄하다. 어떤 도메인의 테이블이 다른 도메인의 정보를 갖고 있어야만 한다.
    또한, 위에서 언급했던 비회원이 자신이 작성했던 컨텐츠의 수정 / 삭제를 구분할 수 없다.

    쿠키나 세션도 생각해보았지만, 비회원이 언제 다시 게시판에 접속할지도 모르는데 평생 비회원 정보를 쿠키나 세션에 갖고있을 수도 없고, 낭비가 매우 심하다고 생각했다

    결론적으로, 어떤 테이블로 구분하던지 비회원이 자신의 컨텐츠를 구분할 수 있는 별도의 정보가 필요하다

  • 결론

    병원 예약이나 문의글을 남겨보았다면 알겠지만, 대부분의 병원 홈페이지에는 비회원 게시판이 있다
    글을 작성할 때 아이디와 비밀번호를 입력하고, 게시글에 다시 접근할 때는 다시 입력해야 한다.
    비회원 구분 문제를 해결하기 위해 이 아이디어를 적용하기로 했다.

    하지만 이 아이디어에도 고민이 있었다.
    "비회원 마다" 아이디 / 비밀번호가 필요한 것이 아니라 "비회원이 작성하는 게시글 또는 댓글 마다" 아이디 / 비밀번호가 필요하다. 이러면 과연 User 테이블에서 관리해야 할까, post / comment 테이블에서 관리해야 할까?

    만약 post / comment 테이블에서 관리한다면
    회원 / 비회원에 상관 없이 게시글이나 댓글을 작성할 때 한번의 insert 쿼리로 끝날 수 있다는 장점이 있지만
    1. 위에서 언급했던 다른 도메인의 정보를 갖고있어야 한다는 문제가 있고
    2. post / comment 테이블이 모두 아이디 / 비밀번호 컬럼을 갖고있어야 한다. 이 말은 "대댓글" 테이블이 추가되면
    대댓글 테이블에도 아이디 / 비밀번호 컬럼이 들어가야 한다. 즉, 테이블이 늘어날 때 마다 공통 컬럼이 계속해서 추가되어야 한다.

    User테이블에서 관리한다면
    비회원 데이터가 훨씬 많을것이다.
    사실상 "비회원이 작성하는 게시글 / 댓글" 이 하나의 row를 차지할 테니까.
    앞서 언급했던 회원 관련 컬럼이 텅텅 비워진 채 비회원 구분 아이디 / 비밀번호만 들어있는 row가 대다수가 될거라고 생각했다.

    때문에 결론적으로 비회원 전용 테이블을 따로 생성하고, 따로 관리하기로 했다.
    비회원이 게시글 / 댓글 작성 시 두번의 insert쿼리가 발생하긴 할 테지만, 가장 깔끔하게 데이터를 저장할 수 있을 것이라고 생각했다.

 

2. 조회수를 별도의 테이블로 분리할 것인가 / post테이블의 컬럼으로 놓을것인가??

 

  • 유튜브의 실시간 인기 게시글 같은 경우, 조회수가 굉장히 중요하다. 어떤 나이대의 시청자가 보았는지, 몇분이나 시청했는지가 알고리즘에 적용 될 것이기 때문에 이러한 경우는 조회수를 별도의 테이블로 빼는 것이 맞다고 생각한다.
  • 반면 일반적인 게시판의 경우 조회수가 그렇게 중요하지 않기 때문에 post테이블의 컬럼으로 두어도 크게 이상이 없을것이다.
  • 하지만 "조회할 때 마다 조회수가 1 증가한다"고 치면, update쿼리가 발생하면서 결국 post 테이블의 row에 rock이 걸린다. 극단적인 상황을 가정하면, 만약 작성자가 게시글 수정하고 있는데 누군가가 조회하는 순간 동시성 문제가 터질수도 있다.
더보기

개인적으로 게시글에 접근할 때 마다 매번 update 쿼리로 조회수를 1 증가시키는 것은 매우 비효율적이라고 생각한다. 차라리 특정 저장소에 조회수를 모아두었다가, 시간 간격으로 update쿼리를 보내 조회수를 증가시키는 방법은 어떨까 싶다. 특정 숫자를 기준으로 (예를 들어 조회수가 100, 200에 도달하면) update쿼리를 보낼수도 있지만, 이러면 평생 조회수가 0인 게시글도 생기고, 조회수가 100의 단위로만 바뀌게 된다.

 

  • 떄문에 이번 프로젝트에서는 조회수를 별도의 테이블로 분리할것이다.

 

3. post / comment 테이블의 데이터를 삭제할 때, 실제로 삭제할 것인가, 사용유무 컬럼을 두고 사용자에게 보여지지만 않게 만들것인가??

 

  • 어떤 중요한 데이터는 실제 삭제시키는 것이 아니라 사용자에게 보여지지 않게만 처리한다고 들은 적이 있다.
  • 그래도 이번 프로젝트에서는 그냥 삭제시키기로 했다. 그렇게 중요한 데이터는 없을것이다
  • 하지만 이러한 상황을 가정해보자. 데이터를 실제 데이터베이스에서 삭제시키는 정책으로 운영중인데, 만약 누군가가 사이버 범죄와 관련된 게시글이나 댓글을 작성하고 삭제해버렸다면, 어떻게 해야할까??

    지금 내 수준에서는 delete쿼리 발생 시 로그에 쿼리와 관련 데이터를 찍게 만들고, 로그데이터를 주기적으로 저장하는 방법이 떠오른다. 실제 게시판 운영쪽에서는 어떻게 하는지 궁금하다. 이 부분은 조금 더 알아봐야 할 것 같다

산출물

1차적인 산출물이다. 고민해보고 바뀌면 업데이트 될 수 있다.