TIL 13 | Toy Project - Westagram

Soojeong Lee·2021년 6월 19일
0

지금까지 배운 HTML, CSS, Javascript로 구현한 Instagram Clone

Instagram Clone 토이 프로젝트를 시작하면서, 나는 개인적인 목표를 세워서 프로젝트를 시작했다.

  1. HTML - Semantic Tag 사용하여 마크업 하기, 접근성 고려하기
  2. CSS - 중복으로 사용되는 속성 최대한 줄이기, display : flex ; 사용하기
  3. Java script - 필수 기능만 구현하되 깔끔한 코드 작성하기

먼저 프로젝트에서 필요한 페이지는 로그인페이지와 메인페이지였다.

1. 로그인 페이지

HTML

먼저, HTML은 심플하되 시맨틱하게 작성하는 것이 목표였다.

<main class="loginWrapper">
    <header>
      <h1>Westagram</h1>
    </header>
    
    <section class="loginInputBox">
      <h2 class="sr-only">login page</h2>
      <form action="">
        <input type="text" id="loginId" placeholder="전화번호, 사용자 이름 또는 이메일" />
        <input type="password" id="loginPw" placeholder="비밀번호" />
        <button type="button" class="loginBtn">로그인</button>
      </form>
    </section>
    
    <footer>
      <a class="findPassword" href="#">비밀번호를 잊으셨나요?</a>
    </footer>
  </main>

✔️ main을 header, section, footer 부분으로 나누어서 태그를 작성하였다. 처음엔 main을 div로 잡았는데, main도 활용하면 구조상 더 의미가 잘 전달될 것 같아 main으로 구현하였다.

✔️ 이때, section에는 heading 태그가 필수적이지만, 실제 보여지는 페이지에서는 구현할 필요가 없어서 sr-only라는 속성을 따로 common에 부여하여 스크린 리더기엔 작동하되, 시각적으로는 보이지 않도록 구현하였다.

2. CSS

✔️ 작성된 모든 스타일을 적을 순 없지만, 모든 정렬은 display: flex;로 구현하였다. 기존에 손에 익었던 float을 통한 정렬도 좋지만, display: flex;을 통해 명확하고 자유롭게 레이아웃을 구현하고자했다.

✔️ 사진에선 확인되지 않지만 html, body에도 display: flex;을 적용시켜서 center 배치를 하였다. 이렇게 스타일을 부여하면 반응형에도 적합한 스타일이라고 생각했다.

3. Javascript

사실 개인적으로 Javascript 문법에 대한 지식이 부족하다고 느껴져서 ID, PW 입력 시 로그인 버튼 활성화 기능을 구현할 수 있을까 막막했다. 그래도 일주일 간 Javascript와 친해지려고 노력했던 덕분인지, 이전에는 '어떻게 문제를 풀어야지?'라는 생각이 들었다면 이번 프로젝트에서는 '어떻게 풀어야겠다!'하는 생각이 들기 시작했다...! (하지만 생각한대로 출력되지 않아서 힘든 시간을 보냈다.😇)

✨ 그 결과 구현해낸 코드

// 로그인 버튼 활성화
addEventListener( 'keyup', () => {
  let loginId = document.getElementById('loginId').value; 
  const loginPw = document.getElementById('loginPw').value;
  const loginBtn = document.getElementsByClassName('loginBtn')[0];

  const loginBtnColor = loginBtn.style; 
  
  return (loginId !=="") && (loginPw !=="") ? loginBtnColor.backgroundColor = "#0096f6" : loginBtnColor.backgroundColor = "#C0DFFD"; 
});

✔️ 먼저, 기능을 구현하되 함수를 화살표 함수로 바꿔주는 것과 if 조건문을 삼항 조건 연산자로 적용될 수 있도록 하였다.

✔️ 처음에 문제를 푸는 방법은 바로 떠올랐지만 풀어내지 못한 이유는, loginId, loginPw를 value값을 받는 변수로 정의해야하는데, value값을 적어두지 않은 탓에 결과가 도출되지 않았었다. 꼭 출력하고자 하는 것이 무엇인지 명확하게 확인 후 선언하는 것이 중요하다는 것을 배웠다.

✔️ 최초에는 return 값의 조건을 (loginId !==0), (loginPw !==0)이라고 선언했었다. 하지만 falsy, truthy에 대한 명확한 이해가 부족해서 였다.

➡️ truthy : true, 1
➡️ falsy : false, 0, "", null, undefined, NaN

나는 ID, PW input에 입력된 값이 있다면 출력될 수 있도록 기능을 구현하고 싶어서 그와 반대인, 입력된 값이 없다면을 조건으로 세우려고 했다. 하지만 여기서 엄청난 오류가 있었다..! (loginId !==0)는 값이 0일 뿐
""은 null이 아니고, NaN undefined가 아니었던 것이다. 그래서 값이 있을 때와 없을 때로 구분해야하기 때문에 0 대신 ""를 사용하여 기능을 구현하였다.

✔️ 마지막으로 스타일 속성을 주기 위해서 중복되는 부분인 loginBtn.style.backgroundColor;를 loginBtnColor로 변수화 하였더니 색상 변경이 적용되지 않았다. 로직 상으로 불가능하지 않은데 왜그럴까하고 멘토님과 이야기해보니, loginBtn.style.backgroundColor; 자체를 변수화해서 출력되는 것은 스트링이 었을 뿐 backgroundColor; 의 속성을 적용할 수 없었던 것이다...! WoW 그래서 loginBtn.style까지만 변수로 담아주었다.

(⬇️) 아래는 HTML, CSS, Javascript로 구현한 페이지이다.

추가적인 기능은 부여하지 못했지만, 더욱 여력을 쏟자면 validation 검사 관련한 코드를 보고 적용시켜야겠다는 생각이 들었다. 대부분의 페이지에서는 validation을 걸고 있다. 다른 기능과 함께 추후 꼭 적용시킬 기능이다. ✨

2. 메인 페이지

1. HTML

✔️ 레이아웃은 크게 nav, main으로 잡고 메인에서 article과 aside로 구역을 나누었다.

레이아웃을 나눌 때, 1) main 아래 div로 article, aside구획을 잡을 것인가 2) div안에 article과 aside로 구획을 잡을 것인가 고민이 되었다.
➡️ article을 게시글이라고 생각했을 때, 여러 개의 article이 올 수 있으니, 이를 하나로 묶어주는 div가 결국 필요할 것이라고 생각이 들어 2)안으로 진행하기로 결정했다.

✔️ userProfile(Image-Text 구조)가 반복되어 사용되기 때문에 동일한 태그를 작성해서 추후 CSS를 적용할 때 같은 class 네임으로 스타일을 줄 수 있도록 작성하였다.

2. CSS

✔️ flex로 레이아웃을 잡아서 반응형으로 구현해도 크게 흔들리지 않도록 스타일을 주었다.

✔️ 또 피드를 보면, 하나의 아이콘만 우측 배열이 되어있다. 하지만 heart, comment, share, bookmark 모두 형제요소여서 flex배치를 할 때 방법이 떠오르지 않았다. 배치를 위해서 html 태그를 추가하고 싶지 않았기 때문이다...! 하지만 html 태그를 사용하지 않으면 float 속성을 써야하는 번거로움이 있었기 때문에, html 태그를 추가하는 방법으로 진행하였다.

✔️ footList의 경우 가상요소를 사용해서 list 뒤, 자동으로 dot이 올 수 있도록 처리하였다. 맨 마지막 list의 경우에는 가상요소의 컨텐츠에 ''속성을 주어 보이지 않도록 처리하였다.

 .main-right footer .footList li::after{
  content: '·';
  margin: 5px;
}

.main-right footer .footList li:last-child:after {
  content: '';
}

3. Javascript

메인 페이지의 주된 기능은 댓글 구현 기능이다. 먼저 댓글 기능을 구현하기 위해서 어떻게 해야할까 생각을 하였다. 도출해낸 결론은 input에 담은 value를 list tag에 출력될 수 있도록 하자는 것 이었다.

<footer>
  <div class="inputBox">
    <input id="userComment" class="comment" type="text" placeholder="댓글 달기..." >
    <button class="commentSubmit" type="submit">게시</button>
    </div>
</footer>
const commentBox = document.getElementById('commnetBox');
const submitButton = document.getElementsByClassName('commentSubmit')[0];
const InputEnter = document.getElementById('userComment');

// Click 
submitButton.addEventListener('click', function addCommnetClick() {
  const addList = document.createElement('li');
  const addComment = document.getElementById('userComment').value;

  addList.innerHTML = `<span class="commentUserId">eessoo__</span>${addComment}`; 
  commentBox.appendChild(addList);
});

1) 먼저, 기능이 필요한 tag를 DOM으로 접근하여 변수에 담아주었다.
2) click이라는 event가 발생했을 때, 기능이 작동되도록 함수를 정의하였다.
3) 진행되는 기능은 li를 생성하고 생성된 li에 input value를 넣어주는 것이다.

✔️ 처음 내가했던 실수는 addEventListener 앞에 어떤 대상을 타겟으로 이벤트를 적용해야하는가에 대해서 적어줘야하는데, 그 개념 자체를 놓쳐서 addEventListener('click', function addCommnetClick() {} 로 구문을 실행하고 있었다.. console.log로 출력해 보니 윈도우 전체가 이벤트를 갖고 있게 되었다는걸 발견하게 되었다.

✔️ 로직을 구현하고 적용을 했지만 처음엔 댓글이 입력되지 않아서 동기분들과 코드를 함께 리뷰해 보니, 최초 코드에서는 const addList = document.createElement('li'); , const addComment = document.getElementById('userComment').value; 모두를 함수 밖에서 전역 변수로 선언해주어 계속 값이 담기지 않은 빈 ul만 생성하고 있었던 것이다.

✔️ console.log 로 확인을 해보니 빈 li만 추가되고 있다는 것을 발견하고 이제부터 1) console.log를 찍어보는 습관을 들일 것 2) 변수를 정의 할 때, 필요해 의해 전역 변수와 지역 변수로 나누어 정의해야 겠다는 생각을 했다. 나는 단순하게 전역 변수로 일단 넣어두면 다 적용되겠지..! 라는 짧은 생각을 했던 것이었다.

✔️ 동일한 기능을 click 이벤트 외 Enter press가 되었을 때도 진행 시켜야 했다.

InputEnter.addEventListener('keypress', function addCommentEnter(event) {
  const addList = document.createElement('li');
  const addComment = document.getElementById('userComment').value; 

  if (event.code === 'Enter') {
    addList.innerHTML = `<span class="commentUserId">eessoo__</span>${addComment}`; 
    commentBox.appendChild(addList);
  }

});
  • evnet가 적용될 key : Enter 이기 때문에 해당 키에만 적용 될 수 있도록 if 조건 문을 사용해서 제한을 걸어 주었다. 이때 나는 evetn.code 자체가 property인지 몰라서 뱅뱅 해맸었다. 이 역시도 console.log를 출력해보니 여러개의 코드가 나왔었다.

  • 기존에 사용하려고 했던 keyup 이벤트를 적용하니, 댓글이 두개씩 달리는 문제가 발생하였다. 이를 방지하기위해 우선 keypress를 사용했지만, 하지만 내가 적용한 keypress 가 MDN에선추천하지 않는 이벤트라고 한다. 다른 방법이 있는지 확인해봐야겠다.

3. 프로젝트를 마치며

프로젝트를 마치며 2주간의 시간을 되돌아 보았다. 레이아웃과 스타일적인 요소는 내가 늘 흥미가 있던 부분이라 즐겁게 마쳤다. 하지만 구현한 것들에 기능을 입히는 요소는 아직도 어려운 단계이다. 기능을 구현하면서 Javascript의 기초적인 문법적인 개념이 많이 부족하다는 생각이 들었다. 앞으로 진행하게될 react를 위해서 부던하게 Javascript 문법을 다져야겠다.

profile
🍼 newbie frontend developer

0개의 댓글