엘리스 SW 트랙 4주차-1

Hyejis·2022년 10월 3일
0

엘리스

목록 보기
1/11

10월 3일

비동기

1) 자바스크립트 제어 흐름

① 자바스크립트 비동기

  • 자바스크립트는 다른 멀티스레드 프로그래밍 언어와 다른 방식으로 비동기 동작을 처리한다.
  • 처음 자바스크립트를 접하는 경우, 동작에 대한 정확한 이해가 없으면 코드의 흐름을 따라가기 어렵다.
  • 자바스크립트 내부의 비동기 동작을

② 자바스크립트 엔진

  • 자바스크립트 엔진은 하나의 메인 스레드로 구성된다.
  • 메인 스레드는 코드를 읽어 한 줄씩 실행한다.
  • 브하우저 환경에서는 유저 이벤트를 처리하고 화면믈 그린다.

③ 동기적 제어 흐름

  • 동기적 제어 흐름: 현재 실행 중인 코드가 종료되기 전까지 다음 줄의 코드를 실행x
  • 분기문, 반복문, 함수 호출 등이 동기적으로 실행
  • 코드의 흐름과 실제 제어 흐름이 동일
  • 싱글 스레드 환경에서 메인 스레드를 긴 시간 점유하면 프로그램을 멈추게 한다.
let a=10
console.log("a: ",a)
function foo(num){
  for (let i=0;i<10;++i){
    console.log(num)
  }
}

-> 하던 일이 끝나야 다른 요청 처리 가능

④ 비동기적 제어 흐름

  • 비동기적 제어 흐름: 현재 ㅈ실행 중인 코드가 종료되기 전에 다음 라인의 코드를 실행
  • 프로미스, 콜백 함수를 호출하는 함수 등은 비동기적으로 실행
  • 코드 흐름과 제어 흐름이 다르다.
  • 비동기 작업을 기다리는 동안 메인 스레드는 다른 작업을 처리
let a=10
setTimeout(function callback(){
  console.log('a: ',a)
},3000)
console.log('Finished')

-> 중간에 다른 요청 처리 가능

2) 이벤트 루프

① 자바스크립트 비동기

  • 자바스크립트 엔진은 비동기 처리를 제공하지 않는다.
  • 대신, 비동기 코드는 정해진 함수(API)를 제공하여 활용할 수 있다.
  • 비동기 API의 예시로 setTimeout, XMLHttpRequest, fetch 등의 Web API가 있다
  • node.js의 경우 파일 처리 API, 암호화 API 등을 제공한다.
// 타이머 비동기 처리
setTimeout(() => console.log('타이머 끝'), 1000)
setInterval(() => console.log('인터벌 타이머'), 1000)
// 네트워크 처리
fetch('https://google.com')
	.then(() => console.log('네트워크 요청 성공.'))
	.catch(() => console.log('네트워크 요청 실패.'))

② 비동기 처리 모델

메인스레드: call stack(execution context stack)
비동기 환경: task queue, job queue
메인스레드 -> (비동기 코드 호출) -> 비동기 환경
메인스레드 <- (비동기 코드 처리, 결과 함수 반환) <- 비동기 환경

  • 비동기 코드를 터리하는 모듈은 자바스크립트 엔진 외부에 있다.
  • 이벤트 루프, 태스크 큐, 잡 큐 등으로 구성
  • API 모듈은 비동기 요청 처리 후 태스크 큐에 콜백 함수를 넣는다.
  • 자바스크립트 엔진은 콜 스택이 비워지면 태스크 큐의 콜백 함수를 실행
request("user-data",(userData) => {
  console.log("userData 로드")
  saveUsers(userData)
});
console.log("DOM 변경")
console.log("유저 입력")

③ 동기 비동기 타이머 구현하기

동기적, 비동기적으로 카운터를 증가하는 Counter

지시사항

  1. incrementSync 함수는 3초 동안의 동기 동작 후 Counter의 count 를 증가합니다.
  • Date.now() 함수를 이용하여, 현재 시간보다 3초 뒤에 this.count 를 증가하도록 구현하세요.
  • Date.now()는 ms 단위의 시간을 반환하므로, 3000ms를 기준으로 시간의 변화를 판단하면 됩니다.
  1. incrementAsync 는 3초 동안의 비동기 동작 후 Counter의 count를 증가합니다.
  • setTimeout 함수를 이용하여 3초 뒤에 this.count를 증가하고 콜백을 호출하도록 구현합니다.
const Counter = {
  count: 0,
  getCount: function () {
    return this.count;
  },
  resetCount: function () {
    this.count = 0;
  },
  incrementSync: function () {
    // 동기적으로 3초 뒤에 this.count를 증가
    // while 문 안에서, 또 다른 Date.now()를 구하여 3000을 초과하는 순간 while 문을 벗어남
    const currentTime=Date.now()
    while (true){
        const now=Date.now()
        if (now-currentTime>3000) break
    }
    this.count++
  },
  incrementAsync: function (callback) {
    // 비동기적으로 3초 뒤에 this.count를 증가하며 callback을 호출
    // setTimeout을 활용하세요.
    setTimeout(()=>{
        this.count++
        callback()
    },3000)
  },
};
export default Counter;

3) Promise

① Promise API

  • Promise API는 비동기 API 중 하나이다.
  • 태스크 큐가 아닌 잡 큐를 사용한다.
  • 잡 큐는 태스크 큐보다 우선순위가 높다.
setTimeout(()=>{
  console.log("타임아웃1");
},0);
Promise.resolve().then(()=>console.log("프로미스1")); 
setTimeout(()=>{
  console.log("타임아웃2");
},0);
Promise.resolve().then(()=>console.log("프로미스2"));

// 프로미스1 프로미스2  -> 프로미스의 처리가 우선순위가 더 높다.
// 타임아웃1 타임아웃2

② Promise

  • 비동기 작업을 표현하는 자바스크립트 객체
  • 비동기 작업의 진행, 성공, 실패 상태를 표현
  • 비동기 처리의 순서를 표현

③ Promise 생성자

let promise=new
Promise((resolve,reject)=>
        {
  if(Math.random() < 0.5){
    return reject("실패")
  }
  resolve(10)
})
----------------------------------------------------------------------------   
- new Promise(callback)
- callback함수는 (resolve, reject) 두 인자를 받는다.
- Promise가 성공했을 때 resolve를 호출
- Promise가 실패했을 때 reject를 호출
     

④ Promise 생성자

promise
	.then(data => {
  		console.log("성공:",data)
	})
	.catch(e => {
  		console.log("실패:",e)
	})
	.finally(() => {
  console.log("promise 종료")
	})
---------------------------------------------------------------------------
- then() 메서드에 성공했을 때 실행할 콜백 함수를 인자로 넘긴다.
- catch() 메서드에 실패했을 때 실행할 콜백 함수를 인자로 넘긴다.
- finally() 메서드는 성공/실페 여부와 상관없이 모두 실행할 콜백 함수를 인자로 넘긴다.
- then(callback1, callback2)로 callback1의 자리에 성송, callback2의 자리에 실패 메서드를 인자로 넘길 수 있다.

⑤ Promise 메서드 체인

promise
	.then(data => {
  		return fetchUser(data)
	})
	.then(user => {
  		console.log('User : ',user)
	})
	.catch(e => {
  		console.log("실패:",e)
	})
----------------------------------------------------------------------------
- then/catch 메서드가 또 다른 promise를 리턴하여 비동기 코드에 순서를 부여한다.
- 이렇게 동일한 객체에 메서드를 연결할 수 있는 것을 체이닝이라 한다.
- 함수를 호출한 주체가 함수를 끝낸 뒤 자기 자신을 리턴하도록 구현

⑥ Promise.resolve, Promise.reject

Promise
	.resolve(10)
	.then(console.log)
Promise
	.reject("Error")
	.catch(console.log)
----------------------------------------------------------------------------
- Promise.resolve 함수는 성공한 Promise를 바로 반환
- Promise.reject 함수는 실패한 Promise를 바로 반환
- 인위적으로 Promise 메서드 체인을 만들 수 있다.
- 비동기 코드로 진행해야 하는 상황 등에 유용하게 사용할 수 있다.

⑦ Promise.all

Promise.all([
  promise1,
  promise2,
  promise3
])
	.then(values => {
  	console.log("모두 성공: ",values)
	})
	.catch(e => {
  console.log("하나라도 실패: ",e)
	})
----------------------------------------------------------------------------
- Promise.all은 Promise의 배열을 받아 모두 성공 시 각 Promise의 resolved 값을 배열로 반환
- 하나의 Promise라도 실패할 시, 가장 먼저 실패한 Promise의 실패 이유를 반환

⑧ 유저 주소 검색 폼 구현하기

유저네임을 입력받아, 그 유저에 해당하는 주소를 검색하는 앱
UserInput 컴포넌트를 구현하여 앱. setValue는 유저로부터 받은 inputValue를 클로저의 value에 저장.
지시사항을 참고하여 searchAddress() 함수를 구현

지시사항

  1. findUserByUsername, findAddressByUserId 함수는 모두 Promise를 리턴합니다.
  2. findUserByUsername API 함수를 이용하여, value 값을 이용해 유저를 검색합니다.
  3. findAddressByUserId API 함수를 이용하여, 찾은 user의 id를 이용해 주소를 검색합니다.
  4. searchAddress는 address 객체를 반환하는 Promise를 리턴하도록 구현합니다.
  5. catch를 이용해, 에러 발생 시 error에 error.message를 저장하도록 구현합니다.
    ####Tips!
  • 가짜 API가 주어져 있다. 데이터를 참조하여 구현
import { findUserByUsername, findAddressByUserId } from "./api";

const UserInput = () => {
  let value = "";
  let error = "";

  function getValue() {
    return value;
  }

  function getError() {
    return error;
  }

  function setValue(inputValue) {
    value = inputValue;
  }
    // 지시사항을 참고하여 searchAddress() 함수를 구현
  function searchAddress() {
    error = "";
    return findUserByUsername(value)
    .then(user=>findAddressByUserId(user.id))
    .catch(e=>{
        error=e.message
    })
  }
  return { getError, getValue, setValue, searchAddress };
};
export default UserInput;

10월 5일

4) async/await

① async/await

  • Promise를 활용한 비동기 코드를 간결하게 작성하는 문법
  • async/await 문법으로 비동기 코드를 동기 코드처럼 간결하게 작성 가능
  • async 함수와 await 키워드를 이용
  • await 키워드는 반드시 async 함수 안에서만 사용
  • async로 선언된 함수는 반드시 Promise 리턴

② async함수

async function asyncFunc(){
  let data=await fetchData()
  let user=await
  fetchUser(data)
  return user
}
----------------------------------------------------------------------------
- async함수는 function 키워드 앞에 async를 붙여 만든다.
- async 함수 내부에서 await 키워드를 사용한다.
- fetchData, fetchUser는 Promise를 리턴하는 함수

③ await키워드 실행 순서

async function asyncFunc(){
  let data1=await fetchData1()
  let data2=await fetchData2(data1)
  let data3=await fetchData3(data2)
  return data3
}
function promiseFunc(){
  return fetchData()
  .then(fetchData2)
  .then(fetchData3)
}
----------------------------------------------------------------------------
- await 키워드는 then 메서드 체인을 연결한 것처럼 순서대로 동작
- 비동기 코드에 쉽게 순서를 부여

④ 에러 처리

function fetchData1(){
  return request()
  .then((response)=>
        response.requestData)
  .catch(error=>{
    // error 발생
  })
}
----------------------------------------------------------------------------
- Promise를 리턴하는 함수의 경우 에러가 발생하면 catch 메서드를 이용해 에러를 처리
- catch 메서드를 사용하지 않는다면 async 함수에서 try-catch 구문을 이용해 에러를 처리

⑤ 에러 처리

async function asyncFunc(){
  try{
    let data1=await
    fetchData1()
    return fetchData2(data1)
  } catch (e) {
    console.log("실패:",e)
  }
}
----------------------------------------------------------------------------
- try-catch 구문으로 async/await 형태 비동기 코드 에러 처리가 가능
- catch 절의 e는 Promise의 catch 메서드가 받는 반환값과 동일

요약

콜백 함수

비동기로 작동되는 함수
비동기 함수는 2초 뒤에 Elice라는 이름을 인자로 받은 콜백함수의 인자로 넘겨준다.

function getName(cb) {
    setTimeout(() => {
        cb("Elice");
    }, 2000);
}

앞선 함수를 실행하려면 getName 함수에 콜백함수를 넣어서 사용 가능

getName((name) => {
    console.log(name);
})
// 2초 후 Elice

getName 함수를 이용해서 Elice라는 이름을 3번 출력하려면?
getName 함수를 절차적으로 실행시키면 2초 뒤에 Elice라는 이름이 나온다.

getName((name) => {
    console.log(name);
})
getName((name) => {
    console.log(name);
})
getName((name) => {
    console.log(name);
})
// 2초 후
// Elice
// Elice
// Elice

하지만 앞선 방법으로 콜백함수를 호출하면 각 함수에 대한 데이터를 사용할 수 없다.
예를들어 이름, 나이, 주소가 저장된 데이터를 비동기적으로 가져와야 한다고 가정해보면

function getName(cb) {
    setTimeout(() => {
        cb("Elice");
    }, 2000);
}
function getAge(cb) {
    setTimeout(() => {
        cb(6);
    }, 2000);
}
function getAddress(cb) {
    setTimeout(() => {
        cb("Seoul");
    }, 2000);
}

해당 정보 출력하고자 한다. 하지만 console.log를 한 번만 사용해야한다.

getName((name) => {
    getAge((age) => {
        getAddress((address) => {
            console.log(name, age, address)
        })
    })
})

앞선 코드처럼 콜백함수 안에 콜백 함수를 반복하여 호출해야 name, age, address를 한꺼번에 접근 가능
비동기 함수가 3개 쓰이고, 각 2초씩 걸리기 때문에 6초 뒤에 Elice 6 Seoul이라는 log가 나오게 된다.
바로 이것을 콜백 지옥이라 부른다. 비동기 함수를 3개만 썼을 뿐인데도,
코드가 정말 복잡해졌다. 비동기 함수가 더 많다면 관리하기 더 힘들다.

Promise

Promise로 콜백 지옥을 보기 좋게 바꾸기!
앞서 사용한 비동기 함수인 getName, getAge, getAddress와 Promise 객체를 만들어서 사용해 같이 수정

function getName() {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve("Elice");
        }, 2000);
    })
}
function getAge() {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(6);
        }, 2000);
    })
}
function getAddress() {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve("Seoul");
        }, 2000);
    })
}

각 함수는 Promise 객체를 리턴. 그리고 Promise 객체는 항상 2초 후에 resolve 되어 이름, 나이, 주소에 대한 정보를 준다. 그리고 다음과 같이 호출하여 사용.

getName().then((res) => {
    console.log(res);
})
getAge().then((res) => {
    console.log(res);
})
getAddress().then((res) => {
    console.log(res);
})

하지만 이렇게 사용하면 정보를 하나의 함수에서 제어하기 힘들다.
따라서 다음과 같이 사용할 수 있다.

Promise
    .all([getName(), getAge(), getAddress()])
    .then((res) => {
        const [name, age, address] = res;
        console.log(name, age, address)
    })

Promise.all은 첫번째 인자에 배열을 받는다. 그 배열의 원소는 모두 프로미스 객체
getName, getAge, getAddress 함수는 모두 프로미스 객체를 반환하기 때문에 Promise.all에서 사용 가능하다. 또한, Promise.all은 병렬적으로 배열의 원소에 있는 프로미스를 동시에 실행시킨다. 따라서 결과적으로 2초 후에 Elice 6 Seoul을 출력 가능하다. 즉, 동시에 Promise 객체를 반환하는 함수들을 실행가능 하다는 것. 콜백함수로는 할 수 없는 일이다.

async/await

프로미스를 더 간단하게 사용하려면 다음과 같이 사용 가능하다.
즉시실행 함수 형태에 async 화살표 함수를 이용해 작성할 수 있다. await 키워드에서 프로미스가 resolve 될 때까지 기다린 후 다음 순서로 넘어가기 때문에 6초 후에 Elice 6 Seoul이 출력된다.

(async () => {
    const name = await getName();
    const age = await getAge();
    const address = await getAddress();
    console.log(name, age, address);
})();

Promise와 async/await는 효과적으로 사용될 수 있는 상황이 다르기 때문에
두 방법 모두 잘 알고 있어야한다. 메소드 체이닝이 많이 사용되는 코드에서는 Promise가 코드에 일관성을 지켜서 더 깔끔하게 보일 수 있고, 개별 함수를 호출하여 값을 받아오는 경우에는 asyne/await이 효과적이다.

⑥ wait 함수 구현하기

특정 시간 이후에 Promise를 resolve 하는 wait 함수

지시사항

새로운 Promise를 리턴하는 wait 함수를 선언하세요.

  • wait 함수는 ms 단위로 기다리는 시간을 입력받습니다.
  • ex) wait(500) - 500ms를 기다립니다.
  • ex) wait(1000) - 1초(1000ms)를 기다립니다.
  • wait 함수는 내부에 setTimeout을 사용합니다.
  • setTimeout 이후 wait 함수가 리턴하는 Promise는 resolve 됩니다.
const wait = ms => new Promise(resolve=>setTimeout(resolve,ms))

5) HTTP,REST API

① HTTP

  • Web에서 서버와 클라이언트 간의 통신하는 방법을 정한 것
  • 클라이언트는 웹 브라우저 등 서버로 요청을 보내는 대상
  • 서버는 클라이언트가 요청을 보내기 전까지 대응하지 않음
  • 서버와 클라이언트 사이에는 무수히 많은 요소가 존재
  • HTTP는 이런 존재들 사이의 통신 방법을 규정

    클라이언트<-HTTP->Web<-HTTP->Server

② HTTP Message

  • 서버 주소, 요청 메서드, 상태 코드, target path, 헤더 정보, 바디 정보 등이 포함
  • 요청 메시지, 응답 메시지의 모양이 다름
  • HTTP/1.1 메세지는 사람이 읽을 수 있음

③ HTTP Header

  • HTTP 메시지의 헤더에는 콘텐츠 관련 정보, 인증 관련 정보, 쿠키 정보, 캐시 관련 정보 등 서버와 클라이언트 간 통신 시 필요한 정보를 담는다.
  • 클라이언트 요청 시, 서버 응답 시 모두 헤더에 담을 수 있다.

④ HTTP Status

  • HTTP 요청 시, 클라이언트는 요청의 결과에 대한 상태 정보를 얻는다.
  • 200, 400, 500 등 숫자 코드와 OK, NOT FOUND 등의 텍스트로 이루어짐
  • 코드를 이용해 각 결과에 해당하는 행위를 할 수 있음

⑤ 요청 메서드

  • HTTP에서, 클라이언트는 서버로 요청을 보낸다.
  • 요청 시 요청 메서드로 특정 요청에 대한 동작을 정의한다.
  • GET, POST, PUT, PATCH, DELETE, OPTIONS, CONNECT, TRACE 등이 규정됨

⑥ REST API

  • API: 사용자가 특정 기능을 사용할 수 있도록 제공하는 함수
  • REST API: HTTP의 요청 메서드에 응하는 서버 API와 클라이언트 간 통신의 구조가 지켜야 할 방법을 명시 한 것
  • 구체적인 내용으로는 요청 메서드의 의미, URL설계, 클라이언트 상태에 대한 동작 등을 정의

⑦ REST API 요청 메서드의 의미

  • GET: 리소스 정보를 얻음
  • POST: 리소스를 생성
  • PUT: 리소스를 생성하거나 업데이트
  • DELETE: 리소스를 제거

6) Fetch API

① Fetch API

let result = fetch(serverURL)
result
.then(response=>{
  if(response.ok){
    // 요청 성공
  }
})
.catch(error=>{
  // 요청 실패
})
----------------------------------------------------------------------------
- 기존 XMLHTTPRequest를 대체하는 HTTP 요청 API
- ES6에 추가된 Promise를 리턴하고록 정의
- 네트워크 요청 성공 시, Promise는 Response 객체를 resolve한다.
- 네트워크 요청 실패 시, Promise는 에러를 reject한다.

② Response

fetch(serverURL)
.then(response=>{
  response.ok
  response.status
  response.statusText
  response.url
  response.bodyUsed
})
----------------------------------------------------------------------------
- Response 객체는 결과에 대한 다양한 정보를 담는다.
- response.ok는 HTTP Status code가 200-299 사이면 true, 그 외 false이다.
- response.status는 HTTP status code를 담는다.
- response.url은 요철한 URL 정보를 담는다.

③ Header

fetch(serverURL)
.then(resp=>{
  for(let [k,v] of
      resp.headers){
    console.log(k,v)
  }
})
----------------------------------------------------------------------------
- response.headers로 Response 객체의 헤더 정보를 얻을 수 있다.

④ Body 메서드

fetch(serverURL)
.then(response=>{
  return response.json()
})
.then(json=>{
  console.log('body : ', json)
})
----------------------------------------------------------------------------
- response.json() 메서드는 얻어온 body 정보를 json으로 만드는 Promise를 반환한다.
- Promise가 resolve 되면 얻어온 body 정보를 읽는다.
- response.text(), response.blob(), response.formData() 등의 메서드로 다른 형태의 바디를 읽는다.

⑤ POST 요청

fetch(serverURL,{
  method:'post',
  headers:{
    'Content-Type':
    'application/json;charset=utf-8',
    Authentication:'mysecret'
  },
  body:JSON.stringify(formData)
})
.then(response=>{
  return response.json()
})
.then(json=>{
  console.log('POST 요청 결과:', json)
})
----------------------------------------------------------------------------
- fetch(url,options), fetch 메서드 옵션을 넣는다.
- method 필드로 여러 요청 메서드를 활용한다.
- headers,body 필드를 활용해 서버에 추가 정보를 보낸다.

⑥ 유저 정보 요청하여 변환하기

https://randomuser.me API를 이용해, 여러 유저의 정보를 받아와 가공하는 함수
API 정보를 가공하여 활용. User.js의 requestUsers 함수

지시사항

1 유저 정보를 변환

- user.email -> email
- user.name.first, user.name.last -> name - `${user.name.first} ${user.name.last}`
- user.picture.large -> pictureUrl
- user.login.username -> username
- user.location.country, user.location.state, user.location.city -> location - `${user.location.country}, ${user.location.state}, ${user.location.city}`
- user.dob.age -> age
  • 예시
// 유저 정보가 다음과 같을 경우
{
  gender: "female",
  name: {
    title: "Miss",
    first: "Sara",
    last: "Petersen",
  },
  location: {
    street: {
      number: 1383,
      name: "Vægterparken",
    },
    city: "Sommersted",
    state: "Nordjylland",
    country: "Denmark",
    postcode: 30790,
    coordinates: {
      latitude: "24.7161",
      longitude: "11.7793",
    },
    timezone: {
      offset: "-11:00",
      description: "Midway Island, Samoa",
    },
  },
  email: "sara.petersen@example.com",
  dob: {
    date: "1994-10-26T10:14:18.009Z",
    age: 27,
  },
  registered: {
    date: "2009-12-05T16:15:56.322Z",
    age: 12,
  },
  id: {
    name: "CPR",
    value: "261094-1270",
  },
  picture: {
    large: "https://randomuser.me/api/portraits/women/63.jpg",
    medium: "https://randomuser.me/api/portraits/med/women/63.jpg",
    thumbnail: "https://randomuser.me/api/portraits/thumb/women/63.jpg",
  },
  // ...
},

// 이렇게 변환됩니다.
{
  email: 'sara.petersen@example.com',
  name: 'Sara Petersen',
  pictureUrl: 'https://randomuser.me/api/portraits/women/63.jpg',
  username: 'happybear329',
  location: 'Denmark, Nordjylland, Sommersted',
  age: 27
}
  1. age 가 40세 이상인 유저만을 필터링
  2. 필터링 된 유저 목록을 리턴

Tips

  • Promise, async/await 방법을 모두 활용해 구현
import API from "./api";
function transformUser(user){
    const {first, last}=user.name
    const {country,state,city}=user.location
    const email=user.email
    const name= `${first} ${last}`
    const pictureUrl=user.picture.large
    const username=user.login.username    
    const location=`${country}, ${state}, ${city}`
    const age=user.dob.age
    return {email,name,pictureUrl,username,location,age}
}
function filterByAge(user){
    return user.age >= 40
}
const requestUsers = () => {
  return API.fetchUsers().then((users) => {
    // 유저 정보를 변화하고, 필터링하는 코드를 작성해보세요.
    return users
    .map(transformUser)
    .filter(filterByAge)
  });
};
export default requestUsers;

⑦ Posts 정보 조합하기

유저 정보, post 정보, 커멘트 정보를 응답하는 API를 활용, 하나의 포스트 목록
https://jsonplaceholder.typicode.com 의 API를 이용하여 데이터를 조합
Posts.jsrequestPosts 메서드. requestPosts는 posts 정보를 아래 지시사항에 따라 조합하여 리턴하는 비동기 함수

지시사항

  1. api.js 에 제공된 fetchPosts, fetchUsers, fetchComments API를 이용하여 포스트 정보, 유저 정보, 커멘트 정보를 각각 요청하세요.
  2. 얻어온 데이터를 활용하여 정보를 조합하세요.
  • fetchPosts API를 이용하여 posts 목록을 가져옵니다.
  • 하나의 post 객체에는 userId가 들어있습니다. userId 필드를 제거하고 userId에 해당하는 유저 정보를 post정보에 합칩니다. 유저 정보는 fetchUsers 에서 얻은 정보를 활용합니다.
  • 하나의 post 객체에는 id가 들어있습니다. id 필드를 제거하고, 이 post id를 이용하여 comments를 요청하고, 새롭게 comments 필드를 추가하여 응답받은 커멘트 목록을 post 합칩니다. 커멘트 정보는 fetchComments API를 활용합니다.
  • 하나의 post 정보에 user 필드를 추가하고, 그 필드에 post.userId에 매칭되는 유저 정보를 넣습니다.
  • 하나의 post 정보에 comments 필드를 추가하고, 그 필드에 comment.postId에 매칭되는 커멘트들의 목록을 넣습니다.
  • 최종적으로 하나의 post 정보는 모든 post 정보에 추가로 user, comments 필드를 갖게 됩니다.
  • fetchPosts 가 이렇게 정보가 합쳐진 post 들의 배열을 반환하도록 합니다.
    테스트 앱을 활용하여 결과가 제대로 만들어지는지 확인해보세요.

Tips!

  • fetchPosts는 포스트 목록을 반환합니다.
  • fetchUsers는 유저 목록을 반환합니다.
  • fetchComments 는 postId를 파라미터로 받아 해당하는 커멘트 목록을 반환합니다.
  • 반환이 이루어지는 posts 배열의 요소인 post 는 아래의 4개 필드를 가지고 있어야 채점이 정상적으로 이루어집니다.
    body, comments, title, user



----------------------------------------------------------------------------

profile
프론트를 시작으로 풀스택을 걸쳐 모든 분야를 아우르고 싶은 야망이 살짝 있는 아기 개발자입니다.

0개의 댓글