React/예제

await/async 예제 - 랜덤 강아지 이미지

lamarcK 2025. 4. 8. 22:19

await/async를 통해 fetch로 강아지의 이미지를 받아오고 이미지가 변경되도록 했다.

async 구문이 아닐 경우 내부 작업이 프로미스 처리가 되지 않기 때문에 중간에 기다리를 과정이 없어진다.

 

  • const response = await fetch()
    • 즉 fetch가 이미지를 받아오기 전에 다음 단계로 넘어가서 undefined인 상태로 json으로 넘어가게 된다.
  •  const data = await response.json()
    • 결과적으로 강아지 이미지가 반영되지 않고 오류가 난다.

이용 사이트 dog api

 

Dog API

Dog CEO's Dog API. Over 20,000 images of dogs programmaticaly accessible by over 120 breeds. Image supplied by the Stanford Dogs Dataset.

dog.ceo

JSON 형태로 파일을 제공해준다.

message 부분이 이미지 파일 이름

js 코드

더보기
import { useState, useEffect } from 'react'
import './App.css'

// App.jsx

function App() {
  const [dogImage, setDogImage] = useState('')
  const [isLoading, setIsLoading] = useState(false)
  const [error, setError] = useState(null)

    // async로 dog 이미지 로딩 기다림
      const fetchDog = async () => {
        setIsLoading(true)
        try {
          const response = await fetch('https://dog.ceo/api/breeds/image/random')
          const data = await response.json()
          setDogImage(data.message)
          setError(null)
        } catch (err) {
          setError('강아지 이미지를 가져오는데 실패했습니다.')
        } finally {
          setIsLoading(false)
        }
      }
  //최초 1회 실행행
  useEffect(() => {
    fetchDog()
  }, [])

  return (
    <div className="container">
      <h1>🐕 랜덤 강아지 이미지 🐕</h1>
      {error && <p className="error">{error}</p>}
      {dogImage && (
        <div className="dog-img">
          <img 
            src={dogImage} 
            alt="Random Dog" 
            className="dog-box"
          />
        </div>
      )}
      
      <button 
        onClick={fetchDog} 
        disabled={isLoading}
              >
        {isLoading ? '로딩중...' : '새로운\n강아지 보기'}
      </button>
    </div>
  )
}

export default App

css

더보기
#root {
  max-width: 1280px;
  margin: 0 auto;
  padding: 2rem;
  text-align: center;
}

.container{
  width: fit-content;
  height: fit-content;
  display: flex;
  flex-direction: column;

  align-items: center;
}

.dog-box{
  border-radius: 25px;
  max-height: 300px;
  height: 300px;
  object-fit: cover;
}

button {
  margin: 20px;
  border-radius: 8px;
  height: 100px;
  width: 200px;
  max-height: 100px;
  max-width: 200px;
  border: 1px solid transparent;
  padding: 0.6em 1.2em;
  font-size: 1.5em;
  font-weight: 800;
  background-color: azure;
  border-radius: 25px;
  font-family: inherit;
  cursor: pointer;
  transition: border-color 0.25s;
  white-space: pre-line;
}

button:disabled {
  background: linear-gradient(to bottom, #ffffff, #cccccc);
  color: #888;
  cursor: not-allowed;
  border: 1px solid #ccc;
}