Jaeilit

항해99_사전스터디_미니프로젝트_객체(데이터)만들기 + API 호출(json-server) 본문

항해99 3기

항해99_사전스터디_미니프로젝트_객체(데이터)만들기 + API 호출(json-server)

Jaeilit 2021. 9. 2. 22:27
728x90

* 미니프로젝트는 순수 HTML, CSS, 간단한 JS 로 제작하였습니다. *

 

항해99_3기 본 과정에 앞서 사전스터디 그룹에서 미니프로젝트를 시작하게 되었습니다.

 

미니프로젝트의 내용은 사전강의를 통해 배운 내용으로 간단한 커피리뷰 사이트를 제작해서 배포까지가 목표입니다.

 

제가 맡은 부분은 커피에 대한 상세 페이지 부분입니다.

 

1. 객체(데이터)만들기

지난 번의 코드에서 수정을 조금 했습니다.

 

더보기

수정사항

 

db에 저장하기 위해서 아래 사진과 같이 객체 데이터를 만들었습니다.

db 저장을 위해 객체 데이터를 만든 모습

핵심내용은 for 문안에서 배열을 순회하면서 true 인 값의 id 값을 반환 하는 건데요,

id 값이 사진을 보시면 detail-form-radio-bad 입니다. 좀 이상하죠,,

 

이런 id값을 을 반환 하는 이유는 아래 사진과 같이 

댓글/리뷰 작성 시에 선택하는 radio 의 값에 따라

 

사용자가 리뷰를 보기 이전에 

좋아요 / 보통이에요 / 싫어요 의 합계?를 간단히 보여주기 위함입니다.

글을 읽기 귀찮아하시는 분들은 대충보고 아 이건 좋은거같다 보통인거같다 유추할 수 있을 것 같아서 넣었습니다.

 

id 값의 맨 끝 부분은 좋아요는 best 보통은 nomal 싫어요는 bad 입니다.

id 에 포함 된 값이 best 냐, nomal 이냐, bad 냐로 코드를 작성 할 수 있겠죠?

임시 값

코드 핵심

for 문안에서 reveiwRadio[i] 배열을 순회시켜서 id 값을 name에 담는건데요,

 

지금은 false 값도 함께 name에 할당 되지만 if문에 checked == true 를 거치면서

true 인 값만 객체에 담기게 됩니다.

function reviewSubmit() {
const reviewInput = document.getElementById("detail-review-content")
const reviewValue = reviewInput.value.trim()
  
  // 체크박스
  const reviewRadio = document.getElementsByClassName("detail-form-radio")
  for (let i = 0; i<reviewRadio.length; i++){
    const name = reviewRadio[i].id
    if(reviewValue && reviewRadio[i].checked === true){
      let reviewsObj = {};
      const date = new Date().toLocaleString()

      // console.log(date)
      // 날짜
      const commentDate = document.createElement("div")
      commentDate.classList.add("detail-comment-date")
      commentDate.innerText = date
      // console.log(commentDate)
  
      const commentReview = document.createElement("div")
      commentReview.classList.add("detail-comment-review")
      commentReview.innerText = reviewValue
      // commentReview.appendChild(commentDel)
      
      const createComment = document.getElementById("detail-comment-box")
      createComment.appendChild(commentReview)
      createComment.appendChild(commentDate)

      reviewsObj = {reviewValue, date, name}
      
      console.log(reviewsObj)
      
      reviewInput.value = "";

    }
  }
}

2. API 호출하기

커피 영양정보를 준비한 API 불러와야 합니다.

 

API는 json-server를 이용해서 서버로 띄울겁니다.

그래야지 호출이 됩니다.

json 파일만 가지고 있는다고해서는 안됩니다.

 

더보기

json-server 는 

 

npm i json-server 로 설치하셔서

 

json-server --watch 경로 --port 포트번호 하시면 됩니다.

 

성공적으로 API를 json-server로 띄웠다면 사용해야겠죠??

 

API 호출 / 적용 코드

const renderPosts = async () => {
  let url = "http://localhost:3001/starbucks"

  const res = await fetch(url)
  const api = await res.json()
  console.log(api)

  // 제목 가져오기
  const title = document.getElementById("detail-title").innerText

  let facts = [];
  let templates = '';
  
  // console.log(title)

  for(let i=0; i<api.length; i++){
    if(api[i].name === title){
      facts.push(api[i])
    };
  }
  // console.log(facts)

  facts.forEach(fact => {
    templates = `
      <li> 나트륨(mg): ${fact.sodium}(mg)</li>
      <li> 포화지방(g): ${fact.cholesterol}(g)</li>
      <li> 당류(g): ${fact.sugars}(g)</li>
      <li> 단백질(g): ${fact.protein}(g)</li>
      <li> 카페인(mg): ${fact.caffeine}(mg)</li>
    `
  })
  const detailFact = document.getElementById("detail-fact")
  detailFact.innerHTML = templates

  // 이미지 // 
  const detailImg = document.getElementById("detail-img")
  detailImg.innerHTML = `
    <div class="detail-img" style="background-image: url(${facts[0].img_url}">`
}



window.addEventListener('DOMContentLoaded', () => renderPosts())

Node 같은 프레임워크 없이

순수 html,css, js 로만 작업하려니까 구글링을 해도 Node나 React 구문만 나오고 힘들고 너무 하드코딩이였습니다.

 

코드 파해치기

외국 유투버분을 자막틀고 보고 배운겁니다.. 눙물..

 

1. DOMContenetLoaded

window.addEventListener('DOMContentLoaded', () => renderPosts())

모든 문서를 파싱하고 DOM 까지 로드가 끝난 후에 시작하라는 뜻 

이해를 돕는 링크

https://enai.tistory.com/6

 

2. async, await 비동기 함수, fetch 함수

const renderPosts = async () => {
  let url = "http://localhost:3001/starbucks"

  const res = await fetch(url)
  const api = await res.json()
  console.log(api)
  }

1. async  await 은 내가 앞에 일을 할 동안 기다려라 라는 뜻입니다.

여기서 앞에 일은 url 즉 api 을 가져오는 거겠죠?

 

2. fetch 는 서버에 요청하고 응답을 받을 수 있는 함수입니다.

 

이해를 돕는 링크

async, await : https://ko.javascript.info/async-await

fetch : https://ko.javascript.info/fetch

 

 

3. API에서 받은 값 HTML 에 적용하기

 const title = document.getElementById("detail-title").innerText

  let facts = [];
  let templates = '';
  
  // console.log(title)

  for(let i=0; i<api.length; i++){
    if(api[i].name === title){
      facts.push(api[i])
    };
  }
  // console.log(facts)

  facts.forEach(fact => {
    templates = `
      <li> 나트륨(mg): ${fact.sodium}(mg)</li>
      <li> 포화지방(g): ${fact.cholesterol}(g)</li>
      <li> 당류(g): ${fact.sugars}(g)</li>
      <li> 단백질(g): ${fact.protein}(g)</li>
      <li> 카페인(mg): ${fact.caffeine}(mg)</li>
    `
  })
  const detailFact = document.getElementById("detail-fact")
  detailFact.innerHTML = templates

  // 이미지 // 
  const detailImg = document.getElementById("detail-img")
  detailImg.innerHTML = `
    <div class="detail-img" style="background-image: url(${facts[0].img_url}">`

1. html 의 detail-title 이라는 div 태그의 값을 title 변수에 할당합니다.

2. facts 라는 빈 배열과 templates 라는 빈 문자열을 만듭니다.

3. 반복문을 통해서 api 의 배열을 순회하면서 같은 이름인 아이템 정보만 배열만 facts 라는 빈 배열에 넣습니다.

  ( 사실 이 부분이 마음에 안드는데 다른 방법을 아직 찾지 못해서 빈 배열에 할당했습니다. )

4. Array.forEach() 메서드로 api 의 각 데이터들을 뽑아서 HTML 코드화 해서 templates 에 할당 해줍니다.

5. 표시 할 부모요소의 id 값을 변수로 담아주고 innerHTML 으로 값을 넣기 해줍니다.

 

똑같은 방법으로 제품의 이미지도 넣어줘야 하는데요,

이미지는 li 태그들과는 다른 부분에 넣어줘야하기 때문에 forEach 구문에 넣지 않고 따로 하였습니다.


프로젝트 리뷰

 

제 역할은 상세 페이지여서 프로젝트는 아마 여기서 끝일듯 싶습니다.

 

프로젝트 시작전에는 간단할줄 알았는데 엄청난 하드코딩을 해버렸네요.

HTML, CSS 할때도 느꼈지만 내가 안다고 생각한것 중에 진짜로 제가 알고 있는건 없었습니다.

근데 구글은 다 알고 있더라구요....

 

앞으로 공부 할 때 진짜로 제가 아는 것인지 의심해 볼 필요가 많다고 느꼈고 무조건 진도를 빼기보다는 느리더라도 단단하게 나아가야 할 것 같습니다.

 

728x90