728x90

지난시간,,

https://stepby-yun.tistory.com/180

 

[mySQL 이미지 저장] BLOB말고 문자열로 하는 이유 (+string문자열 VAR / CHAR 차이)

지난 시간,,, https://stepby-yun.tistory.com/179 formData 이미지데이터 보내고 받기 (react,nodejs,header) 회원가입시 아이디 비번 프로필을 등록하려했다. id password는 넘겨주고 req.body.id로 받았는데 프..

stepby-yun.tistory.com

db에 이미지 저장까지 마쳤다.

formData로 이미지를 받았다.

이미지를 불러오는걸 하기 전에

id와 password도 함께 보내는 걸 하고 싶다.

 

formData를 쓰면 req.body를 쓸 수 없고id, password는 req.body로 받아와야하니 분리해야하나 싶었는데 역시나 방법이 있었어

 

 

 참조

<form> 파일, 텍스트 </form> 다 가져오고싶은데

  • 파일업로드 미들웨어의 필수조건인 <form enctype="multipart/form-data">을 쓰면 req.body를 undefined로 받고
  • 그렇다고 req.body를 받기위해 <form enctype="multipart/form-data">를 안쓰면 express-fileuplode나 multer를 못쓴다.

 

bodyParser를 쓰면 된다고 함 (팀플할때 무지성으로 썼는데 혼자하니 이렇게 깨닫는구나 역시 왜 쓰는지 생각해봐야함)

 

 

 

파싱이란 HTML 형식으로 사용자가 제출한 데이터에 접근하는 것을 의미합니다. 'GET' 방식으로 폼을 제출하면 '쿼리 문자열'에 데이터가 추가되어 쉽게 접근할 수 있지만 'POST' 방식으로 폼을 제출하면 데이터에 접근하기가 다소 어렵습니다. 보안을 위해 인코딩되었습니다. 데이터를 매우 쉽게 파싱할 수 있는 바디 파서 NPM 방법이 있지만 이 파싱 방법을 처음부터 구현하려고 하면 몇 가지 단계가 필요합니다.

 

Parsing means accessing the data submitted by user with HTML form. When the form is submitted with the ‘GET’ method, data are appended in ‘query string’ and can access easily but when a form is submitted using the ‘POST’ method, it is somewhat difficult to get access over those data since they are encoded because of security purpose. 
There exist a body-parser NPM method that makes it very easy to parse the data but if we try to implement this parsing method from scratch, there’s involve some steps.

 

 

근데 드는 의문이

bodyParser쓰면 multer지금 쓰고 있는거 필요없는거 아닌가?

걔도 미들웨어... 둘다 쓰는건가..

 

어라라 찾아보니까

하지만, express 버전 4.16이상 부터는 'express bodyparser deprecated ( bodyParser는 더이상 지원되지 않습니다.)' 와 같은 문제가 발생한다.

그 이유는, 4.16버전 이상 부터는 express 내부에 bodyParser가 포함되기 때문이다.

라고 한다.

 

 

- app.use(express.bodyParser())
+ app.use(express.json())
+ app.use(express.urlencoded())

이렇게 바디파서 대신 밑에 두줄을 쓴다는 건데...뭔지 잘모르겠는데요

 

 

 

 

일단 코드 추가하고 실행해보니 

일단 body-parser 모듈을 사용할 때 아무 옵션을 주지 않는 다면
body-parser deprecated undefined extended: provide extended option 같은 문구가 뜬다.

 

bodyParser 미들웨어의 여러 옵션 중에 하나로 false 값일 시 node.js에 기본으로 내장된 queryString, true 값일 시 따로 설치가 필요한 npm qs 라이브러리를 사용한다.

queryString 과 qs 라이브러리 둘 다 url 쿼리 스트링을 파싱해주는 같은 맥락에 있으나 qs가 추가적인 보안이 가능한 말 그대로 extended 확장된 형태이다.
기본이 true 값이니 qs 모듈을 설치하지 않는다면 아래와 같이 false 값으로 따로 설정을 해주어야 한다.

 

오 그렇군요 감사합니다

그래도 아직 req.body는 아무것도 안들어온다

이미지만 들어오고 흠흠

 

 

 

보낼때 id랑 password추가하면 body값만 찍히고 

이미지는 안되고...

 

 

라는데 왜...안되지..

https://blog.naver.com/bunggl/221699257359

 

 

이미지 넣은 것처럼 id랑 password도 formdata에 넣어봄

 

'id,password'이렇게 한 배열로 들어가서 안됨

 

 

 

https://hyc7575.github.io/2017/05/24/2017-05-24-node-js-bodyparserAndMulter/

 

Node.js(express) - body-parser와 multer

Node.js에서 form양식을 submit을 하기위해 사용되는 body-parser와 multer 미들웨어에 대해서 간단하게 알아보려 합니다. 각 미들웨어의 용도를 짧게 소개하면 body-parser는 라우터와 미들웨어 예제때 언급

hyc7575.github.io

 

https://kirkim.github.io/javascript/2021/10/16/body_parser.html

 

[NodeJs] express.json()과 express.urlencoded()의 차이점 알아보기

1️⃣ 사용이유 (1) .json()과 .urlencoded()를 사용하지 않을 때

kirkim.github.io

 

 

 

 

 

 

 

res.json/res.send차이https://haeguri.github.io/2018/12/30/compare-response-json-send-func/

출처

res.json

https://jin2rang.tistory.com/entry/express-bodyparser-deprecated-bodyparser%EB%8A%94-%EB%8D%94%EC%9D%B4%EC%83%81-%EC%82%AC%EC%9A%A9%EB%90%98%EC%A7%80-%EC%95%8A%EC%8A%B5%EB%8B%88%EB%8B%A4-%EB%AC%B8%EC%A0%9C%ED%95%B4%EA%B2%B0

 

https://velog.io/@hyunju-song/body-parser%EC%9D%98-urlencoded%EB%8A%94-%EB%8F%84%EB%8C%80%EC%B2%B4-%EC%96%B4%EB%96%A4-%EC%97%AD%ED%95%A0%EC%9D%84-%ED%95%98%EB%8A%94-%EA%B1%B8%EA%B9%8C

++

바디파서써서 req.body랑 이미지 파일 전송하기 

https://velog.io/@yuna_song/enctypemultipartform-data-%EC%82%AC%EC%9A%A9-%EC%8B%9C-req.body-%EC%82%AC%EC%9A%A9%EB%B2%95

formData 객체전송

https://melius.tistory.com/51

728x90
728x90

지난 시간,,,

https://stepby-yun.tistory.com/179

 

formData 이미지데이터 보내고 받기 (react,nodejs,header)

회원가입시 아이디 비번 프로필을 등록하려했다. id password는 넘겨주고 req.body.id로 받았는데 프로필은 formData 객체로 묶어서 그자체로 넘겨줬는데 자꾸 undefined 떴다. formData는 req.body가 안된다길

stepby-yun.tistory.com

formData 로 이미지 받는 걸 Header를 뒤늦게 추가해서 넣었다.

이제 mySQL 데이터베이스에 넣으려는데

아무것도 없고  BLOB만 달랑 저장됨

이미지 저장은 보통 BLOB로 한다고 해서 타입을 이렇게 넣었는데 

저렇게만 보이니 당황,, 

 

 

BLOB은 뭘까?

A Binary Large Object (BLOB) is a MySQL data type that can store binary data such as images, multimedia, and PDF files.

바이너리 데이터를 DB외부에 저장하기 위한 타입이다

"blob의 경우 4GB의 이진 데이터를 저장할 수 있다고 합니다. 하지만 이건 DB에 직접 저장하는 것이 아니라 DB에는 Large Object의 위치 포인터만 저장하게 됩니다."

그말은 즉, 컴퓨터가 인식하는 모든 파일(이진 데이터)를 저장하는 타입이라고 한다. 오 찾아보니까 볼 수 있긴하네

이렇게 확인할 수는 있구만 

 

 

하지만 BLOB보다는 URL자체로 저장을 선호한다고 한다.

그 이유는데이터베이스 서버는 애플리케이션이 확장될 때 종종 성능병목 현상이 일어나는데 이미지와 함께 로드하면 더 큰 병목현상이 발생한다고 함.

Many web app designers don't store images in database BLOBS, but rather store them in a file system, and store their URLs in database strings. Why? Database servers often become a performance bottleneck when an application scales up. If you load them with images, they'll become even bigger bottlenecks.

 

그럼 string문자열로 바꿔줘야지~

하고 string찾는데 없어 아 맞다 VAR이지하고 보다가

 

VARCHAR과 CHAR의 차이가 뭔가 궁금해졌다

VARCHAR은 '가변길이'

실질적인 데이터와 길이 정보도 같이 저장된다.

CHAR은 길이가 고정되어있어야한다. 남는 공간은 공백으로 채운다 공간낭비 발생!

VARCHAR is variable length, while CHAR is fixed length

https://petri.com/sql-server-string-data-types/

 

 

 

경로저장함

 

 

 

이제 id랑 password 도 함께 저장해봐야지 

 

 

 

 

 

 

출처

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=magnking&logNo=220950061851

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=rlasksdud53&logNo=220595010315

 

 

728x90
728x90

회원가입시

아이디 비번

프로필을 등록하려했다.

 

id password는 

넘겨주고 req.body.id로 받았는데 

프로필은 formData 객체로 묶어서 

그자체로 넘겨줬는데 자꾸 undefined 떴다. 

 

formData는 req.body가 안된다길래 

 

 

 

multer을 써봤는데도 안됨

(req.body대신 req.file 또는 files를 찍어봤지만 안됐다. )

 

formData쓸때 헤더에 타입을 넣어줘야한대서 

 

뒤늦게 

  {
        headers: {
          "Content-Type": "multipart/form-data",
        },
      }

를 추가했다. 위치는 보내는 formdata 다음에 넣어줬다.

 

이걸로도 해결이 안됐는데 신기하게 

같이보낸 id, password를 지우니 

undefined가 안뜨고 이미지가 전송돼서 images폴더에 이미지도 담겼다!

 

req.file에 이미지url이 찍혔다.

 

import React, { useState } from "react";
import Axios from "axios";
import "./signup.css";
import FormData from "form-data";

function Signup() {
  //회원가입 값
  const [id, setId] = useState("");
  const [password, setPassword] = useState("");

  // const [imageUpload, setImageUpload] = useState(null);

  const [image, setImage] = useState({
    preview:
      "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAAM1BMVEXk5ueutLfn6eqrsbTp6+zg4uOwtrnJzc/j5earsbW0uby4vcDQ09XGyszU19jd3+G/xMamCvwDAAAFLklEQVR4nO2d2bLbIAxAbYE3sDH//7WFbPfexG4MiCAcnWmnrzkjIRaD2jQMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMw5wQkHJczewxZh2lhNK/CBOQo1n0JIT74/H/qMV0Z7GU3aCcVPuEE1XDCtVLAhgtpme7H0s1N1U7QjO0L8F7llzGeh1hEG/8Lo7TUmmuSrOfns9xnGXpXxsONPpA/B6OqqstjC6Ax/0ujkNdYQQbKNi2k64qiiEZ+ohi35X+2YcZw/WujmslYewiAliVYrxgJYrdwUmwXsU+RdApUi83oNIE27YvrfB/ZPg8+BJETXnqh9CVzBbTQHgojgiCvtqU9thFJg/CKz3VIMKMEkIXxIWqIpIg2SkjYj+xC816mrJae2aiWGykxRNsW0UwiJghJDljYI5CD8GRiCtIsJxizYUPQ2pzItZy5pcisTRdk/a9m4amtNNfBuQkdVhSaYqfpNTSFGfb9GRIakrE2Pm+GFLaCQPqiu0OpWP+HMPQQcgQMiQprWXNmsVwIjQjYi/ZrhAqNTCgr2gu0Jnz85RSSjso0HkMFZ0YZjKkc26a/jlmh9JiDyDxi9oeorTYAzZkwwoMz19pzj9bnH/GP/+qbchjSGflneWYhtTuKdMOmNKZcJ5TjInQKcYXnESd/jQxy0ENpULTNGOGgxpap/oyw9pbUAqhfx2Dbkhovvfgz4iUzoM9+GlK6/Mh4q29hyC1mwro30hpVVLPF9wYQr71RazOeM5/cw81iBRD+A03aM9/C/obbrKjbYSpCmIVG3qT/Q8oeUo3Rz0IL7vI1tEbCB9pSiu8I/aV8x3Kg/BGWrWp4ZVs0nZfmAoEG4h/61yHYIJiFSl6Q0Vk6tTW1N8kYp8hdOkfHYYMXd2Qft+8CYwqYDSKvqIh+MCF8Wgca2u/cwdgeW3TtuVn6+1oBs3yLo5C2JpK6CvQzGpfUkz9UG/87gCsi5o2LIXolxN0FbwAsjOLEr+YJmXn7iR6N0BCt5p5cMxm7eAsfS+/CACQf4CTpKjzgkvr2cVarVTf96372yut7XLJ1sa7lv6VcfgYrWaxqr3Wlo1S6pvStr22sxOtTNPLzdY3nj20bPP+ejFdJYkLsjGLdtPBEbe/mr2bQKiXWJDroA+vtzc0p9aahuwqHMDYrQEXHEw9jwQl3drMpts9JBU1SdktPe5FBRdJQ6bwXBpa57ib2A8kukQDzMjh++Uo7Fo6Wd02Pkf4fknqoo4HtvAIjsqUcjx6DIPgWCaOML9rKI/oqD9/lgNrn+eF+p7j8tnzHBiR7+kdUGw/+V1Kzkc75mMy6U+FMaxjPibiM1U1uGM+puInHpmALZCgP4pt7i840MV8+0R1zPsRB6UTcqpizncYwZ89syDydfyWCwXB1l8/zRNGWbTG/GHKUm9AkxHMc/EGSk3z2+ArEhPEV5TUBLEvUGFcjEUH80J/jveTGOAJEljJbILWGQT3zRYiwuKsUXN1EEJAzBhRJFll7mBUG7KD8EqPkKekBREaL8hMDZLQSG6AQjtHPYmvTQnX0TtpC1SYCe2YdkkyLP3jj5BSbKiuR585eQhTgoje6yIb0Yb0C+mV6EYvebqw5SDy2WmubogZiF2AVxPC2FpDf8H2Q9QWo6IkjUxTWVEI3WY/wrCeSuqJ+eRWzXR/JXwgVjUMozbCOfoEZiSiKVGepqv5CJ8RyR4D7xBeamqa7z3BJ/z17JxuBPdv93d/a2Ki878MMAzDMAzDMAzDMAzDMF/KP09VUmxBAiI3AAAAAElFTkSuQmCC",
    data: "",
    // Headers: " 'Content-Type': 'multipart/form-data'",
  });

  //다 userlist에 담아서 db저장하기
  // const [userList, setUserList] = useState([]);

  const onChangeId = (event) => {
    setId(event.target.value);
  };

  const onChagePassword = (event) => {
    setPassword(event.target.value);
  };

  const Submit = (e) => {
    e.preventDefault();

    let formData = new FormData();
    formData.append("file", image.data);

    console.log(image.data, "선택한이미지! ");
    console.log(formData, "들어가기전폼데이터");

    Axios.post(
      "http://localhost:3001/submit",

      // {
      //   id: id,
      //   password: password,
      //   formData,
      //   headers: { "Content-Type": "application/x-www-form-urlencoded" },
      // }
      // {
      //   id: id,
      //   password: password,
      // },

      formData,

      {
        headers: {
          "Content-Type": "multipart/form-data",
        },
      }
    ).then(() =>
      console.log(
        formData,
        "then이후 폼데이터",
        image,
        "이건뭐",
        image.data,
        "이미지데이터"
      )
    );
  };

  const handleFileChange = (e) => {
    const img = {
      preview: URL.createObjectURL(e.target.files[0]),
      data: e.target.files[0],
    };

    setImage(img);
  };

  return (
    <div className="formBox">
      <div className="signup_id">
        <input placeholder="아이디" onChange={onChangeId}></input>
      </div>
      <div className="signup_password">
        <input placeholder="비밀번호" onChange={onChagePassword}></input>
      </div>
      <div>
        <input placeholder="비밀번호 확인"></input>
      </div>
      {image.preview && <img src={image.preview} width="100" height="100" />}
      <input
        type="file"
        onChange={handleFileChange}
        name="Images"
        accept="Images/*"
      />

      <button onClick={Submit}>제출</button>
    </div>
  );
}

export default Signup;

 

 

 

const express = require("express");
const app = express();

const mysql = require("mysql");
const cors = require("cors");
const multer = require("multer");
const path = require("path");
app.use(cors());

app.use(express.json());
//이거 필요한거임?
app.use(express.static("Images"));

const db = mysql.createConnection({
  user: "*",
  host: "*",
  password: "*",
  database: "*",
});

const upload = multer({
  storage: multer.diskStorage({
    destination: function (req, file, cb) {
      cb(null, "Images/");
    },
    filename: function (req, file, cb) {
      cb(null, new Date().valueOf() + path.extname(file.originalname));
    },
  }),
});
// const upload = multer({
//   dest: "Images/",
//   limits: { fileSize: 5 * 1024 * 1024 },
// });

// app.post("/up", upload.array("img"), (req, res) => {
//   console.log(req.files);
// });

app.post("/submit", upload.single("file"), (req, res) => {
  console.log(req.files, "레큐파일ㄴ");
  console.log(req.body, "레큐바디");
  // console.log(req.body, "레큐바디");
  // const id = req.body.id;
  // const password = req.body.password;
  const profile = req.file;

  console.log(req.file, "파일");
  // res.json({ url: `/img/${req.file.filename}` });
  // FormData의 경우 req로 부터 데이터를 얻을수 없다.
  // upload 핸들러(multer)를 통해서 데이터를 읽을 수 있다

  //   function insertRecord(req, res) {
  // req.files.forEach((e) => {
  // // console.log(e.filename);
  // // });
  // console.log(req.file, "파일");
  // console.log(profile, "이미지");

  db.query(
    "INSERT INTO userlist (userProfile) VALUES (?) ",
    [profile],
    (err, result) => {
      if (err) {
        console.log(err);
      } else {
        res.send("userlist values inserted");
      }
    }
  );
});

app.listen(3001, () => {
  console.log("your server is running on 3001~! yeah");
});

 

문제는 id랑 password를 빼고 보내서 그런지 

 

Error: ER_WRONG_VALUE_COUNT_ON_ROW: Column count doesn't match value count at row 1

오류: ER_WRONG_VALUE_COUNT_ON_ROW: 열 개수가 행 1의 값 개수와 일치하지 않습니다.

이게 뜬다

 

아직 db저장도 안됐고 해결안된게 많지만 이미지를 받아서 행복함...

id랑 password를 같이 받으면 왜 undefined로 뜨는걸까?

따로 해야되는것인가..

 

 

 

아무튼 

header의 역할 ,context Type에 대해 공부하고

https://jw910911.tistory.com/117

formData(json으로 변환하라는 얘기도 있던데...나는 그거 안되던데..왜지?), multer

에 대해 더 공부하고 정리해봐야겠다.

+

app/router차이도 헷갈리니까 확인해놓자.

http://expressjs.com/ko/guide/routing.html

express가져와서 app으로 선언해서 썼는데 검색하다가 코드보면 express.router로 쓰는 게 무슨 차인가 싶어서..

728x90
728x90

scoop는 설치 프로그램

scoop로 설치한 프로그램은 scoop update *로 한번에 업데이트할 수 있음

 

 

파워셸에서 관리자 메뉴로 실행

Set-ExecutionPolicy RemoteSigned -scope CurrentUser

A-예 로 응답.

$env:SCOOP='C:\Scoop'

"환경변수 편집" 검색

새로 만들기 눌러서

변수이름 SCOOP

변수값 C:\Scoop

로 하고

 

다음명령어 실행했는데

 

계속 이 에러 떴음

Running the installer as administrator is disabled by default, see https://github.com/ScoopInstaller/Install#for-admin for details. 

 

(결국 환경변수 편집한거 삭제해봤는데 그게 문제는 아니었음. 하지만 다음 진행하다보니 삭제한 상태에서 깔아버린 나.. 사용자 안에 C:\안에 scoop가 생겼더라고)

 

해결)

관리자모드였던 창 끄고 새로운 power shell 창에서 실행했다

 

iex (new-object net.webclient).downloadstring('https://get.scoop.sh')

node 설치   (-> 이미 설치되어있어서 스킵)

LTS버전이 바람직하다고 함 리액트 네이티브 개발은 Nodejs버전에 영향을 받기 때문에!

에러 나면 나도 다시 깔아야지..

 

scoop install nodejs-lts
node -v

git 설치 -> 이미 설치되어있는데 무심코 깔아버린 나

scoop install git

 

자바8설치

리액트 네이티브 사용해서 안드로이드 앱만들려면 안드로이드 SDK빌드 도구가 필요하다. 근데 앱이 동작하는 안드로이드폰의 운영체제는 자바버전8이다. 자바버전8JDK 설치해야한다

scoop bucket add java

scoop install adopt8-hotspot

에러 뜸 ) Couldn't find manifest for 'adopt8-hotspot'.

자바버전 체크도 안됨

 

해결)

scoop install temurin8-jdk

버전 체크

java -version

 

 

비주얼 스튜디오도 깔려 있어서 넘어가고 

안깔려있따면 이거 하기

더보기

 (이제보니까 여기서 버킷을 하고 했으면 다음에 문제 없었겠구만!)

scoop bucket add extras
scoop install vscode

 

 

 

안드로이드 스튜디오와 개발도구인 안드로이드 SDK 설치할거야

scoop install android-studio android-sdk

에러) Couldn't find manifest for 'android-sdk'.

 

해결 )

scoop bucket add extras

 

다시 설치 실행

scoop install android-studio android-sdk

 

근데 스튜디오는 중간에 끊김..

다시 설치~

scoop install android-studio

 

 

휴~~

 

<에러에  도움 준 글>

https://www.pabburi.co.kr/content/javascript/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B8%B0%EB%B0%98-%EB%A6%AC%EC%95%A1%ED%8A%B8%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C-%EC%9C%88%EB%8F%84%EC%9A%B010-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EC%84%A4%EC%A0%95/

 

728x90
728x90

노마드코더 강의 보는중

 

리액트 네이티브는 브라우저가 없음, 웹사이트가 아니야!

 

앱개발하는데 필요한 java 등등 깔아줄게 많음

 

그래서 강의에서는 네이티브 코드 바로 시작할 수 있게 expo 써서 한다.

핸드폰에 expo앱깔면 연동으로 보이네 신기하다

(expo 설치 내용 https://docs.expo.dev/)

 

( https://snack.expo.dev/ 여기서 작업하면 visual studio도 필요없고 node, npm 설치 안했어도 바로 테스트할 수 있음)

 

 

리액트 네이티브는 웹사이트가 아님!

HTML이 아니기 때문에 div쓸 수 없음

대신에 view를 씀 얘는 container컨테이너다 (react Native에서 import해와야 쓸 수 있음!)

(The most fundamental component for building UI, View is a container that supports layout with flexbox, style, some touch handling,,,)

 

react native에 있는 모든 텍스트는 text component안에 들어가야한다

border css는 사용불가능하다

 

처음에 react Native는 많은 컴포넌트와 API를 지원했는데 버그많고 비효율적이어서 

빠르게 만드는데 초첨맞추고 두 개를 축소시킴

 

(components와 API의 차이는 무엇인가?>

components는 화면에 렌더링할 항목이다

API는 (운영체제와 소통하는) 자바스크립트 코드이다)

 

reactNative 커뮤니티에서 쓸 수도 있지만

expo가 우리에게 필요한 Package를 제공한다.  https://docs.expo.dev/versions/v44.0.0/sdk/async-storage/

 

여기서는 이미 container View가 Flew container다

모바일에서는 Flex direction 기본값이 colum(열-세로)

(원래 웹에서는 Flex direction 기본값이 Row(행-가로) 였음)

 

레이아웃에서 대부분 width, height안씀. 반응형 페이지 생각해야함!!! 매번화면 달라지는데말여

React Native에서는 flex 비율로 레이아웃 채워서 씀

 

 

 

728x90
728x90

결론>

헤더와 푸터를 만들기 위해서 컴포넌트를 만들었는데

헤더랑 푸터 스크립트 안에 또 <Header/>로 컴포넌트 부르고 있어서 그랬다.

 

 

삽질>

캐시 지우고 

 

컴퓨터 고급 설정으로 메모리 더 사용하게 바꾸고

 

더 큰 메모리 할당하는 방법, 옵션 주는 것도 해봤는데 안됐다. 

 

728x90

+ Recent posts