WeBucks 프로젝트 회고

luneah·2021년 12월 9일
0

Webucks Project

목록 보기
10/10
post-thumbnail

✦ 첫 미니 프로젝트 WeBucks 회고

장장 2주간에 걸친 대망의 첫 프로젝트가 드디어 끝이 났다. 리액트에 입문하며 HTML과 자바스크립트로 구현할 때가 좋았다며 동기들과 얘기를 나누던 게 엊그제 같은데 벌써 리액트로도 척척 구현해내는 내 모습을 보며 새삼스럽게 사람이 짧은 시간에 이렇게나 성장할 수도 있구나 하는 걸 느낀 2주였다. 리액트의 강렬했던 그 첫 인상과 이번 프로젝트를 하며 기억하고 가져가고 싶은 코드들을 남기려 회고를 작성한다.


🔖 [JS] 기억에 남는 코드

  1. 로그인 페이지 기능 구현

    active 라는 클래스에 버튼의 색을 바꿔주는 css 속성이 있는데 이를 조건에 따라 추가해주는 방법을 여기서 처음 알게 되었다. 또한 조건에 맞게 입력했다 지웠을 때도 버튼이 활성화 상태인 오류가 생겨 이를 해결하는 방법에 대해 많이 찾아봤었는데 null 값을 주면 실행되지 않는다는 것을 보고 해결했다!

loginBox.onkeyup = function () {
    let userId = document.querySelector('.id').value;
    let userPw = document.querySelector('.pw').value;
    ((userId.includes('@')) && (userPw.length >= 8))
  // 아이디와 비밀번호가 조건에 맞을 때 : active라는 클래스를 추가해주고 moveList라는 함수가 실행됨
    ? (loginBtn.classList.add('active'), loginBtn.onclick = moveList)
  // 조건에 맞지 않을 경우 : active라는 클래스를 삭제해주고 onclick 이벤트를 null로 주어 실행되지 않게 함
    : (loginBtn.classList.remove('active'), loginBtn.onclick=null);
};
  1. 댓글 기능 구현

    댓글을 추가하는 부분에서 애를 먹었던 기억이 있다. 기존에 있는 댓글이 아니라 새로 생성되는 부분이라 다른 방식으로 구현해야 하는데 잘 모르겠어서 검색을 많이 했다. createElement로 새로운 html 요소를 생성해줄 수 있고 innerHTML/Text로 해당 값에 할당해줄 수 있다는 점을 알게 되었다. 또 appendChild를 써서 자식 요소로 추가해주어 댓글이 생성되게끔 만들어줄 수 있다는 것을 배웠다. 머리로 생각하는 것보다 댓글에 대한 틀을 손으로 먼저 그려보고 이에 따라서 코드를 짜니 더욱 쉽게 완성할 수 있었다.

const commentInput = document.querySelector('.comment');

function uploadComment() {  
    const box = document.querySelector(".writeComment"); // 댓글 전체 요소를 감싸는 박스 생성

    // 댓글 요소 생성
    const comments = document.createElement("div");
    const userId = document.createElement("span");
    const review = document.createElement("span");

    // 해당 댓글 요소가 나타낼 것 html에서 선택
    comments.classList.add("writeComment")
    userId.classList.add("userId");
    review.classList.add("text");
 
    userId.innerHTML = "luneah ";   // userId 지정하여 댓글 달면 ID 칸에 뜨게 함
    review.innerText = commentInput.value;  // input에 들어온 값 불러옴

    // appendChild 속성으로 자식 요소로 추가해줌
    comments.appendChild(userId);
    comments.appendChild(review);
    box.appendChild(comments);
}
  1. 비밀번호 테두리 색 변경

    비밀번호가 조건에 맞을 때 비밀번호 input의 테두리 색을 변경해줘야 하는데 비밀번호의 조건을 설정하는 방법을 몰라서 헤맸었다. 그러다 정규식 표현을 발견했고 이를 적용해 구현하려고 했으나 잘 이해가 안 된 상태에서 무작정 쓰니 해결은 커녕 오류만 생겼다. 찾아보니 사람들마다 다양한 정규식 표현을 쓰고 있었고 나에게 맞는 정규식을 구성하여 실행시키니 작동이 잘 되는 것을 확인할 수 있었다!

pwBox.onkeyup = function () {
    const userPw = document.querySelector('.pw');
    // 대소문자, 숫자, 특수문자를 포함한 8글자 이상
    const regexPw = /(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[#?!@$%^&*-]).{8,20}/;

    if (regexPw.test(userPw.value)) {
        userPw.style.borderColor = 'green';
    }
    else {
        userPw.style.borderColor = '#e3e3e3';
    }
};

🔖 [React] 기억에 남는 코드

  1. mock 데이터 사용해 리스트 페이지 구현

    CoffeeCard 라는 컴포넌트와 mock 데이터를 만들어 fetch 함수를 통해 호출하고 map을 통해 나타나게 만들어주는 부분이다. useState의 역할, fetch 함수의 사용법, 첫 번째와 두 번째 res의 차이점, 조건부 렌더링 등 이 코드 안에서 배운 것이 참 많다. 덕분에 다른 코드들도 어렵지 않게 짤 수 있었던 것 같다!

import CoffeeCard from '../components/CoffeeCard';

function List() {
   const [mockdata, setMockData] = useState([]);

   useEffect(() => {
    fetch("http://localhost:3000/data/data.json")
      .then((res) => res.json())
      .then((res) => setMockData(res));
  }, []);

	<ul className="coffee-list">
          {mockdata.cold && mockdata.cold.map((e, i) => {
            return <CoffeeCard key={id} item={e} />;
          })}
        </ul>
}
  1. 좋아요 기능 구현

    단순하지만 처음엔 아이콘을 불러오질 못해서 한참 고민했었다. 그러던 중 생각난 것은 font awesome 을 불러오려면 스크립트가 있어야 한다는 것... 미처 생각 못하고 있었던 부분이었다. 자바스크립트로 구현할 때와 마찬가지로 html 에 스크립트를 붙여넣기 해주었더니 정상적으로 잘 작동했다. 그리고 isLike 의 값을 Boolean 값으로 사용한 것은 잘 짠 로직인 것 같다!

function Deatil() {

  const [isLike, setIsLike] = useState(false);

  return (
    <div className="detail-page__content-title">
       <i
         className={isLike ? 'fas fa-heart' : 'far fa-heart'}
         id="detail-page__content-heart"
         onClick={() => setIsLike(!isLike)}>
       </i>
    </div>
  )
}
  1. 댓글 기능 구현

    리뷰의 댓글 부분도 따로 컴포넌트를 만들어주어 넣으면 좋겠다고 생각하여 작성하였는데 기존에 있던 댓글들에 문제가 발생했다. 맨 위에 댓글에만 좋아요 기능이 적용된다던지 좋아요가 다 동시에 눌린다던지... 처음에는 각각의 댓글에 클래스 명을 다르게 하여 함수를 세 개를 따로 적용했었다. 그런데 너무 비효율적인 방법이라 다른 좋은 방법이 없을까 생각해보던 와중 mock 데이터를 활용하여 map을 시켜주는 방법이 생각났다. 위의 방법으로 코드를 다시 구현하니 오류 없이 모두 다 잘 작동하는 것을 볼 수 있었다. 그리고 리뷰를 작성하는 아이디는 로그인하는 사람에 따라 계속 변하게 되므로 로그인 아이디가 바뀔 때 그 값을 세션 스토리지에 저장해뒀다가 디테일 페이지에서 댓글을 작성할 때 불러올 수 있게끔 구현해줬더니 훨씬 보기 좋았다!

function ReviewComment(props) {

   const [heart, setHeart] = useState(false);

   return (
       <div className="nutrition-info__review-comment__inner">
          <div className="commentText">
             <span>{props.user ? props.user : (sessionStorage.getItem("id"))}</span>: {props.text}
          </div>
          <i
             className={heart === true ? 'fas fa-heart fheart' : 'far fa-heart'}>
          </i>
          <i className="fas fa-trash"></i>
       </div>
    );
}

export default ReviewComment;

💬 회고를 마치며

사실 자바스크립트로 구현했던 프로젝트를 리액트로 옮기는 단계부터가 고난이었다. 리액트는 html 페이지가 하나뿐이라 이때까지 html로 구현했던 로그인, 리스트, 디테일 페이지를 모두 js 파일로 만들어줘야 했고 css는 Sass를 이용해서 네스팅을 해줘야 했다. 결과는 처참했다... 이럴거면 코드를 처음부터 다시 짜는 게 낫겠다 싶은 생각이 들어서 자바스크립트로 구현할 때 아쉬운 점이 많았던 리스트 페이지와 디테일 페이지를 처음부터 다시 만들었다. 처음 작성했을 땐 지저분하게 구현한 부분이 많았는데 새로 작성할 땐 훨씬 깔끔하고 직관적으로 작성하려고 노력했다. 덕분에 네스팅 할 부분도 적어지고 훨씬 효율적인 코드가 되었다! 코드 리뷰를 거치며 더욱 완성도를 높이고 좋은 코드란 무엇인가에 고민해보는 시간을 가지기도 했다.

2주간의 WeBucks 프로젝트를 통해 기존에 알고 있던 HTML과 CSS, 그리고 새로 배운 React를 단순히 개념만 아는 것이 아니라 이를 활용하는 방법에 대해서도 확실히 알 수 있었던 좋은 기회였던 것 같다. 리액트를 배운 지 2주가 채 되지 않은 시점이지만 꽤나 많은 양의 내용을 알게 된 것 같다. 처음 시작해서 하나도 몰라서 어버버 하던 게 엊그제 같은데 이젠 동기들에게 왜 그렇게 써야 하는지 작동 원리에 대해서도 설명해줄 수 있는 멋진 코린이가 되었다.

첫 프로젝트를 무사히 끝낸 나에게 칭찬의 박수를 보내며 앞으로의 프로젝트에서도 꾸준히 배울 점을 찾고 발전하는 내가 되길 바란다!!

profile
하늘이의 개발 일기

0개의 댓글