나만의 아고라스테이츠 만들기_1차 솔로프로젝트 회고

wool·2022년 7월 21일
1

회고

목록 보기
4/29
post-thumbnail

과제내용


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 형식에 따라주세요.

Advanced Challenge

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

과제 수행 시 신경 쓴 부분


  • 색을 선택할 때 센스가 부족해서 컬러헌트 사이트를 통해 도움을 받았다.

    Color Palettes for Designers and Artists - Color Hunt

  • 코드를 작성 할 때 복잡해 보이지 않게 작성하려고 노력했다.

    • CSS
      • 전역에 설정하는 속성을 따로 빼서 코드가 여기저기 겹치지 않도록했다.
        *{
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Noto Sans KR', sans-serif;
            font-family: 'Ubuntu', sans-serif;
        }
      • 같은 태그인데 class가 없는 요소를 선택해야할 경우 >를 사용하여 위치에 따른 라벨태그를 표시하여 쓸데없는 class명선언을 하지 않도록 했다.
        .form__input--title > label {
            word-spacing : 7px
        }
        
        .form__input--name > label {
            word-spacing : 3px
        }
  • 자바스크립트 기능구현부분에서 최대한 내 힘으로 해보려고 했으나.. 실패로 인해 다른 분들의 성공 코드를 봤다. 하지만 그 코드를 그대로 복사 붙여넣기가 아닌 이해가 되면 그 코드를 사용하는 등, 의미없는 답안 배껴쓰기가 되지 않도록 했다.

과제 수행 방식


1. 어떤 컨셉으로 정할지 고민

아고라 스테이츠를 찾는 사람들은 깊은 고민을 하다가 여기까지 온 것이라는 생각을 해서 심해라고 표현했고 바닷속이지만 좀 더 어두운 분위기로 디자인하려고 생각했다.

2. CSS로 스타일 입히기

  • CSS 전체 코드 보기
    *{
        margin: 0;
        padding: 0;
        box-sizing: border-box;
        font-family: 'Noto Sans KR', sans-serif;
        font-family: 'Ubuntu', sans-serif;
    }
    /* 브라우저 초기화 */
    
    @import url('https://fonts.googleapis.com/css?family=Amatic+SC');
    
    body {
        display: flex;
        justify-content: center;
        align-items: center;
        background-image: url('https://mblogthumb-phinf.pstatic.net/MjAxOTA5MDZfOTYg/MDAxNTY3NzM3Mjk2Mzc3.7LtUfaRWQKnLapgW6ygwGLoPE3IHKMAFzSIQ-Uvm1rYg.z-qRlOC9t3AmEByoYiaZM5USLi187cpUrxI06y8Jgp8g.JPEG.ygpa11819/%25EC%258B%25AC%25ED%2595%25B47.jpg?type=w800');
        background-repeat:no-repeat;
        background-size: cover;
    }  
    
    .form__input--title > label {
        word-spacing : 7px
    }
    
    .form__input--name > label {
        word-spacing : 3px
    }
    
    h2 {
        font-family: 'Nanum Brush Script', cursive;
        color: #99bcda;
    }
    section.form__container {
        background-color: rgba(82, 213, 245, 0.5);
        border-radius: 20px;
    }
    .discussion__answered {
        padding-top: 39px;
        font-size: 20px;
        margin: 5px;
        color: #FFF9CA;
    
    }
    .discussion__container {
        display: flex;
        justify-content: space-between;
        align-items: center;
        width: 578px;
        height: 150px;
        font-size : 10px;
        border-radius: 19px;
        margin : 10px;
        padding: 20px;
    }
    .discussion__avatar--image {
        width: 48px;
        border-radius: 50%;
        display: flex;
        align-items: center;
        margin: 5px;
    }
    .discussion__content{
        display: block;
    }
    .discussion__content >:nth-child(1){
     width: 440px;
     text-align: left;
     margin-top: 0;
    }
    .discussion__content >:nth-child(2){
        height:30px;
        text-align: right;
    }
    li {
        list-style-type: none;
    }
    section.discussion__wrapper{
        display: flex;
        flex:4;
        width: 578px;
        justify-content: center;
        align-items:center;
    }
    ul {
        padding: 0px;
    }
    li.discussion__container {
        background-color: rgba(0, 165, 231, 0.5);
    }
    a:link {
        color: white;
        font-family: 'Dongle', sans-serif;
        font-size: 22px;
    }
    a:visited {
        color: rgb(0, 0, 0);
    }
    
    /* 폼 디자인 */
    h1 {
        text-align: center;
        margin-top: 70px;
        margin-bottom: 20px;
        color: #99bcda;
        font-size: 40pt;
    }
    h3 {
        text-align: center;
        color: #99bcda;
        margin-bottom: 20px;
    }
    section {
        display:flex;
        justify-content: center;
        align-items: center;
    }
    form {
        display: flex;
    
        width: 500px;
        flex-wrap: wrap;
        flex-direction: row;
    }
    .form__textbox {
        display: flex;
        flex-direction: column;
    }
    #story {
        width: 500px;
        border-radius: 10px;
        padding: 10px;
    }
    .form__input--wrapper {
        margin: 5px;
    
    }
    .form__input--wrapper input {
        width:300px;
        height: 30px;
        font-size:1.2rem;
        margin: 5px;
        border-radius: 10px;
        border: 2px solid #0078AA;
    }
    .form__submit {
        flex:1;
        margin:3px;
    
    }
    .form__submit input {
        width: 448px;
        height: 43px;
        border-radius: 10px;
        font-size: 15px;
        margin-left: 25px;
        margin-right: 0px;
        border: 2px solid black;
    }
    textarea {
        margin : 5px;
    }
    
    .discussion__information {
        padding-top: 10px;
        font-size: 14px;
        color: #FFF9CA;
    }
    
    img {
        width: 48px;
        border-radius: 100%;
    }
  • 배경이미지를 넣을 때 배경에 맞추어 보여지게 하기 위해 이미지를 HTML에서 넣지 않고 CSS body에서 background-image, background-size: cover로 넣어주었다.
    body {
        display: flex;
        justify-content: center;
        align-items: center;
        background-image: url('https://mblogthumb-phinf.pstatic.net/MjAxOTA5MDZfOTYg/MDAxNTY3NzM3Mjk2Mzc3.7LtUfaRWQKnLapgW6ygwGLoPE3IHKMAFzSIQ-Uvm1rYg.z-qRlOC9t3AmEByoYiaZM5USLi187cpUrxI06y8Jgp8g.JPEG.ygpa11819/%25EC%258B%25AC%25ED%2595%25B47.jpg?type=w800');
        background-repeat:no-repeat;
        background-size: cover;
    }
  • 배경 이미지가 보이기 원해서 뒷 배경이 투명해지길 원했는데 opacity를 사용하면 박스 전체가 투명하게 되어 배경컬러에 rgba(82, 213, 245, 0.5);로 배경색 투명도를 조정했다
    section.form__container {
        background-color: rgba(82, 213, 245, 0.5);
        border-radius: 20px;
    }
  • 콘텐츠의 정렬은 display: flex를 활용하여 구성했다.

3. 자바스크립트로 기능 구현하기

  • 자바스크립트 전체코드
    // index.html을 열어서 agoraStatesDiscussions 배열 요소를 확인하세요.
    console.log(agoraStatesDiscussions);
    
    // convertToDiscussion은 아고라 스테이츠 데이터를 DOM으로 바꿔줍니다.
    const convertToDiscussion = (obj) => {
      const li = document.createElement("li"); // li 요소 생성
      li.className = "discussion__container"; // 클래스 이름 지정
    
    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';
      // 왜 새롭게 만들어주어야하는가?
      // convertToDiscussion 이 함수의 목적은 값을 추출해서 새로운 il뭉치를 만들기 위해 
    
      // TODO: 객체 하나에 담긴 정보를 DOM에 적절히 넣어주세요.
    
      const face = document.createElement("img") // 프로필 사진
      face.src = obj.avatarUrl;
      face.alt = "avatar of" + obj.author;
      avatarWrapper.append(face);
      
    
      const discussionTitle = document.createElement("h2");
      const titleAnchor = document.createElement("a");
      titleAnchor.href = obj.url;
      titleAnchor.textContent = obj.title;
      discussionTitle.append(titleAnchor);
      discussionContent.append(discussionTitle);
      
    
      const discussionInfo = document.createElement("div");
      discussionInfo.textContent = `${obj.author} / ${new Date(obj.createAt).toLocaleTimeString()}` // 날짜 표현 형식이 여러개가 있는데 이걸 제일 많이  쓴다
      discussionContent.append(discussionTitle, discussionInfo);
    
      const checked = document.createElement("p");
      checked.textContent = obj.answer ? "☑︎" : "☒";
      discussionAnswered.append(checked);
    
      li.append(avatarWrapper, discussionContent, discussionAnswered);
      return li; // il요소를 위의 함수를 통해 가공해서 append
    };
    
      // form 은 데이터를 깔끔하게 받기 위해서 받는것
      // 
    
    // agoraStatesDiscussions 배열의 모든 데이터를 화면에 렌더링하는 함수입니다.
    const render = (element) => { // 여기 엘리먼트는 ul.discussions__container 이게 들어옴
      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); 
    // 화면에 그리는 작업을 렌더링이라고 하는데 지금 이 함수는 렌더링함수 이렇게 호출하면서 끝난다.
    
    // 디스커션 추가 구현
    
    // 문서 내용 가져오기.
    const form = document.querySelector("form.form");
    const author = form.querySelector("div.form__input--name > input");
    const title = form.querySelector("div.form__input--title > input");
    const textbox = form.querySelector("div.form__itextbox > textarea");
    
    // submit을 클릭하면 자료를 가져온다
    
    form.addEventListener("submit", (event) => {
      event.preventDefault(); //서브밋 이벤트로 사용시 꼭 함께 사용해주어야함
      const obj = {
        id: "new id",
        createdAt: new Date().toISOString(),
        title: title.value ,
        url: "https://github.com/codestates-seb/agora-states-fe/discussions",
        author: author.value,
        bodyHTML: textbox.value,
        avatarUrl: "https://avatars.githubusercontent.com/u/97888923?s=64&u=12b18768cdeebcf358b70051283a3ef57be6a20f&v=4"
      }
    })
    
    agoraStatesDiscussions.unshift(obj);
    
    const discussion = convertToDiscussion(obj);
    
    ul.prepend(discussion);
  • 값을 추출해서 새로운 li뭉치를 만들기
    // index.html을 열어서 agoraStatesDiscussions 배열 요소를 확인하세요.
    console.log(agoraStatesDiscussions);
    
    // convertToDiscussion은 아고라 스테이츠 데이터를 DOM으로 바꿔줍니다.
    const convertToDiscussion = (obj) => {
      const li = document.createElement("li"); // li 요소 생성
      li.className = "discussion__container"; // 클래스 이름 지정
    
    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';
      // 왜 새롭게 만들어주어야하는가?
      // convertToDiscussion 이 함수의 목적은 값을 추출해서 새로운 il뭉치를 만들기 위해
    <필수 구현기능1> TODO: 객체 하나에 담긴 정보를 DOM에 적절히 넣어주세요.
    const face = document.createElement("img") // 프로필 사진
      face.src = obj.avatarUrl;
      face.alt = "avatar of" + obj.author;
      avatarWrapper.append(face);
      
    
      const discussionTitle = document.createElement("h2");
      const titleAnchor = document.createElement("a");
      titleAnchor.href = obj.url;
      titleAnchor.textContent = obj.title;
      discussionTitle.append(titleAnchor);
      discussionContent.append(discussionTitle);
      
    
      const discussionInfo = document.createElement("div");
      discussionInfo.textContent = `${obj.author} / ${new Date(obj.createAt).toLocaleTimeString()}` // 날짜 표현 형식이 여러개가 있는데 이걸 제일 많이  쓴다
      discussionContent.append(discussionTitle, discussionInfo);
    
      const checked = document.createElement("p");
      checked.textContent = obj.answer ? "☑︎" : "☒";
      discussionAnswered.append(checked);
    
      li.append(avatarWrapper, discussionContent, discussionAnswered);
      return li; // il요소를 위의 함수를 통해 가공해서 append
    };

4. 깃으로 배포하기

원래 알고있던거라 어렵지않게 배포완료

https://yeowool1010.github.io/fe-sprint-my-agora-states/

아직 해결되지 않은 이슈


디스커션 오류 해결!

  • 분명히 세션에서 하라는대로 했는데 왜 안되는지 의문… 글이 새로 쌓이지 않는다.. 호다닥 수정중..

    ⇒ 글 적고 게시글이 쌓이고 나서 폼 입력란이 빈칸을로 돌아오게 만들어주기까지 완성

    디스커션 추가 기능을 위한 from.addEventListener를 활용한 이벤트 함수를 만들때 안에서 사용할 변수와 함수호출을 함수 밖에서 해버려서 작동하지 않았던것이다!

<필수 구현기능2>

TODO: 디스커션 추가

  • 나의 오류코드
// 디스커션 추가 구현

// **함수 밖에서 선언한것 오류! addEventListener 안으로 이동해야함**
~~const form = document.querySelector("form.form");
const author = form.querySelector("div.form__input--name > input");
const title = form.querySelector("div.form__input--title > input");
const textbox = form.querySelector("div.form__itextbox > textarea");~~

// submit을 클릭하면 자료를 가져온다

form.addEventListener("submit", (event) => {
  event.preventDefault(); //서브밋 이벤트로 사용시 꼭 함께 사용해주어야함
  const obj = {
    id: "new id",
    createdAt: new Date().toISOString(),
    title: title.value ,
    url: "https://github.com/codestates-seb/agora-states-fe/discussions",
    author: author.value,
    bodyHTML: textbox.value,
    avatarUrl: "https://avatars.githubusercontent.com/u/97888923?s=64&u=12b18768cdeebcf358b70051283a3ef57be6a20f&v=4"
  }
})

// **함수 밖에서 선언한것 오류! addEventListener 안으로 이동해야함**
~~agoraStatesDiscussions.unshift(obj);

const discussion = convertToDiscussion(obj);

ul.prepend(discussion);~~
  • 오류 수정 코드
form.addEventListener("submit", 
(event) => {
  event.preventDefault(); //서브밋 이벤트로 사용시 꼭 함께 사용해주어야함
  // addEventListener 안으로 선언 위치 이동
  **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;**

  const newObj = {
    id: "new id",
    createdAt: new Date().toISOString(),
    title: title,
    url: "https://github.com/codestates-seb/agora-states-fe/discussions",
    author: author,
    bodyHTML: textbox,
    avatarUrl: "https://avatars.githubusercontent.com/u/97888923?s=64&u=12b18768cdeebcf358b70051283a3ef57be6a20f&v=4"
  }
// addEventListener 안으로 선언 위치 이동
  **agoraStatesDiscussions.unshift(newObj);

  const discussion = convertToDiscussion(newObj);
  
  ul.prepend(discussion);**

  // submit 후 입력란 빈칸으로 리셋하는 기능 추가
  **form.querySelector("div.form__input--name > input").value = "";
  form.querySelector("div.form__input--title > input").value = "";
  form.querySelector("div.form__textbox > textarea").value = "";
}**
)
  • 날짜를 설정해줬는데도 여전히 처음 그 형태다

날짜 표기 오류해결!!

⇒ 변수명의 오타로 인해 잘 안들어왔던것!

업로드중..

  • 나의 오류코드
const discussionInfo = document.createElement("div");
  discussionInfo.textContent = `${obj.author} / ${new Date(~~**obj.createAt**~~).toLocaleTimeString()}`
																								    	// obj.createAt 오타!
  discussionContent.append(discussionTitle, discussionInfo);
  • 오류 수정 코드
const discussionInfo = document.createElement("div");
  discussionInfo.textContent = `${obj.author} / ${new Date(**obj.createdAt**).toLocaleTimeString()}` 

새롭게 알게 된 것


  • 현업에서 날짜 표현 할 때 new Date().toLocaleTimeString() 이걸 제일 많이 쓴다는 것을 알게되었다.
  • addEventListener적용 시 submit을 사용할 경우, 반드시 함수 안에 event.preventDefault()를 적용 해 주어야 오류가 나지 않는다.
  • 가능한 함수로 기능들을 묶고 함수를 사용 할 때는 화살표함수를 사용하되 화살표함수는 호이스팅이 일어나지 않으므로 코드가 작동하는 위치에 대해 생각하며 작성해야한다.

느낀점


자바스크립트는 도대체 언제 익숙해지는걸까?

알고있는 반복문 어쩌구 이런거랑 실제 페이지에 적용하는것은 엄청난 괴리가 있다고 생각했다.

아직 자바스크립트의 명령어들을 자주 쓰지 않고 잘 몰라서 그런듯하기도하고..

내 머리가 잘 돌아가지않고 삐걱거려서 그런 부분도 좀 큰것도 같고..

제일 걱정되는것은 이런 나의 속도로 인해 함께 프로젝트할 사람이 없다면..?

그게사실 제일 걱정이다..

ㅋㅋㅋㅋㅋㅋㅋㅋ

ㅜㅜ
2022년 7월 18일 완성
2022년 7월 22일 오류 수정함!

profile
毎日一つづつゆっくり

0개의 댓글