inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지

테이블 관계 정의하기

질문 부탁드립니다

238

김윤진

작성한 질문수 19

0

로그인만 구현해볼려고 하는데요

index.js

const Sequelize = require('sequelize');
const env = process.env.NODE_ENV || 'development';
const config = require('../config/config')[env];
const User = require('./user');

const db = {};
const sequelize = new Sequelize(
config.database, config.username, config.password, config,
);

db.sequelize = sequelize;
db.User = User;

User.init(sequelize);

User.associate(db);

module.exports = db;

user.js

const Sequelize = require('sequelize');

module.exports = class User extends Sequelize.Model {
static init(sequelize){
return super.init({
number: {
type: Sequelize.STRING(11),
allowNull: true,
unique: true,
},
password: {
type: Sequelize.STRING(100),
allowNull: false,
},
birth: {
type: Sequelize.STRING(8),
allowNull: false,
},
provider: {
type: Sequelize.STRING(10),
allowNull: false,
defaultVaue: 'local',
},
gender: {
type: Sequelize.TEXT(''),
allowNull: false,
}
},{
sequelize,
timestamps: true,
underscored: false,
modelName: 'User',
tableName: 'Users',
paranoid: true,
charset: 'utf8',
collate: 'utf8_general_ci',
});
}
}

app.js는 똑같이 했습니다

/Users/yunjin/Desktop/mine/wapeProject/server/models/index.js:17

User.associate(db);

     ^

TypeError: User.associate is not a function

    at Object.<anonymous> (/Users/yunjin/Desktop/mine/wapeProject/server/models/index.js:17:6)

    at Module._compile (node:internal/modules/cjs/loader:1109:14)

    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1138:10)

    at Module.load (node:internal/modules/cjs/loader:989:32)

    at Function.Module._load (node:internal/modules/cjs/loader:829:14)

    at Module.require (node:internal/modules/cjs/loader:1013:19)

    at require (node:internal/modules/cjs/helpers:93:18)

    at Object.<anonymous> (/Users/yunjin/Desktop/mine/wapeProject/server/app.js:11:23)

    at Module._compile (node:internal/modules/cjs/loader:1109:14)

    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1138:10)

[nodemon] app crashed - waiting for file changes before starting...

이렇게 오류가 발생했습니다

그리고 프론트에서 보낸 유저 정보를 어디서 받는지 

잘 모르겠습니다

감사합니다!

Sequelize mongodb mysql nodejs

답변 1

1

제로초(조현영)

static associate 메서드를 안 만드셔서 에러가 난 겁니다.

프론트에서 보낸 유저 정보는 라우터의 req.body에서 받은 후 passport로 보냈습니다.

0

김윤진

const Sequelize = require('sequelize');

module.exports = class User extends Sequelize.Model {
static init(sequelize){
return super.init({
number: {
type: Sequelize.STRING(11),
allowNull: true,
unique: true,
},
password: {
type: Sequelize.STRING(100),
allowNull: false,
},
birth: {
type: Sequelize.STRING(8),
allowNull: false,
},
provider: {
type: Sequelize.STRING(10),
allowNull: false,
defaultVaue: 'local',
},
gender: {
type: Sequelize.TEXT(''),
allowNull: false,
}
},{
sequelize,
timestamps: true,
underscored: false,
modelName: 'User',
tableName: 'Users',
paranoid: true,
charset: 'utf8',
collate: 'utf8_general_ci',
});
}

static associate(db){
 
}
}


user.js 에 associate 안에를 비워놯도 괜찮은가요?

그리고 혹시 프론트에서 axios를 통해 서버로 보낼때 이렇게 작성하는 것이 어디가 틀린지 잘 모르겠어서 질문드립니다

function postUserInfo(){
 
axios({
method: "POST",
url: '../../routes/auth',
data: {
"number": "userNum",
"password": "userPass",
"birth": "userBirth",
"gender": "userGender"
},
withCredentials: true
}).then((res)=>{
console.log(res);
}).catch(error =>{
$joinError.textContent = "입력한 정보가 올바르지 않습니다";
console.log(error);
})

1

제로초(조현영)

네 비워놔도 상관 없습니다. 프론트에서 보내는 데이터가 진짜로 저것은 아니죠? 정보보호를 위해 바꾸신거죠? URL은 서버 주소를 적으셔야 합니다. 폴더 경로가 아닙니다.

0

김윤진

넵 감사합니다
프론트에서 보내는 정보는 변수처리해서 input에 입력하면 들어가게 했습니당

0

김윤진

안녕하세요 오류가 발생해서 질문 드립니다

프론트에서 보내는 코드

axios({
method: "POST",
url: "http://localhost:8880",
data: {
"number": "userNum",
"password": "userPass",
"birth": "userBirth",
"gender": "userGender"
},
withCredentials: true
}).then((res)=>{
console.log(res);
}).catch(error =>{
$joinError.textContent = "입력한 정보가 올바르지 않습니다";
console.log(error);
})

서버에서 받는 코드 auth.js

router.post('/join', async(req, res, next)=>{
const { number, password, birth, gender } = req.body;
try{
const exUser = await User.findOne({where : {number}});
if(exUser){
return res.redirect('/join?error=exist');
}
const hash = await bcrypt.hash(password, 12);
await User.create({
number,
password: hash,
birth,
gender,
});
return res.redirect('/');
}catch(error){
console.error(error);
return next(error);
}
});

발생 오류

그리고 추가로 궁금한 게 

만약 url을 localhost8880 저렇게 적는 것이 맞다면

서버에서 어떻게 프론트에서 보낸 정보를 알 수 있는지 모르겠습니다

검색해도 요청 보내는 법 받는 법 이런 것 밖에 나오질 않네요..

 

 

 

 

 

0

제로초(조현영)

서버 주소가 저게 아닌 것 같은데요? post '/join'으로 만드셨잖아요 그러면 localhost:8080/join이 되어야죠. 다시 한 번 말씀드리지만 폴더경로가 아닙니다. 서버에다 직접 만든 논리적 주소입니다.

요청에서 보낸 데이터는 bodyParser를 통해 파싱(해석)되어서 req.body에 들어갑니다.

0

김윤진

감사합니다!
질문 많이 해서 죄송합니다만
앞으로 많이 할것 같습니다..

0

김윤진

안녕하세요

CORS 문제가 발생해 해결해볼려고 시도 했습니다

검색해보니 프론트에서 해결 하는 것보단 서버에서 해결하는 것이 쉽다고 해서

npm i cors 하고 app.js에

const cors = require('cors');
 

 

app.use(cors({
origin: 'http://localhost:8880/',
credentials: true
}))

했더니 결과는 같았습니다

그래서

auth.js에 

const cors = require('cors');
 
router.post('/join', cors(),async(req, res, next)=>{
const { number, password, birth, gender } = req.body;
try{
const exUser = await User.findOne({where : {number}});
if(exUser){
return res.redirect('/join?error=exist');
}
const hash = await bcrypt.hash(password, 12);
await User.create({
number,
password: hash,
birth,
gender,
});
return res.redirect('/');
}catch(error){
console.error(error);
return next(error);
}
});

이렇게 해봤지만 실패했습니다

그래서 더 검색해보니 프론트 input에서 보내는 데이터는

Context-Type이 application/json  이고

서버로 보낼 때는 

Context-Type이 application/x-www-from-urlencoded 여야 한다고 하는 것 같습니다

그래서 처음엔

axios({
method: "POST",
url: "localhost:8880/join",
data: encodeURIComponent({
number: "userNum",
password: "userPass",
birth: "userBirth",
gender: "userGender"
}),
// withCredentials: true
}).then((res)=>{
console.log(res);
}).catch(error =>{
$joinError.textContent = "입력한 정보가 올바르지 않습니다";
console.log(error);
})
}

이렇게 encode 해봤지만 실패했고

더 검색해보니 헤더를 추가하라고 하는데 그 다음부터 무슨말인지 모르겠어서 질문 드립니다

감사합니다

참고 사이트 : https://gist.github.com/jays1204/703297eb0da1facdc454

 

 

 

0

제로초(조현영)

axios url 앞에 http:// 붙여보세요. Content-Type은 말도 안되는 소리니 무시하세요. 주소가 같으면 cors도 필요없습니다.

0

김윤진

안녕하세요 http:// 붙이면 처음 문제인 404 에러가 발생합니다

제로초님 블로그에 있는 CORS 설명하신거 보고 따라해 봤습니다

 

크롬 등의 브라우저는 localhost에서는 CORS 요청이 안 되도록 막아두기도 하여 저렇게 허용을 해줘도 안 될 수도 있습니다. localhost의 경우에는 안 돼도 너무 당황하지 맙시다.

또한 CORS 외에도 CORB(cross origin read blocking) 현상도 있습니다. CORS를 허용했더라도 POST, PUT, DELETE 요청에서 json을 전송하는 경우 요청이 차단됩니다. 이럴 때는 json 대신 www-form-urlencoded 형식으로 데이터를 보내면 됩니다.

 

이렇게 말씀하셔서 

코드는


axios({
url: "localhost:8880/join",
method: "POST",
// contentType: application/x-www-form-urlencoded, encodeURIComponent
data: encodeURIComponent({
number: "userNum",
password: "userPass",
birth: "userBirth",
gender: "userGender"
}),
// withCredentials: true
}).then((res)=>{
console.log(res);
}).catch(error =>{
$joinError.textContent = "입력한 정보가 올바르지 않습니다";
console.log(error);
})
}

에러

혹시 request header에 

Accept와 Context-Type이 둘다 

application/json 이거나 

application/x-www-form-urlencoded 여야 하나요?

일단 시도해 본것은 프론트에서 보낼 데이터 앞에 encodeURIComponent

이거를 지우고도 해봤는데 실패했습니다

블로그에 있는 방법 다 해봤는데 왜그럴까요?

로컬호스트라서 그냥 불가한거 일까요? 

감사합니다!

 

 

 

0

제로초(조현영)

http:// 붙이셔야하고요. cors랑 상관없는 에러입니다. content-type이랑도 상관없고요. 404 에러가 뜨는건 서버 주소를 잘못 적으셔서 그런겁니다. /join 앞에 뭘 더 적으셔야할텐데요. 제 강좌에 router.use랑 주소 합쳐진다고 했던거 기억하시나요?

0

김윤진

넵 그래서 url 코드를 http://localhost:8880/auth/join

이렇게 적었더니

500 Internal Server Error
 

500 에러가 발생했습니다

산 넘어 산이네요..

 

Request Payload를 보니 데이터는 정상적으로 들어가 있어

서버쪽 문제 인것 같습니다

제가 코드를 잘못 적은 걸까요? 똑같이 따라치긴했습니다

app.js

app.use('/', loginRouter);
app.use('/auth', authRouter);

auth.js


router.post('/join', async(req, res, next)=>{
console.log("AA")
const { number, password, birth, gender } = req.body;
try{
const exUser = await User.findOne({where : {number}});
if(exUser){
return res.redirect('/join?error=exist');
}
const hash = await bcrypt.hash(password, 12);
await User.create({
number,
password: hash,
birth,
gender,
});
return res.redirect('/');
}catch(error){
console.error(error);
return next(error);
}
});

 

0

제로초(조현영)

서버에사 에러가 났으니 서버 에러 메시지를 주셔야죠

0

김윤진

이렇게 왔습니다

0

제로초(조현영)

서버 에러 메시지는 서버 콘솔에서 보셔야죠

0

김윤진

아항..

첫번째 줄 해석해보니 기본엔진이 지정되어 있지 않아 확장이 제공되지 않았다고 뜹니다

제 생각으로는 app.set('view engine', 'html')

이 코드를 작성하지 않아 그런 것 같습니다

 

이 코드 추가해서 시도해보니 'html' 모듈을 찾을 수 없다고 나옵니다

흠..여기서 어떻게 해야할까요?

0

제로초(조현영)

html은 ejs같은 뷰 엔진이 아닙니다. html은 res.sendFile해주면 되므로 뷰 엔진을 설정할 필요가 없습니다.

그리고 위에 provider cannot be null도 provider 자리에 null이 들어가서 그렇습니다. 값을 넣으세요.

0

김윤진

안녕하세요

 

mysql workbenrch user table입니다

local이 provider인데 provider는 제대로 들어간거 맞나요?

 

오류는 동일하게 발생합니다

No default engine was specified and no extension was provided.

provider를 이렇게 했는데 왜 null이 나오는 걸까요?

500에러가 발생했는데 왜 데이터베이스에 들어갈 수 있는건갸요?

그리고 보여주고 싶은 html들을 views 폴더에 꼭 넣어야 하는건 아니죠?

provider: {
type: Sequelize.STRING(10),
allowNull: false,
defaultValue: 'local',
},

추가로

const router = express.Router();
//cors({ origin: 허용 오리진 주소 }) 나중에 실제 도메인에 올릴 땐 이렇게
router.post('/join', async(req, res, next)=>{
console.log("AA")
const { number, password, birth, gender } = req.body;
try{
const exUser = await User.findOne({where : {number}});
if(exUser){
// return res.redirect('/join?error=exist');
return res.status(406).json({message: "Same ID"})
}
const hash = await bcrypt.hash(password, 12);
await User.create({
number,
password: hash,
birth,
gender,
});
return res.redirect('/');
}catch(error){
console.error(error);
return next(error);
}
});

회원가입하려는 id가 이미 존재한다면

프론트로 보내주는 코드를  return res.status(406).json({message: "Same ID"})

적었는데 406오류는 가는데 json은 가지 않습니다

왜그런건가요?

 

0

제로초(조현영)

provider를 이렇게 했는데 왜 null이 나오는 걸까요?

500에러가 발생했는데 왜 데이터베이스에 들어갈 수 있는건갸요?

- 데이터 안 들어갔습니다. 기존에 들어간 건 provider를 제공해서 문제가 없고, 새로 넣은게 안 들어간 겁니다.

No default engine was specified and no extension was provided.

- 소스코드 중에 res.render 쓰고 있는게 있나요? 그러면 다시 뷰 엔진 연결하셔야 합니다.

그리고 보여주고 싶은 html들을 views 폴더에 꼭 넣어야 하는건 아니죠?

- 템플릿 파일만 views에 넣는겁니다(res.render). html은 정적파일이라서 아무데나 넣고 쓰시면 됩니다(res.sendFile).

적었는데 406오류는 가는데 json은 가지 않습니다 왜그런건가요?

- json 갔을겁니다. 받는 부분 코드가 문제거나, 페이지가 이동되는 요청이라 받을 수 없었을 겁니다. 다시 말씀드리지만 return res.redirect('/join?error=exist'); 이게 답입니다.

제 강좌에 이렇게 해서 프론트에서 에러 메시지 띄우는 것까지 전부 다 있습니다.

0

김윤진

감사합니다 모두 해결되었습니다!

리눅스 노드 설치시 패키지

0

172

0

socket.js 에서 referer로부터 roomId를 가져올 때

0

926

3

스트리밍 방식으로 대용량 파일 업로드 & 다운로드 관련 질문

0

2297

2

a[title] 질문드립니다

0

386

1

리뉴얼 강의 및 공부 방법

0

589

1

jwt decode

0

1137

1

node.js 교과서 3판 질문드립니다

0

396

1

passport와 jwt

0

438

1

리뉴얼 강의

0

427

2

혹시 Node.js 교과서 3판 이북은 언제 나오나요?

0

359

1

몽고디비 사용자도 MYSQL부분을 들어야 하나요???

0

488

1

sql 쿼리 로그는 어떤 모듈이 작성하나요?

0

511

2

nunjucks res.render('error'); 작동을 안합니다.

0

518

1

질문있습니다.

0

348

1

multer 한글 파일 업로드시 파일명이 깨져요.

1

3543

1

수업자료는 어디있나요?

0

374

1

질문 있습니디

0

244

1

multer 사용시 file 외 name값은 못받나용?

0

429

1

코드 중복 부분 질문드립니다.

0

303

1

api 만드는 이유 질문드립니다.

0

292

1

Strategy의 done에 대해 질문드립니다.

0

373

1

안녕하세요 fs 권한 관련 질문드립니다

0

455

1

시퀄라이즈 연결질문...

0

510

2

res.setHeader vs res.cookie

0

1797

3