WEB/JAVASCRIPT

[JS] westagram - 댓글 게시 기능 구현

heeney 2021. 12. 12. 22:06
728x90

 

[JS] westagram - 댓글 게시 기능 구현

메인 페이지 내에서 피드에 댓글을 다는 기능을 구현하였다.
쉽게 말해서 해당 댓글 게시 기능은 사용자가 입력한 input값을 담은 요소가 새로 생성되는 것이다.

 


 

Check List ✅

  1. 사용자가 원하는 내용의 댓글을 입력할 수 있도록 input 요소가 있어야 한다. => input ❌, textarea ⭕️
    input으로 구성하려던 도중 인스타그램의 경우 textarea로 구성되어 있었다. 생각해보니 사용자가 정말 긴 내용을 코멘트로 달 수도 있었다. 실제로 인스타그램에서는 많은 양의 내용을 담은 코멘트를 다는 사용자도 있으니 필요한 부분이었다.
  2. 사용자가 댓글을 입력을 할 때에만 게시 버튼이 활성화 되어야 한다.
    keyup 이벤트를 줘서 사용자가 입력하면 게시 버튼을 바로 활성화 시켜준다.
  3. 사용자가 게시 버튼을 누르면 댓글이 바로 생성되어야 한다.
  4. 사용자가 게시 버튼을 누르지 않고 Enter 키를 누를 수도 있으므로 해당 이벤트도 함께 포함시킨다.

 

 

구현한 모습 🎁

 

좌우 스크롤로 유저들의 스토리를 확인할 수 있다.
게시 버튼 활성화 및 댓글 기능 구현

 

 

작성한 코드 ⚙️

 

HTML
<body>
    <div id="container">
        <header class="main_header">
            <div class="header_content">
                <h1 id="logo">westagram</h1>
                <section class="search_wrap">
                    <i class="fas fa-search fa-xs"></i>
                    <input type="text" placeholder="검색">
                </section>
                <nav>
                    <div class="nav_content">
                        <ul>
                            <li>
                                <a href="#"><i class="fas fa-home fa-lg"></i></a>
                            </li>
                            <li>
                                <a href="#"><i class="far fa-paper-plane fa-lg"></i></a>
                            </li>
                            <li>
                                <a href="#"><i class="far fa-plus-square fa-lg"></i></a>
                            </li>
                            <li>
                                <a href="#"><i class="far fa-compass fa-lg"></i></a>
                            </li>
                            <li>
                                <a href="#"><i class="far fa-heart fa-lg"></i></a>
                            </li>
                            <li class="header_my_profile">
                                <a href="#"><img 
                                src="https://images.unsplash.com/photo-1617198420518-e2b79c2cdbb2?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1064&q=80" 
                                alt="my profile img"></a>
                            </li>
                        </ul>
                    </div>
                </nav>
            </div>
        </header>
        <main>
            <div class="main_wrap">
                <section class="feed_wrap">
                    <div class="users_story">
                        <div class="users_story_content">
                            <div>
                                <div class="arrows">
                                    <i class="fas fa-chevron-left"></i>
                                    <i class="fas fa-chevron-right"></i>
                                </div>
                                <ul class="story">
                                    <li>
                                        <div><img class="circle_profile_img" src="" alt="story_user_profile_img"></div>
                                        <em>kangheewon</em>
                                    </li>
                                    <li>
                                        <div><img class="circle_profile_img" src="" alt="story_user_profile_img"></div>
                                        <em>kangminhee</em>
                                    </li>
                                    <li>
                                        <div><img class="circle_profile_img" src="" alt="story_user_profile_img"></div>
                                        <em>dlwlrma_</em>
                                    </li>
                                    <li>
                                        <div><img class="circle_profile_img" src="" alt="story_user_profile_img"></div>
                                        <em>dlwlrma_</em>
                                    </li>
                                    <li>
                                        <div><img class="circle_profile_img" src="" alt="story_user_profile_img"></div>
                                        <em>dlwlrma_</em>
                                    </li>
                                    <li>
                                        <div><img class="circle_profile_img" src="" alt="story_user_profile_img"></div>
                                        <em>dlwlrma_</em>
                                    </li>
                                    <li>
                                        <div><img class="circle_profile_img" src="" alt=""></div>
                                        <em>dlwlrma_</em>
                                    </li>
                                    <li>
                                        <div><img class="circle_profile_img" src="" alt="story_user_profile_img"></div>
                                        <em>dlwlrma_</em>
                                    </li>
                                    <li>
                                        <div><img class="circle_profile_img" src="" alt="story_user_profile_img"></div>
                                        <em>dlwlrma_</em>
                                    </li>
                                    <li>
                                        <div><img class="circle_profile_img" src="" alt="story_user_profile_img"></div>
                                        <em>dlwlrma_</em>
                                    </li>
                                </ul>
                            </div>
                        </div>
                    </div>
                    <section class="users_feed_list">
                        <article class="user_feed">
                            <header>
                                <section class="user_profile">
                                    <div><img src="https://images.unsplash.com/photo-1617198420518-e2b79c2cdbb2?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1064&q=80"
                                            alt="user profile img"></div>
                                    <em>kangheewon</em>
                                </section>
                                <i class="feed_handler fas fa-ellipsis-h fa-1x"></i>
                            </header>
                            <ul class="feed_imgs">
                                <li><img src="https://images.unsplash.com/photo-1633113212875-8ecf30ad2e81?ixlib=rb-1.2.1&ixid=MnwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=987&q=80" alt="feed_img1"></li>
                            </ul>
                            <ul class="feed_img_dots">
                                <li></li>
                                <li class="active_feed_dots"></li>
                            </ul>
                            <section class="feed_reaction">
                                <span><i class="far fa-heart fa-2x"></i></span>
                                <span><i class="far fa-comment fa-2x"></i></span>
                                <span><i class="far fa-paper-plane fa-2x"></i></span>
                                <span><i class="far fa-bookmark fa-2x"></i></span>
                            </section>
                            <a href="#" class="like_people">좋아요 <em>12,020개</em></a>
                            <section class="feed_desc_wrap">
                                <div class="user_desc">
                                    <em>kangheewon</em>
                                    <span>hello world 🌏</span>
                                </div>
                                <a href="#" class="more_comment">댓글 <b>120개</b> 모두 보기</a>
                                <ul class="comment_list">
                                    <li>
                                        <div class="user_desc">
                                            <em>dlwlrmaa</em>
                                            <span>우와 멋지다!!</span>
                                        </div>
                                        <button><i class="far fa-heart fa-xs"></i></button>
                                    </li>
                                    <li>
                                        <div class="user_desc">
                                            <em>taeyeon_ss_</em>
                                            <span>✨</span>
                                        </div>
                                            <button><i class="far fa-heart fa-xs"></i></button>
                                    </li>
                                </ul>
                                <time class="before_post">1일 전</time>
                            </section>
                            <section class="post_comment_wrap">
                                <button class="emoji"><i class="far fa-smile fa-2x"></i></button>
                                <input id="post_comment_input" type="text" placeholder="댓글 달기..." />
                                <button class="post_comment_btn">게시</button>
                            </section>
                        </article>
                    </section>
                </section>
                <aside class="recommend_aside">
                    <div id="my_profile">
                        <div class="profile_img">
                            <img src="https://images.unsplash.com/photo-1617198420518-e2b79c2cdbb2?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1064&q=80"
                                alt="user profile img">
                        </div>
                        <div class="my_info">
                            <em>kangheewon</em>
                            <span class="my_desc">후론트라라라 👩🏻‍💻</span>
                        </div>
                        <button class="my_transform">전환</button>
                    </div>
                    <section class="recommend_me">
                        <div class="title">
                            <h4>회원님을 위한 추천</h4>
                            <button>모두 보기</button>
                        </div>
                        <ul class="users_list">
                            <li>
                                <div class="recommend_user_img">
                                    <img class="circle_profile_img" src="" alt="recommend_user_profile_img">
                                </div>
                                <div class="recommend_user_title">
                                    <em>allabout_jungmin</em>
                                    <span class="recommand_desc">회원님을 위한 추천</span>
                                </div>
                                <button>팔로우</button>
                            </li>
                            <li>
                                <div class="recommend_user_img">
                                    <img class="circle_profile_img" src="" alt="recommend_user_profile_img">
                                </div>
                                <div class="recommend_user_title">
                                    <em>memo04.50</em>
                                    <span class="recommand_desc">dlwlrma님 외 1명이 팔로우합니다</span>
                                </div>
                                <button>팔로우</button>
                            </li>
                            <li>
                                <div class="recommend_user_img">
                                    <img class="circle_profile_img" src="" alt="recommend_user_profile_img">
                                </div>
                                <div class="recommend_user_title">
                                    <em>meaning_0</em>
                                    <span class="recommand_desc">adulkid님 외 1명이 팔로우합니다</span>
                                </div>
                                <button>팔로우</button>
                            </li>
                            <li>
                                <div class="recommend_user_img">
                                    <img class="circle_profile_img" src="" alt="recommend_user_profile_img">
                                </div>
                                <div class="recommend_user_title">
                                    <em>iilihelloili</em>
                                    <span class="recommand_desc">WEstagram 신규 가입</span>
                                </div>
                                <button>팔로우</button>
                            </li>
                        </ul>
                    </section>
                    <footer>
                        <div class="footer_link_list">
                            <a href="#">소개</a>
                            <a href="#">도움말</a>
                            <a href="#">홍보 센터</a>
                            <a href="#">API</a>
                            <a href="#">채용 정보</a>
                            <a href="#">개인정보처리방침</a>
                            <a href="#">약관</a>
                            <a href="#">위치</a>
                            <a href="#">인기 계정</a>
                            <a href="#">해시태그</a>
                            <a href="#">언어</a>
                        </div>
                        <address>© 2021 INSTAGRAM FROM META</address>
                    </footer>
                </aside>
            </div>
        </main>
    </div>
    <script src="./js/main.js"></script>
</body>

 

 

JS
'use strict';

const postCommentInFeed = () => {
  const commentInput = document.getElementById('post_comment_input');
  const commentPostBtn = document.getElementsByClassName('post_comment_btn')[0];

  // 댓글 입력시 요소 생성
  const addNewComment = () => {
    const newCommentLocation = document.getElementsByClassName('comment_list')[0];
    const newComment = document.createElement('li');

    newComment.innerHTML = `
      <div class="user_desc">
        <em>iAmUser</em>
        <span>${commentInput.value}</span>
      </div>
      <button><i class="far fa-heart fa-xs"></i></button>
    `;

    newCommentLocation.appendChild(newComment);
    commentInput.value = '';
  }


  // 사용자 입력 들어올 시, 게시 버튼 활성화
  commentInput.addEventListener('keyup', () => {
    commentInput.value ? commentPostBtn.style.opacity = '1' : commentPostBtn.style.opacity = '.3';
    if (window.event.keyCode === 13 && commentInput.value) {
      addNewComment();
    }
  });

  // 댓글 게시
  commentPostBtn.addEventListener('click', () => {
    if (commentInput.value) {
      addNewComment();
    } else {
      alert('댓글이 입력되지 않았습니다 😳');
    }
  })
}


postCommentInFeed();

 

Process 🤖

댓글 게시

  1. 댓글 입력 시에 해당 input의 value를 담은 새로운 요소가 댓글 리스트 가장 맨 밑에 추가되어야 하므로 addNewComment라는 함수를 만들어 내용을 추가한다.
    새로운 댓글(li)이 ul 부모 안에 가장 맨 밑에 새롭게 추가되어야 하므로 부모 ul 태그를 DOM으로 접근하여 변수에 담아주고 li 태그를 createElement 메소드로 만든다.
  2. 안에 해당 요소가 많으므로 innerHTML로 댓글을 구성하는데 필요한 요소들을 모두 불러온다.
    그 중 유저의 아이디는 우선 임의로 설정해두고, 유저가 input에 입력한 값을 불러와서 보여주기 위해 ${commentInput.value}로 보여줄 수 있도록 한다.
  3. 필요한 모든 요소를 담은 li태그를 ul 부모 안에 붙여준다.
    그러면 해당 함수는 이제 어떤 이벤트로 인해 동작하게 되면 ul 부모 안에 사용자가 input에 입력한 값을 담은 댓글 요소(li)가 가장 맨 밑에 생성되게 되는 것이다.
  4. 그러면 이제 댓글이 생성되는 과정이 끝난거다. 사용자가 원하는 댓글이 모두 생성되었다면 입력한 input의 값은 사라져야 하므로 commentInput.value = ''로 빈 값을 만들어준다.
  5. keyup 이벤트가 실행되면 댓글을 게시할 준비가 되었다는 뜻이다. 이 때 사용자의 댓글 값이 존재하고 그런 상태에서 Enter키를 누르면 addNewComment 함수가 실행되도록 한다.
  6. 댓글이 생성된다.

 

게시 버튼 활성화

  1. 게시 버튼을 누르면 이벤트가 실행된다.
  2. 만약 input에 사용자가 입력한 값이 존재하는 상태에서 게시 버튼을 클릭 하였다면 addNewComment 함수가 실행된다.
  3. 댓글이 생성된다.

 

 

해결하고 싶다... 구현하고 싶다... 🤔

textarea를 적용시키고 자동으로 height가 resizing 되는거까진 해봤는데 이상하게 바로 댓글을 입력하고 빠르게 엔터를 치면 빈 문자열의 댓글이 쌍으로 생성된다. 흐아 ^^... 리액트 들어가서 한번 더 해봐야겠는데 오기가 생긴다.. 일단 아직 이 부분은 막혀있다.

 

728x90