코드스테이츠_4주차_목, 금

윤뿔소·2022년 9월 15일
0

CodeStates

목록 보기
15/47

목, 금은 Git을 배우고 솔로프로젝트로 나만의 아고라 스테이츠를 만들어 배포해보는 시간을 가져본다!

Git

  • 일반 디렉터리와 깃 리포지토리와의 차이점에 대해 설명
  • git staging area에 대해서 설명
  • git add로 git staging area의 내용을 변경
  • git add와 git commit의 차이점에 대해서 설명
  • git commit으로 로컬 깃 리포지토리에 코드 변경점을 기록
  • 로컬 깃 리포지토리와 원격 깃 리포지토리 github 차이점에 대해 설명
  • git clone이 원격 깃 리포지토리를 가져온다는 것을 이해
  • git pull과 git push에 대해서 이해
  • git pull과 git push로 로컬 깃 리포지터리와 원격 깃 리포지토리의 내용을 쉽게 주고받을 수 있음

Unit8에서 했듯이 Git은 분산형 버전 관리 시스템임, 깃헙의 리모트 리포지토리와 컴터의 로컬 리포지토리가 있음!

로컬 깃 저장소 다루기

과정

  1. git init: 해당 디렉토리에 로컬 Git repository를 생성, 개발
  2. git add: 코드를 작성하고 저장하는 공간, 작업 공간(work space)의 파일 및 디렉토리를 git의 관리 하에 있는 상태로 올려줄 수 있음, 이 영역이 staging area
  3. git status: 커밋하기 전 staging area의 상태를 확인
    • 커밋 조건 1. 같은 용도 물건(코드파일)을 하나의 무빙박스(SA)에 넣기
    • 커밋 조건 2. 무빙 박스의 내용물에 대한 간단한 라벨링
  4. git commit -m "commit message": 라벨링, 커밋 메세지 - 코드의 용도 저장 ex) git commit -m "나만의 아고라스테이츠 html, css 완성"
    • git commit: staging area의 파일은 commit이 가능, commit으로 local Git repository에 내 코드를 기록, staging area의 코드 묶음을 저장

추가: git add

staging area : 커밋하기 전 내용을 기록하는 장소, 코드가 작성된 파일들을 모아둬 그 코드를 하나로 모아두는 과정을 거쳐 그 공간을 뜻함, 온전히 저장하고 싶은 코드를 모아놓은 묶음
git add 경로-파일명: 그 파일을 staging area로 추가, .은 현재 경로를 뜻하므로 그 경로의 모든 파일을 추가하는 것임

추가: 커밋 원칙

  1. commit은 작은 단위로 자주 하는게 좋음 GIt commit 기록이 상세하게 되어있으면 아래와 같은 장점이 있음
    • 코드를 잘못 적은 경우에, 이전 기록을 더 쉽게 복원
    • 누가 해당 코드를 수정했는지 쉽게 파악
    • 향후 학습할 merge, rebase등 기능에 날개를 달아주는 기반
  2. commit 메시지는 짧고 간결하게 사실적으로 작성, Git commit 메시지는 동료 개발자가 참고할 수 있기 때문에 짧고 간결하고 사실적이여야 함
# Good: 기능(feat) 구현을 확인 가능, 정확한 기술 용어 사용, 짧고 간결함
git commit -m "feat: 인스타 게시글 조회 페이지네이션"
# Bad: 커밋 타입 구분 X, 만연체, 사실 여부를 판단하기 어려운 "효율성"에 대한 코멘트
git commit -m "더 효율적인 인스타 게시글 조회 기능 구현함"
# Very Bad: 어떻게 나은 형식인지 판단하기 어려움, 어떤 기능인지 확인이 어려움
git commit -m "좀 더 나은 형식"

예시 : 사진이 깨질 때

  1. Git 리포지토리의 현재 상태 확인
    git status
  2. 사진 파일만 모아서 add
    git add code.svg eat.svg repeat.svg sleep.svg
  3. 커밋
    git commit -m "feat: 각 버튼에 맞는 사진 첨부"
  4. 사진 파일만 모아서 add
    git add README.md
  5. 커밋
    git commit -m "docs: README.md 작성"

원격(리모트) 깃 저장소 다루기

원격 깃 저장소를 모아놓은 곳은 깃헙!

  1. Github에서 원격 리포지토리를 생성
    • 깃헙 리포지토리 가서 'New' 버튼을 눌러 실행, 오픈 소스인지 아닌지에 프라이빗, 퍼블릭 설정
  2. git remote add name URL: 로컬 리포지토리에 원격 리포지토리 git url을 등록, name은 원격 저장소 이름(처음은 origin을 씀), URL은 리포지토리 주소, git remote -v로 확인
  3. git push -u remote_name branch: 로컬 Git repository에 기록한 내역을 원격 Git repository에 push
    • git push -u origin main : origin이라는 원격 저장소에 로컬 리포지토리의 main파일 업데이트 함! 근데 같은 브랜치의 이름이라면 덮어쓰기 브랜치는 리포지토리의 임시 폴더? 분기? 느낌, 나중에 합쳐서 수정도 가능해 main은 나두다가 브랜치로 막 바꿀 수 있음

깃헙 레포지토리 만들면 나오는 명령문구

나머지 git clone 리포지토리주소, fork, pullrequest 등을 설명

정리

불러오기: git clone 주소, git pull name branch
커밋: git add 로컬경로, git commit -m "", git push name branch
브랜치: git branch (-v), git branch name branch_name(하위브랜치생성), git checkout (-b) name(-b: 그 위치에 생성 및 이동), git merge name,
확인: git log, git status, git remote -v(erbose) 등등
취소 및 백업: git reset HEAD(^, ~n) 등, git stash



나만의 아고라스테이츠 만들기

깃헙에서 fork 해오고 로컬로 clone해서 로컬 환경 구축하자!!

Bare Minimum Requirement

  • 디스커션 나열 기능
    • script.js를 수정하여 agoraStatesDiscussions 배열의 데이터를 나열할 수 있게 구현합니다.
  • CSS
    • 아고라 스테이츠 질문 리스트가 중앙으로 와야 합니다.
    • style.css를 수정하여 멋지고 아름답게 나만의 아고라 스테이츠를 꾸밉니다.
    • colorhunt, dribbble에서 적절한 색 조합, 디자인을 참고합니다.
  • 디스커션 추가 기능
    • script.js를 수정하여 디스커션 추가 기능을 구현합니다.
    • section.form__container 요소에 새로운 아고라 스테이츠 질문을 추가할 수 있는 입력 폼을 제작합니다. 형식은 자유입니다.
    • 아이디, 본문을 입력하고 버튼을 누르면 실제 화면에 디스커션이 추가되어야 합니다.
    • agoraStatesDiscussions 배열에 추가한 데이터가 실제 쌓여야 합니다.
  • Github Page 배포
    • Github Page 배포 기능을 이용하여 누구나 볼 수 있게 배포합니다.
  • 코드스테이츠 fe-sprint-my-agora-states 리포지토리로 Pull Request
    • 나만의 아고라 스테이츠를 코드스테이츠 깃허브에 Pull request합니다.
    • 주어진 Pull request 형식에 따라주세요.

이거 따라 만들어보는 것이다! 하면서 문제가 발생하면 기록하고, 어떻게 해결했는지의 과정을 중심으로 써보자
그리고 자주 자주 커밋하기!

컴포넌트 목업, 배치

Discussion의 컴포넌트를 만들어 각각 li에 넣어줄 것임, data.js에 데이터들이 있음

구조

보면 질문을 담을 Section 안에 Discussions 자체와 질문칸을 담을 섹션, 질문 안으로 나뉘는 구조임
그 질문칸은 ul - li 구조를 가진 리스트임

HTML

이걸 토대로 하나의 Discussion 컴포넌트의 html 목업을 해보자

<li class="discussion__container">
  <div class="discussion__avatar--wrapper">
    <img class="discussion__avatar--image"
      src="https://avatars.githubusercontent.com/u/12145019?s=64&u=5c97f25ee02d87898457e23c0e61b884241838e3&v=4"
      alt="avatar of kimploo">
  </div>
  <div class="discussion__content">
    <h2 class="discussion__title"><a href="https://github.com/codestates-seb/agora-states-fe/discussions/6">[notice] 좋은 질문하는 법</a></h2>
    <div class="discussion__information">kimploo / 2022-04-22T14:08:33Z</div>
  </div>
  <div class="discussion__answered"><p></p></div>
</li>

CSS

  1. Discussion 컴포넌트
    • 모든 요소에 border-box를 적용합니다.
    • <li> 요소의 기본 스타일인 점을 보이지 않게 합니다.
    • Discussion 컴포넌트 전체의 폭을 540px로 만드세요.
  2. 왼쪽 아바타
    • 아바타 사진을 인스타그램 프로필 사진처럼 동그랗게 표현하세요.
    • 아바타 사진의 너비를 48px로 설정하세요.
    • 아바타 사진이 Discussion 컴포넌트 높이의 중간에 오도록 정렬합니다.
  3. 중간 Discussion 콘텐츠
    • Discussion 제목과 저자, 생성일간에 간격을 충분히 줍니다.
    • 저자, 생성일을 함께 작성하고, 오른쪽 정렬하여 오른쪽에 붙입니다.
  4. 오른쪽 체크 표시
    • 체크 표시가 Discussion 컴포넌트 높이의 중간에 오도록 정렬합니다.

flex-grow를 이용해 옮겼음

JS: 데이터 연동하기

이제 컴포넌트의 구조를 만들었으니 넣을 데이터를 불러와야 할 차례
data.js에 데이터가 41개의 배열로 있음, HTML로 데이터를 보면서 코드를 작성해도되지만 41개를?!
그러므로 DOM을 이용해 추가해보자! JS 코드를 넣으면 DOM의 트리 구조로 변환해주는 사이트도 있음! 보면서 하면 더 쉽게 할 수 있음

우선 DOM + JS 조합으로 요소를 만들고 클래스 이름을 통일화하는 작업을 시작하자

연동 원리

// li 요소 생성 및 클래스 맞춰줌
const li = document.createElement("li"); 
li.className = "discussion__container"; 
// div 요소 생성 및 클래스 맞춰줌, 큰 가짓수의 div 먼저 생성
const avatarWrapper = document.createElement("div");
avatarWrapper.className = "discussion__avatar--wrapper";
const discussionContent = document.createElement("div");
discussionContent.className = "discussion__content";
const discussionAnswered = document.createElement("div");
discussionAnswered.className = "discussion__answered";
// ul
const ul = document.querySelector("ul.discussions__container");
// img 요소 제작, data.js의 배열 데이터 가져오기
const avatarImg = document.createElement("img");
avatarImg.src = agoraStatesDiscussions[0].avatarUrl;
avatarImg.alt = "avatar of " + agoraStatesDiscussions[0].author;
// HTML에 맞게 자식으로 넣어주기
avatarWrapper.append(avatarImg);
li.append(avatarWrapper, discussionContent, discussionAnswered);
ul.append(li);

이런 식으로 하면 됨. 물론 리액트가 좀 들어간 render()와 반복문을 써줘서 해야하지만 구조는 어쨌든 이럼, 이제 n을 지정해 41개의 데이터를 렌더링해보자

막힌 것

1부터 끝까지 다 설정해줘야함

  1. 트리 구조를 제대로 활용 못해 막혔었음
    • img에서 했듯 요소와 그 속성까지 모조리 data.js의 키값과 매칭해주기
    • div가 3개 있으니 나무들을 먼저 각각 하고 마지막엔 조합하기(append)
  2. 만들어줬으니 맞는 자리에 조합하기
    • 어느 내용이 어디에 들어가는지 알기, 제자리 찾아가게 하기

결과

// convertToDiscussion은 데이터를 DOM을 통해 HTML로 변환
const convertToDiscussion = (obj) => {
  // li 요소 생성 및 클래스 맞춰줌
  const li = document.createElement("li");
  li.className = "discussion__container";

  // 이미지 div 요소 생성 및 클래스 생성
  const avatarWrapper = document.createElement("div");
  avatarWrapper.className = "discussion__avatar--wrapper";
  // img 요소 제작, data.js의 배열 데이터 가져오기
  const avatarImg = document.createElement("img");
  avatarImg.className = "discussion__avatar--image";
  avatarImg.src = obj.avatarUrl;
  avatarImg.alt = "avatar of " + obj.author;
  // HTML에 맞게 자식으로 넣어주기
  avatarWrapper.append(avatarImg);

  // content 불러오기
  const discussionContent = document.createElement("div");
  discussionContent.className = "discussion__content";
  // 제목 불러오기
  const discussionTitle = document.createElement("h2");
  const titleAnchor = document.createElement("a");
  titleAnchor.href = obj.url;
  titleAnchor.textContent = obj.title;
  discussionTitle.append(titleAnchor);
  // 인포메이션 불러오기
  const discussionInfomation = document.createElement("div");
  discussionInfomation.className = "discussion__information";
  discussionInfomation.textContent = `${obj.author} / ${obj.createdAt}`;
  // 마무으리
  discussionContent.append(discussionTitle, discussionInfomation);

  // 답변 유무 불러오기
  const discussionAnswered = document.createElement("div");
  discussionAnswered.className = "discussion__answered";
  const isAnswer = document.createElement("p");
  isAnswer.textContent = obj.answer === null ? "☑" : "☒";
  discussionAnswered.append(isAnswer);
  discussionContent.append(discussionAnswered);

  // TODO: 객체 하나에 담긴 정보를 DOM에 적절히 넣어주세요.

  li.append(avatarWrapper, discussionContent, discussionAnswered);
  return li;
};

렌더링 하기

위에선 만든 엘리먼트들과 객체 데이터의 변수를 연결했다. 이제 그 결과를 ul에 넣어주는 함수를 구해보자

의사코드

  1. 더미데이터가 배열의 모습을 하고있음을 알고 배열의 각 요소마다 돌기
  2. 각 요소에 위에서 만들었던 convertToDiscussion함수 적용한 뒤 ul에 추가
const render = (element) => {
  // 고차함수
  // agoraStatesDiscussions.map((pre) => element.append(convertToDiscussion(pre)));
  for (let i = 0; i < agoraStatesDiscussions.length; i += 1) {
    element.append(convertToDiscussion(agoraStatesDiscussions[i]));
  }
  return;
};
// ul 요소에 agoraStatesDiscussions 배열의 모든 데이터를 화면에 렌더링
const ul = document.querySelector("ul.discussions__container");
render(ul);

JS: 제출 받아주기

디스커션 추가기능 : 폼 제작, 작성자-본문 작성 후 제출하면 배열 데이터에 쌓임 + 뷰포트에 디스커션 실제로 추가

// 제출
const form = document.querySelector("form");

form.addEventListener("submit", () => {
  // submit 이벤트 필수, 새로고침 안되게
  // 로컬스토리지화 되면서 새로고침돼도 안없어지니 필요없어짐
  // event.preventDefault();
  // 제출된 내용(Value) 변수화
  const author = form.querySelector("div.form__input--name > input").value;
  const title = form.querySelector("div.form__input--title > input").value;
  const textbox = form.querySelector("div.form__textbox > textarea").value;
  // 들어갈 임시 객체 그릇 만들기
  // 입력되면 객체 그릇에 내용 담기
  // data.js에 옮기고 convertToDiscussion로 DOM 변환
  // render에 넣어서 렌더링 되게 하기

  const newObj = {
    id: "new id",
    createdAt: new Date(),
    title: title,
    url: "https://github.com/codestates-seb/agora-states-fe/discussions",
    author: author,
    answer: null,
    bodyHTML: textbox,
    // 랜덤 이미지 출력
    avatarUrl: "https://i.pravatar.cc/300",
  };
  // 바로 나타나기
  ul.pretent(convertToDiscussion(newObj))

  // submit 후 빈칸으로 리셋
  form.querySelector("div.form__input--name > input").value = "";
  form.querySelector("div.form__input--title > input").value = "";
  form.querySelector("div.form__textbox > textarea").value = "";
});

Advanced Challenge

  • 답변도 나오게 하기
  • 현지 시간 적용
    • 샘플 시간을 잘 변형하여, 현지 시간에 맞게 표현합니다. (ex. 오전 10:02:17)
  • 페이지네이션 기능
    • 페이지네이션에 대해서 스스로 학습합니다.
    • 한 페이지에 10개씩 디스커션이 보여야 합니다.
    • 다음 페이지로 넘어갈 수 있어야 합니다.
    • 이전 페이지로 돌아올 수 있어야 합니다.
    • 다음 페이지가 없거나, 이전 페이지가 없는 경우 페이지를 유지해야 합니다.
  • 디스커션 유지 기능
    • LocalStorage에 대해서 스스로 학습하고, 새롭게 추가하는 Discussion이 페이지를 새로고침해도 유지되도록 제작합니다.

현지시간 적용

new Date(시간).toLocaleString() 메소드 사용하면 됨, 현업에서도 많이 쓰임!

// 데이터를 넣어주면 알아서 해줌, 그냥 쓰면 현재시간 나옴!
new Date(obj.createdAt).toLocaleString()

시간을 표출해주기도 했음!

// 시계
const clock = document.getElementById("clock");
function getClock() {
  // 현재 시간 가져옴, 시간분초 다 따로 가져와야함
  const date = new Date();
  // get~으로 시분초 가져와서 변수 할당
  // number이기 때문에 String 변환해 textContent로 갖고오기
  const hours = String(date.getHours());
  const minutes = String(date.getMinutes());
  const seconds = String(date.getSeconds());
  // 10 이상 즉 2자리수 이상일 시 0을 붙이게 삼항연사자 썼음
  clock.textContent = `${hours < 10 ? `0${hours}` : hours} : 
    ${minutes < 10 ? `0${minutes}` : minutes} : ${seconds < 10 ? `0${seconds}` : seconds}`;
}
getClock();
// 코드 조각이나 함수를 1000ms로 계속 실행시키게 만드는
setInterval(getClock, 1000);

로컬스토리지를 이용한 새로고침 해도 값 유지하기!

  1. localStorage의 인터페이스를 활용
    • localStorage.setItem("key", "String") : 폼 엘리먼트같은 곳에서 제출같은 게 되면 브라우저의 로컬저장소(크롬 개발자도구-애플리케이션-로컬스토리지)에 저장되게 만드는 메소드. ⭐️객체를 넣으려면 JSON.stringify(obj) 필수로 넣어야함, 안그러면 '[object Object]'로 나옴!
    • localStorage.getItem("key") : 저장된 키의 값을 불러오기, 불러와서 뷰포트에 나오게 하거나 변수 지정 가능!
    • sessionStorage도 있음! 차이점은 로컬은 영구적(브라우저, 창이 닫아져도 값 유지)이지만 세션은 휘발성을 지님(닫으면 없어짐)
  2. newObjsetItem으로 저장 후 getItem으로 불러와 더미데이터에 추가 하는 방식으로 렌더링
    // 전역변수에서 설정해 더미데이터 배열에 들어갈 수 있게
    let getLocalDates = JSON.parse(localStorage.getItem("agoraLocalData"));
    agoraStatesDiscussions.unshift(getLocalDates);
    // 제출 이벤트 : pretend는 쓸모 없어졌으니 삭제
    form.addEventListener("submit", () => {
      // ...중략
      localStorage.setItem("agoraLocalData", JSON.stringify(newObj));
    }
    • 주의점 : getItem쓸 때 JSON.parse()를 써야한다. 그 이유는 객체 그 자체가 아닌 JSON 문자열 데이터로 나오기에 JSON.parse()를 써줘 객체로 들어가게끔 해야함

페이지네이션

여러개의 데이터들을 변환해줄 수 있는 기능을 만들어보자..

의사코드

  1. 현재 페이지-currentPage
  2. 뷰포트의 페이지 개수-pageCount : 5
  3. 페이지 안 데이터 개수-limit : 10
  4. 총 페이지 개수 - totalPage, 임의로

이런 식의 구조로 가면 된다

무조건 구현한다.
페이지네이션, 상위로 올라가기 버튼,
레퍼런스

profile
코뿔소처럼 저돌적으로

0개의 댓글