내일배움캠프 AI - 15일차 TIL, 2022.05.09

Dongwoo Kim·2022년 5월 9일
0

TIL / WIL

목록 보기
18/113

스파르타 코딩클럽

내일배움캠프 AI 웹개발자양성과정 2회차

2022.05.09. 15일차- TIL

1. merge라고 쓰고 conflict라고 읽는다.

09:00-10:00

오늘은 그동안 진행한 개별 개발상황을 공유하고 코드를 합치는 작업부터 진행했다. 다들 맡은 역할에 대해 책임감을 가지고 주말에도 작업을 했다는 것이 정말 대견했다. 하지만 좋은 점이 있으면 나쁜 점도 있는법. 아니나 다를까 코드를 머지하는 과정에서 충돌이 일어났다. 물론 개별적으로 다른 기능들을 작업하고있었기 때문에 이전 프로젝트에서처럼 복잡한 충돌은 아니었고 단순이 코드겹침(?) 수준이라 바로바로 수정할 수 있었다. 하지만 다음부터는 이러한 충돌도 방지하기위해 오늘처럼 아침마다 각자의 코드를 가볍게 리뷰하고 다같이 머지하는 일정을 고정적으로 해야할 필요성을 느꼈다.

2. DB 설계 수정 & 임시 DB 데이터 만들기

10:00-13:00
이후에는 DB 설계를 수정하는데 있어서 팀원들과 이야기를 나눴다. 주말동안 고민해본 결과 프로필 사진 DB에 저장하기위해서는 따로 프로필사진 콜랙션을 만들어야했다. 추가적으로 최근알림 데이터는 유저데이터에 객체 리스트로 저장하도록 설계했었는데 이를 따로 콜랙션을 나눠서 저장하여 유저 데이터크기가 커지는 상황을 방지하기로했다.

수정전 DB(왼쪽)와 수정후 DB(오른쪽) 다이어그램

이미지를 저장하는 방법은 GridFs를 사용하였다. GridFs는 용량이 큰 이미지도 데이터를 나누어서 저장할 수 있었기 때문이다. 또한 저장과정에서 filename을 Pofile과 Post의 key값으로 지정하여 간단하게 불러올 수 있었다.

  # 유저 정보 불러오기
  user_info = db.Users.find_one({"UserName": user_name})

  # 게시글 정보 불러오기
  posts = list(db.Posts.find({"UserName": user_name}))

  # 포스트 이미지 불러오기
  post_images = []
  fs = gridfs.GridFS(db, 'Post')
  for post in posts:
    data = db.Post.files.find_one({'filename': post['PostId']})
    my_id = data['_id']
    data = fs.get(my_id).read()

    data = base64.b64encode(data)
    data = data.decode()

    post_images.append(data)            

한가지 애를 먹었던 점이 있다면 data를 decode하는 부분이다. fs.get(my_id).read()는 bytes로 이미지를 반환하는데 이를 html에서 display하기위해서 어떤 작업이 필요할지 찾는데 시간이 오래 걸렸다. 인터넷에선 대부분 Node.js를 이용한 javascript 문법을 사용해서 해당 디코딩 작업을 찾는데 상당한 노력이 필요했다.

3. jinja2 너는 뭐니?

13:00-14:00 점심시간
14:00-17:00 jinja2로 html 구성하기

유저페이지는 유저마다의 개별 페이지를 가지기 때문에 url설정도 개별적으로 해줘야했다. 이 방법에 대해서는 따로 찾아보지않고 튜터님이 공지사항으로 알려준 글을 참고하여 만들었다. 그런데 이 과정에 있어서 jinja2에 대해 알게 되었다. 그동안 html을 어떠한 인자를 통해 구성하기 위해서는 javasrcipt의 ajax 콜을 이용해야했는데 jinja2 문법을 사용하면 아주 간단하게 구성할 수 있었다.

마치 python 문법을 그대로 사용하는 듯한 방법으로 사용할 수 있어서 직관적이고 편했다. 물론 배열의 길이를 반환하는 len() 함수나 in enurmerate와 같은 반복문은 사용할 수 없어서 다른 방법을 찾아야하는 경우도 있었다. 또한 한계점도 발견했다. jinja2문법은 인자를 페이지가 로딩할 때 전달하기때문에 로딩후 동적으로 UI를 변경하기위해서는 제한점이 많았다. 예를 들어 나의 유저페이지같은 경우 유저 게시물과 북마크 게시물은 같은 form안에서 유저가 선택할 때마다 내용이 번갈아가면서 보여져야한다. 따라서 jinja2를 이용하여 이를 구현하기위해서 페이지 로딩시 유저 게시물 정보와 북마크 게시물 정보를 모두 가져와야했고 (유저가 북마크 게시물을 선택하지않아서 안볼수도있는데) 또 가져온 정보들은 같은 form이지만 각각 따로 form을 만들어주어 유저가 선택할때마다 display를 토글해가며 보여줘야해서 같은 코드가 반복적으로 작성되는 단점이 있었다.

<div class="user_post_main_box">
  <div class="user_post_users">
    {% for i in range(posts|length) %}
    {% if i % 3 == 0 %}
    <div class="user_post_row">
      {% endif %}
      <div class="user_post_img_box">
        <img width="100%" src="data:image/jpg;base64, {{ post_images[i] }}"/>
        <div class="user_post_info_box">
          <div class="user_post_like_box">
            <i class="fa-solid fa-heart"></i>
            {{ posts[i]['LikeCnt'] }}
          </div>
          <div class="user_post_comment_box">
            <i class="fa-solid fa-comment"></i>
            {{ posts[i]['CommentCnt'] }}
          </div>
        </div>
      </div>
      {% if i % 3 == 2 or i == posts|length - 1 %}
    </div>
    {% endif %}
    {% endfor %}
  </div>
  <div class="user_post_bookmarks">
    {% for i in range(bookmark_posts|length) %}
    {% if i % 3 == 0 %}
    <div class="user_post_row">
      {% endif %}
      <div class="user_post_img_box">
        <img width="100%" src="data:image/jpg;base64, {{ bookmark_images[i] }}"/>
        <div class="user_post_info_box">
          <div class="user_post_like_box">
            <i class="fa-solid fa-heart"></i>
            {{ bookmark_posts[i]['LikeCnt'] }}
          </div>
          <div class="user_post_comment_box">
            <i class="fa-solid fa-comment"></i>
            {{ bookmark_posts[i]['CommentCnt'] }}
          </div>
        </div>
      </div>
      {% if i % 3 == 2 or i == bookmark_posts|length - 1 %}
    </div>
    {% endif %}
    {% endfor %}
  </div>
</div>

: user_post_users와 user_post_bookmarks 부분은 같은 form이지만 따로 작성해야했다.

물론 이러한 방법은 jinja2의 올바른 방법은 아니라고 생각한다. jinja2의 장점은 이러한 동적인 정보보다 로딩시 고정되는 정보들 (가령 위와 같은 유저페이지의 유저프로필부분, 이부분은 게시물 종류와 상관없이 유저페이지 로딩시 상단에 고정된다.)에서는 매우 빠르고 간편한 장점이 있을 것이라고 생각한다. 이번 경우에는 다른 기능들에서 이미 ajax 콜해야하는 부분이 많았기 때문에 처음 jinja2를 사용해보았다는 것이 의미를 두고 사용했다.

4. 프로젝트 정보

1) github
https://github.com/ai-web-9-team/59stargram

2) notion workspace
https://www.notion.so/kimphysicsman/7db33adca12b403a8a19df5ccce01b70

profile
kimphysicsman

0개의 댓글