Dandy Now!
  • [Next.js] 웹 카메라 제어 : 촬영된 base64 인코딩 데이터 jpg 저장
    2023년 10월 14일 10시 39분 00초에 업로드 된 글입니다.
    작성자: DandyNow
    728x90
    반응형

    1. multer로 삽집;;;

    node.js로 서버를 구축할 때 파일 저장 라이브러리로 multer를 이용했었다. 이번에도 react-camera-pro 라이브러리를 이용해 캡처된 이미지를 jpg 형식으로 저장할 때 multer를 이용해야겠다고 생각하다 무지하게 삽집했다!

    react-camera-pro 라이브러리를 Next.js App Router를 이용한 프로젝트에 적용하여 애플리케이션을 만들고 있다. src/app/route.js 파일을 생성하고 jpg 이미지를 public/uploads 폴더에 저장하는 POST API를 구현하였다. 이때 multer를 사용했는데 이미지 저장에 실패하는 현상에서 빠져버렸다.

     

    2. base64 인코딩 데이터 jpg 저장은 fs로~

    2.1. base64 인코딩 데이터를 FormData 객체에 추가 및 POST API 호출

    react-camera-pro 라이브러리는 캡처된 이미지 데이터를 base64 인코딩 데이터로 제공해 주었다. 이 데이터를 FormData객체에 append 한 후 fetch를 이용해 POST API를 호출하였다. 해당 코드는 아래와 같다.

    // CameraControler.jsx
    
    "use client";
    
    // (생략)
    
    const handleFileUpload = async () => {
    	
        // (생략)
        
        const [image, setImage] = useState(null); // image는 캡쳐된 base64 인코딩 데이터이다.
        
        if (!image) {
          console.error("이미지가 없습니다.");
          return;
        }
    
        const formData = new FormData();
        formData.append("image", image);
    
        try {
          const response = await fetch("/api", {
            method: "POST",
            body: formData,
          });
    
          if (response.ok) {
            console.log("이미지 업로드 성공");
          } else {
            console.error("이미지 업로드 실패");
          }
        } catch (error) {
          console.error("이미지 업로드 중 오류 발생:", error);
        }
    };
    
    // (생략)

     

    2.2. POST API에서 fs를 이용해 jpg 이미지 파일 생성 및 저장

    App Router 방식의 프로젝트라서 Route Handlers를 이용하였다. request body로 넘어온 FormData 객체의 base64 인코딩 데이터를 fs.writeFileSync()를 이용해 jpg 파일로 저장하는 POST API를 구현하였다. 이때 fs.writeFileSync()의 인수로 파일명(경로 포함)과 디코딩한 이미지 데이터를 각각 넣어 주면 된다.

    주의할 점이 있는데 base64 데이터를 디코딩할 때 "data:image/png;base64"를 제거하지 않으면 생성된 이미지 파일이 열리지 않는다. 따라서 정규식을 이용해 해당 문자열을 제거해 주어야 한다. 해당 코드는 아래와 같다.

    // src/app/api/route.js
    
    // (생략)
    
    export async function POST(request) {
      const formData = await request.formData();
      const imageFile = formData.get("image");
    
      // 이미지를 base64에서 디코딩하고 저장'
      // 주의 : 정규식 코드가 누락되면 생성된 이미지 파일이 열리지 않는다!
      const imageBuffer = Buffer.from(
        imageFile.replace(/^data:image\/jpeg;base64,/, ""),
        "base64"
      );
      const imageFilePath = path.join(
        "public/uploads",
        new Date().valueOf() + ".jpg"
      );
    
      fs.writeFileSync(imageFilePath, imageBuffer);
    
      return Response.json({
        status: 200,
      });
    }

     

    3. base64에 대하여

    Base64 인코딩을 사용하면 원본보다 약 30%의 크기 증가가 발생하지만 이진 데이터를 텍스트로 변환하거나, 텍스트 데이터를 포함하는 다양한 형태의 통신에서 유용하게 활용할 수 있다. 다시 말해 Base64로 인코딩 된 이미지나 파일 데이터를 HTML 또는 CSS에 직접 포함시킬 수 있다는 것이다. 이것은 이미지나 파일을 외부로 요청하지 않고 웹 페이지 내에 내장시킬 수 있는 방법 중 하나이다.

    728x90
    반응형
    댓글