백엔드

패스트캠퍼스 챌린지 14일차 - 이미지 리사이징 서버

꾸준이 2021. 9. 19. 23:26

0. 공부인증

공부 시작 21 : 35

공부 종료 23 : 25

본가에서 공부를 하는 마지막 날이다.
아쉽기는 하지만, 여튼 쉽지 않은 공부 과정이었다.

노트북 한 화면에 티스토리, 패캠, VScode를 전부 활용하는 것은 ㄹㅇ무리다.

 

 

1. 이미지 리사이징해서 돌려주기

우선 클라이언트가 접속하면 
unplash에서 이미지를 조회 후, url을 가져옴. 이후 이미지를 스트림 형식으로 클라이언트에 스트림 되는 방식인데,

이미지를 캐싱처리하면 소요시간을 줄일 수 있음.

const imageFilePath = path.resolve(__dirname, `../unsplash-images/${query}`)

  // 파일이 존재하는지 확인 - 이미지 캐싱 여부 확인
  if (fs.existsSync(imageFilePath)) {
    return {
      message: `Returning cached image: ${query}`,
      stream: fs.createReadStream(imageFilePath),
    }
  }


  // 캐시된 이미지가 없을 경우, 이미지를 새로 다운로드
  const result = await searchImage(query)
  const resp = await fetch(result.url)
~

클라이언트 요청을 받아서 요청사항을 파악하고,

이미지 캐싱이 있는지 확인하고,

스트림의 형태로 사용자가 원하는 값으로 리사이징하고,

그것을 다시 스트림의 형태로 클라이언트에게 전송하는 과정이다.

 

-> 캐싱유무를 파악하는 것은 위의 코드블럭에서 확인이 가능하다.

-> 사용자의 요구사항 파악하고 이미지를 리턴하는 코드

  const urlObj = new URL(url, 'http://localhost:5000')

  /**
   * @param {string} name 
   * @param {number} defaultValue
   * @returns
   */
   
  // 파람값에 이미지 사이즈 정보가 있는지 확인
  // 없으면 디폴트 값으로 설정
  function getSearchParam(name, defaultValue) {
    const str = urlObj.searchParams.get(name)
    return str ? parseInt(str, 10) : defaultValue
  }

  // 가로의 크기를 URL 파라미터 값에서 받아오는 것.
  const width = getSearchParam('width', 400)
  const height = getSearchParam('height', 400)

  // 이미지 정보까지 리턴
  return {
    query: urlObj.pathname.slice(1),
    width,
    height,
  }

-> 위 코드에서 리턴한 값을 활용하여,
이미지를 캐시 혹은 다운로드로 스트림의 형태로 받아와야함.

// 위에서 이미 설명한 코드
async function getCachedImageOrSearchedImage(query) {
  const imageFilePath = path.resolve(__dirname, `../unsplash-images/${query}`)

  if (fs.existsSync(imageFilePath)) {
    return {
      message: `Returning cached image: ${query}`,
      stream: fs.createReadStream(imageFilePath),
    }
  }

  const result = await searchImage(query)
  const resp = await fetch(result.url)

 // resp.body 로 부터 들어오는 스트림을 
 // fs에 넘겨주면서 데이터를 스트림으로 저장함.
  await promisify(pipeline)(resp.body, fs.createWriteStream(imageFilePath))
  const size = imageSize(imageFilePath)

  // 그렇게 저장된 값을 다음 로직에서 활용할 수 있도록, 데이터를 넘김
  return {
    message: `Returning new image: ${query}, width: ${size.width}, height: ${size.height}`,
    stream: fs.createReadStream(imageFilePath),
  }
}


~~~

    const { query, width, height } = convertURLToImageInfo(req.url)
    try {
      // 스트림 방식으로 읽어온 파일을 처리하기
      const { stream } = await getCachedImageOrSearchedImage(query)
      
      // promisify를 통해서 데이터를 순차적으로 가공함.
      await promisify(pipeline)(
        // 스트림 데이터를,
        stream,
        
        // 샤프 모듈로 리사이징 처리함.
        sharp()
          .resize(width, height, {
            fit: 'contain',
            background: '#ffffff',
          })
          .png(),
	    // 그리고 그 값을 바로 클라이언트에게 던짐
        res
      )
    } catch (e) {
      res.statusCode = 400
      res.end()
    }
  }

  main()
})

위와 같은 코드로 원하는 데이터를 받을 수 있다.

 

근데 스트림에 대한 이해가 너무 부족하다.

스트림에 대한 공부를 좀 더 해봐야겠다.

우선 https://jeonghwan-kim.github.io/node/2017/07/03/node-stream-you-need-to-know.html 를 참고하면 좋을 것 같다.

 

Node.js Stream 당신이 알아야할 모든 것 1편

원본: https://medium.freecodecamp.com/node-js-streams-everything-you-need-to-know-c9141306be93 노드js의 스트림은 정말 다루기 어렵고 이해하기 힘든 것으로 유명합니다. 글세요. 이제는 더 이상 그렇지만은 않을 거

jeonghwan-kim.github.io

 

내일부터는 다시 사무실에가서 GIt 과 관련된 수업을 들을 예정이다.

 

여튼 부디 내일부터는 공부 진도가 쭉쭉 나갔으면 좋겠다.

 

 

환급 챌린지 (14/30)

 

 

본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.

https://bit.ly/37BpXiC

 

패스트캠퍼스 [직장인 실무교육]

프로그래밍, 영상편집, UX/UI, 마케팅, 데이터 분석, 엑셀강의, The RED, 국비지원, 기업교육, 서비스 제공.

fastcampus.co.kr

#패스트캠퍼스 #패캠챌린지 #직장인인강 #직장인자기계발 #패스트캠퍼스후기 #한번에끝내는Node.js웹프로그래밍초격차패키지