묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
로그인 시도중 backend 에서 에러가 발생하면서 로그인이 되지 않습니다. 작성한 코드는 강사님이 작성하신 코드와 차이가 없는것 같습니다.
login(option) login(Post) 아래는 backend - log 입니다. Executing (default): SELECT `id`, `email`, `nickname`, `password`, `createdAt`, `updatedAt` FROM `Users` AS `User` WHERE `User`.`email` = 'test@test.com'; Executing (default): INSERT INTO `Users` (`id`,`email`,`nickname`,`password`,`createdAt`,`updatedAt`) VALUES (DEFAULT,?,?,?,?,?); Executing (default): SELECT `id`, `email`, `nickname`, `password`, `createdAt`, `updatedAt` FROM `Users` AS `User` WHERE `User`.`email` = 'test@test.com'; (node:11018) UnhandledPromiseRejectionWarning: Error: Include unexpected. Element has to be either a Model, an Association or an object. at Function._conformInclude (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:383:11) at /Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:319:59 at Array.map (<anonymous>) at Function._conformIncludes (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:319:39) at Function._baseMerge (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:786:10) at Function._defaultsOptions (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:823:17) at Function._injectScope (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:3224:10) at Function.findAll (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:1694:10) at Function.findOne (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:1905:23) at /Users/imac/Desktop/nodebird study/back/routes/user.js:25:56 (node:11018) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2) (node:11018) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. 에러 메세지를 읽은 결과... 원인이 두가지로 생각되는데요 1. routes/user.js 에 route /login 부분의 요소가 연관 모델이 아니다. 2. routes/user.js 에 route /login 함수를 try catch 로 묶어 줘라. 제가 이해한것이 맞는지 모르겠네요.. routes/user.js const express = require('express'); const bcrypt = require('bcrypt'); const passport = require('passport'); const { User, Post } = require('../models'); const router = express.Router(); // 로그인 login // 미들웨어 확장 router.post('/login', (req, res, next) => { passport.authenticate('local', (err, user, info) => { // 서버 에러, 성공, 클라이언트 에러 if (err) { console.error(err); return next(err); } if (info) { return res.status(401).send(info.reasone); // 401: 허가되지 않음 , 403: 금지 } return req.login(user, async (loginErr) => { // passport login error 시 if (loginErr) { console.error(loginErr); return next(loginErr); } const fullUserWithoutPassword = await User.findOne({ where: { id: user.id }, // attributes: ['id', 'nickname','email'], attributes: { exclude: ['password'] }, include: [{ model: Post, attributes: ['id'], }, { medel: User, as: 'Followings', attributes: ['id'], }, { model: User, as: 'Followers', attributes: ['id'], }] }) // res.setHeader('Cookie', 'cxlhy') return res.status(200).json(fullUserWithoutPassword); }); })(req, res, next); }); // 로그아웃 logout router.post('/logout', (req, res) => { req.logout(); req.session.destroy(); // session 에 저장된 쿠키와 id 를 지운다. res.send('ok'); // 로그아웃 성공 }); // 회원가입 signup router.post('/', async (req,res, next) => { // POST /user try { const exUser = await User.findOne({ where: { email: req.body.email, } }); if (exUser) { return res.status(403).send('이미 사용 중인 아이디입니다.'); // 응답 } const hashedPassword = await bcrypt.hash(req.body.password, 12); // 10 ~ 13 - 해쉬화 한다. await User.create({ email: req.body.email, nickname: req.body.nickname, password: hashedPassword, }); // res.json(); // res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000'); // res.setHeader('Access-Control-Allow-Origin', '*'); res.status(200).send('ok'); // res.status(200).send('ok'); 응답 } catch(error) { console.error(error); next(error); // status 500 } }); // router.delete('/', (req,res) => { // DELETE /user // res.json({id: 1 }); // }); module.exports = router; app.js const express = require('express'); const cors = require('cors'); const session = require('express-session'); const cookieParser = require('cookie-parser'); const passport = require('passport'); const dotenv = require('dotenv'); const postAPIRouter = require('./routes/post'); const userAPIRouter = require('./routes/user'); const db = require('./models'); const passportConfig = require('./passport'); dotenv.config(); const app = express(); db.sequelize.sync() .then(() => { console.log('db 연결 성공'); }) .catch(console.error); passportConfig(); app.use(cors({ // origin: 'https://nodebird.com', // https://nodebird.com 에서 온 요청만 허용하겠다. origin: '*', // 모든 요청 허용 // credentials: false, // })); app.use(express.json()); // front server 에서 json 형식으로 데이터를 보냈을때 req.body 안에 data를 넣어준다. app.use(express.urlencoded({ extended: true})); // from submit 했을때 urlencoded 방식으로 변환해준다. app.use(cookieParser(process.env.COOKIE_SECRET)); app.use(session({ saveUninitialized: false, resave: false, secret: process.env.COOKIE_SECRET, })); app.use(passport.initialize()); app.use(passport.session()); app.use('/post', postAPIRouter); app.use('/user', userAPIRouter); app.listen(3065, () => { console.log('서버 실행 중') }); models/user.js module.exports = (sequelize, DataTypes) => { const User = sequelize.define('User', { // Mysql에는 users 테이블 생성 // id가 기본적으로 들어있다. email: { type: DataTypes.STRING(30), // INTEGER: 정수, FLOAT: 소수(실수) BOOLEAN, FLOAT allowNull: false, // 필수 unique: true, // 고유한 값 }, nickname: { type: DataTypes.STRING(30), allowNull: false, // 필수 }, password: { type: DataTypes.STRING(100), allowNull: false, // 필수 }, }, { charset: 'utf8', collate: 'utf8_general_ci' // 한글 저장 }); User.associate = (db) => { db.User.hasMany(db.Post); db.User.hasMany(db.Comment); // Liked user 가 좋아요를 누른 post 를 가져온다.. db.User.belongsToMany(db.Post, { through: 'Like', as: 'Liked' }); db.User.belongsToMany(db.User, { through: 'Follow', as: 'Followers', foreignKey: 'FollowingId'}); db.User.belongsToMany(db.User, { through: 'Follow', as: 'Followings', foreignKey: 'FollowerId'}); }; return User; models/post.js module.exports = (sequelize, DataTypes) => { const Post = sequelize.define('Post', { // Mysql에는 posts 테이블 생성 // id가 기본적으로 들어있다. content: { type: DataTypes.TEXT, allowNull: false, }, // RetweetId }, { charset: 'utf8mb4', collate: 'utf8mb4_general_ci' // 이모티콘 저장 }); Post.associate = (db) => { db.Post.belongsTo(db.User); db.Post.belongsToMany(db.Hashtag, { through: 'PostHashtag'} ); db.Post.hasMany(db.Comment); db.Post.hasMany(db.Image); // user post 테이블간에 like 테이블이 생기고.. as 에 따라서 post.getLikers 처럼 게시글 좋아요.. 누른 user 를 가져온다. // Likers 좋아요를 누른 user 를 가져온다. db.Post.belongsToMany(db.User, { through: 'Like', as: 'Likers' }); db.Post.belongsTo(db.Post, { as: 'Retweet' }) }; return Post; } models/comment.js module.exports = (sequelize, DataTypes) => { const Comment = sequelize.define('Comment', { // Mysql에는 comments 테이블 생성 // id가 기본적으로 들어있다. content: { type: DataTypes.TEXT, allowNull: false, }, // UserId: 1 // PostId: 1 }, { charset: 'utf8mb4', collate: 'utf8mb4_general_ci' // 한글 저장 }); Comment.associate = (db) => { db.Comment.belongsTo(db.User); db.Comment.belongsTo(db.Post); }; return Comment; } sagas/user.js import { all, put, fork, takeLatest, delay, call } from 'redux-saga/effects'; import axios from 'axios'; import { LOG_IN_REQUEST, LOG_IN_SUCCESS, LOG_IN_FAILURE, LOG_OUT_REQUEST, LOG_OUT_SUCCESS, LOG_OUT_FAILURE, SIGN_UP_REQUEST, SIGN_UP_SUCCESS, SIGN_UP_FAILURE, FOLLOW_REQUEST, FOLLOW_SUCCESS, FOLLOW_FAILURE, UNFOLLOW_REQUEST, UNFOLLOW_SUCCESS, UNFOLLOW_FAILURE, } from '../reducers/user'; function followAPI(data) { return axios.post('/api/follow', data); } function* follow(action) { try { // yield put({ // type: 'FOLLOW_REQUEST', // }); // const result = yield call(followAPI, action.data); // ex> const result = yield call(logInAPI, action.data, a, b, c); a, b, c 인자를 추가시 yield delay(1000); // throw new Error('') // 아래 catch 로 넘어간다. yield put({ type: FOLLOW_SUCCESS, data: action.data, }); } catch (err) { yield put({ // put => dispatch 다. type: FOLLOW_FAILURE, data: err.response.data, }); } } function unfollowAPI(data) { return axios.post('/api/unfollow', data); } function* unfollow(action) { try { // yield put({ // type: 'UNFOLLOW_REQUEST', // }); // const result = yield call(unfollowAPI, action.data); // ex> const result = yield call(logInAPI, action.data, a, b, c); a, b, c 인자를 추가시 yield delay(1000); // throw new Error('') // 아래 catch 로 넘어간다. yield put({ type: UNFOLLOW_SUCCESS, data: action.data, }); } catch (err) { yield put({ // put => dispatch 다. type: UNFOLLOW_FAILURE, data: err.response.data, }); } } function signUpAPI(data) { return axios.post( '/user', data); // localhostUrl ( http://localhost:3065 ) + /user } function* signUp(action) { try { // yield put({ // type: 'LOG_IN_REQUEST', // }); const result = yield call(signUpAPI, action.data); // ex> const result = yield call(logInAPI, action.data, a, b, c); a, b, c 인자를 추가시 // yield delay(1000); // throw new Error('') // 아래 catch 로 넘어간다. console.log(result); yield put({ type: SIGN_UP_SUCCESS, // data: result.data, }); } catch (err) { console.error(err); yield put({ // put => dispatch 다. type: SIGN_UP_FAILURE, data: err.response.data, }); } } function logOutAPI() { return axios.post('/api/logout'); } function* logOut() { try { // yield put({ // type: 'LOG_OUT_REQUEST', // }); // const result = yield call(logOutAPI); yield delay(1000); yield put({ type: LOG_OUT_SUCCESS, }); } catch (err) { yield put({ // put => dispatch 다. type: LOG_OUT_FAILURE, error: err.response.data, }); } } function logInAPI(data) { return axios.post('/user/login', data); } function* logIn(action) { try { console.log('saga logIn'); // yield put({ // type: 'LOG_IN_REQUEST', // }); const result = yield call(logInAPI, action.data); console.log(result); // ex> const result = yield call(logInAPI, action.data, a, b, c); a, b, c 인자를 추가시 // yield delay(1000); yield put({ type: LOG_IN_SUCCESS, data: result.data, }); } catch (err) { console.error(err); yield put({ // put => dispatch 다. type: LOG_IN_FAILURE, error: err.response.data, }); } } function* watchFollow() { yield takeLatest(FOLLOW_REQUEST, follow); // take =>logIn 액션이 실행될때까지 기다리겠다. } function* watchUnFollow() { yield takeLatest(UNFOLLOW_REQUEST, unfollow); // take =>logIn 액션이 실행될때까지 기다리겠다. } function* watchLogIn() { yield takeLatest(LOG_IN_REQUEST, logIn); // take =>logIn 액션이 실행될때까지 기다리겠다. } function* watchLogOut() { yield takeLatest(LOG_OUT_REQUEST, logOut); } function* watchSignUp() { yield takeLatest(SIGN_UP_REQUEST, signUp); // take =>logIn 액션이 실행될때까지 기다리겠다. } export default function* userSaga() { yield all([ fork(watchFollow), fork(watchUnFollow), fork(watchLogIn), fork(watchLogOut), fork(watchSignUp), ]); } sagas/index.js // all fork call put delay debounce throttle takeLatest tabkeEvery takeLeding taekMaybe import { all, fork } from 'redux-saga/effects'; import axios from 'axios'; import postSaga from './post'; import userSaga from './user'; import { localhostUrl } from '../config/config'; axios.defaults.baseURL = localhostUrl; export default function* rootSaga() { yield all([ // all 은 배열을 받아서 배열안에 있는 명령들을 한번에 실행 시켜준다. fork(postSaga), fork(userSaga), ]); }; front/config/config.js export const domainUrl = 'http://api.nodebird.com'; export const localhostUrl = 'http://localhost:3065';
-
미해결Vue.js 끝장내기 - 실무에 필요한 모든 것
안녕하세요. 질문이 있습니다.
태그 작성하고 저장하면 자동적으로 포멧팅 하는데 br, img, input 들이 뒤에 /가 붙어서 나오더라구요.. <br/> <img/> <input/> 이렇게요~ 해당 기능을 끌 수 있을까요?? 확인 부탁 드립니다. 감사합니다.
-
미해결홍정모의 따라하며 배우는 C++
random shuffle이 안되는데 이유를 모르겠습니다.
#include <iostream> #include <vector> #include <algorithm> using namespace std; class Cents { private: int m_cents; public: Cents(int cents = 0) { m_cents = cents; } int getCents() const { return m_cents; } int& getCents() { return m_cents; } friend std::ostream& operator << (std::ostream& out, const Cents& cents) { out << cents.m_cents; return out; } }; int main() { vector<Cents> arr(20); for (unsigned i = 0; i < 20; ++i) { arr[i].getCents() = i; } std::random_shuffle(begin(arr), end(arr)); for (auto& e : arr) { cout << e << " "; } cout << endl; return 0; } 강의 내용 그대로 친 것 같은데 random 셔플부분만 std에 존재하지 않는다고 계속 에러나네요.
-
해결됨스프링과 JPA 기반 웹 애플리케이션 개발
엔티티에 저장이 안되는 문제에 대한 문의
안녕하세요. 강의 잘 보았습니다. 강의 도움 받아서 테스트 진행해보고 있는데요. 저장이 안되는 부분에 대해 문의 드려봅니다. Car, Camp 엔티티가 있고 Car 전체 데이터 읽어서 특정 필드의 값을 Camp 에서 찾아서 업데이트하는 로직입니다. if (carRepository.count() > 0) { carRepository.findAll().stream().forEach(s -> { String campName = s.getCampEngName(); Optional<Car> car = carRepository.findById(s.getId()); Camp camp = campRepository.findByEngName(campName); if (camp != null) { car.ifPresent(m -> m.setNote(camp.getKorName())); } });} 해당 부분 코드는 이렇게 했는데, 수행 후에 실제 Car 엔티티의 note 값이 변경이 안되어있습니다. 로그 찍어보면 campName 값은 일일이 잘 가져오고 있는데 setNote로 저장이 안됩니다. 트랜젝션 문제일까요? 강의를 제대로 소화를 못했는지 원인을 못찾겠네요. ㅠㅠ 도움 부탁드립니다. 아.. 저게 수행되는 곳이, 일반 컨트롤러 통해서 들어오는게 아니라 최초 실행시점입니다.(혹시 이게 문제일까요?) @PostConstruct public void initCarData() throws IOException { ... if (carRepository.count() > 0) { } ... } 이 부분입니다.
-
미해결홍정모의 따라하며 배우는 C언어
디버깅에 대하여
강의를 따라 해보는데 강의처럼 구현이 되지 않습니다. 어떻게 해야 될까요.
-
미해결쉽고 자연스럽게 배워보는 Javascript 입문 - 코드스쿼드 마스터즈 코스 레벨1
질문은 아니구 5:40 쯤 수정하실때
(에디터마다 상이하겠지만 서브라임 텍스트 기준) - , * , / 두개씩 수정하시는 부분 1. 첫번째 '-' 옆에 커서 넣고 2. ctrl 키 3. 두번째 '-' 옆에 커서 넣고 수정하시면 한번에 수정가능해요! 업무나 기타 프로그램 이용에 참고하세요~~~ -지나가던 웹디 + 초보 퍼블리셔-
-
미해결홍정모의 따라하며 배우는 C언어
소수끼리의 몫과 나머지
예를들어 5.4 나누기 1.05의 몫과 나머지를 구하는 연산자는 뒤에 나오나요? (while 문으로 계속해서 빼는 방식으로 프로그램을 만들 수는 있어보이네요)
-
미해결현존 최강 크롤링 기술: Scrapy와 Selenium 정복
scrapy shell
scrapy shell로 해서 하나하나 response 결과를 확인할때는 잘 파싱되서 결과값이 나오는데, 전체 scrapy를 생성해서 crawl 돌리면 400 HTTP status code is not handled or not allowed 이 나는건 왜 때문인가요...?
-
윤재성의 만들면서 배우는 Spring MVC 5
이미지의 경로
삭제된 글입니다
-
미해결파이썬 알고리즘 문제풀이 입문(코딩테스트 대비)
sum1과 sum2 초기화 과정에 대한 문의
안녕하세요 선생님 명쾌한 강의를 해주셔서 항상 감사합니다. 다름이 아니오라 sum1과 sum2 초기화 과정에 대한 과정에 대해 질문드릴 사항이 한가지 있습니다. 사진에서 표기한 2)인 대각선을 위한 sum1과 sum2의 초기화 과정이 1)의 과정과 달리 for반복문 밖에 작성하는지궁금합니다. 실제로 대각선을 구하는 for안에 넣어보니 -1이 된 154가 출력되는 것을 확인할 수 있었습니다. 어떠한 이유때문에 155가 아닌 154출력 되었으며 어째서 for문 안이 아닌 밖에서 초기화 과정이 이루어지는지 궁금합니다.
-
미해결현존 최강 크롤링 기술: Scrapy와 Selenium 정복
scrapt shell re() 정규표현 적용시 에러
강사님이 알려주신데로 re를 쓰게되면 이런 에러가 나는데 방법이 있을까요...?
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
선생님의 github 예시로 가입/로그인을 해도 에러가 납니다.
안녕하세요. 제가 작업한 작업물에서 오류를 해결하지 못해서 선생님의 작업물을 받아서 돌려보았는데요, 추가한 건 dev.js(제가 쓰던 파일을 그대로 복사해서 사용했습니다.) root와 cilent애 전부 npm install 해주었고, 추가로 bcrypt 오류가 떠서 npm install bcrypt --save 해주었는데, 콘솔창에서 에러가 뜨지는 않지만, 알림창으로 Failed to sign up이라고 뜨는 것으로 보아 dispatch(registerUser(body)) .then(response => { if (response.payload.success) { props.history.push("/login") } else { alert("Failed to sign up") } }) 이 부분에서 계속 돌고 있는 것 같습니다. 다른 분들은 질문을 하시지 않은 것으로 봐서 제 로컬 문제 같은데요... 리덕스 구축할 때 혹시 로컬에서 확인해야 할 부분이 있으면 다시 짚어주시면 감사하겠습니다.
-
미해결프로그래밍 시작하기 : 파이썬 입문 (Inflearn Original)
튜플 리스트로 형 변환 활용
튜플을 리스트로형 변환 해서 튜플 값을 수정하거나 삭제하는 코드를 간단하게 보여주실 수 있을까요? 지금 막 해보는데 잘 안되네요..ㅠㅠ
-
미해결인터랙티브 웹 개발 제대로 시작하기
키다운-업 연속 시 캐릭터에 .running class
안녕하세요 강사님. 26강까지 다 듣고, 강사님이 주신 원본이랑 비교까지 다 했는데도 궁금한 점이 있어서요! 다름이아니라, 제 파일에서 키다운 이벤트 시, 키코드 37번과 39번은 문제없이 작동하는데, 위 아래 키보드를 클릭하면 running클래스가 랜덤하게 작동합니다. 1. forward 시에 running클래스 정상작동, 얼마 안가서 backward시 running이 붙지 않고, 돌아옵니다. 2. forward로 끝까지 갔다가 backward시에는 running이 붙었다가 중간에 또 forward와 backward를 반복하면 running이 붙지 않은채 움직입니다. 원본 파일에서 개발자 코드를 켜놓고 character 클래스를 볼 때도, forward에는 running이 붙다가 backward에는 running이 붙지 않고 돌아오는데, 이 부분 해결방법 여쭤봅니다. 저는 크롬이랑, 웨일에서 개발자도구를 실행시켰습니다. 감사합니다!
-
미해결페이스북 클론 - full stack 웹 개발
댓글 순서
안녕하세요 강사님! 강의 잘 듣고 있습니다. 질문은 아니고 그냥 제가 생각했던 문제가 해결되어서 남겨봅니다. 동영상 끝부분에 댓글을 달아서 보여주시는 부분을 하다가, 새로운 댓글들이 위쪽으로 달리는 것을 보고 이상하게 느꼈습니다. 대부분이 새로운 댓글들이 아래로 달리지 않나 합니다. 그래서 찾아본 결과 post_list.html 파일에 for문, 즉 {% for comment in post.comment_set.all %} 이 부분에서 끝에 reversed 를 달아 {% for comment in post.comment_set.all reversed %} 이런식으로 바꾸면 for문이 반대로 돌아 댓글들 순서가 반대로 되어 순차적으로 댓글들이 달리게 됩니다. 그리고 insertAdjacentHTML에서 'afterend'를 쓰니 제 마음에 딱 드는 방식으로 바뀌게 되었습니다. 더 좋은 방법이 있다면 알려주세요! 혹시나 저처럼 이상하게 생각하신 분들이 있을까봐 질문 남겨요 :)
-
미해결예제로 배우는 스프링 입문 (개정판)
"}"은(는) 예상되지 않았습니다.
win에서 .\mvnw package를 terminal에 검색하면 "}"은(는) 예상되지 않았습니다. 라는 오류가 뜹니다. JAVA_HOME은 C:\Program Files\Java\jdk1.8.0_231 이고 Path는 C:\Program Files\Java\jdk1.8.0_231\bin\ 입니다.
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
흑흑...왜 EMPTY_RESPONSE 에러가 나는 걸까요?
왜 EMPTY_RESPONSE 에러가 나는 걸까요?... 정말 갈길이 험난하네요...
-
미해결홍정모의 따라하며 배우는 C++
같은 함수를 두 번 정의했을 때 에러가 뜨는 건 식별자 문제인가요?
제가 이해한 바로는, 이미 한 번 같은 이름으로 메모리 공간이 할당되었는데 다시 같은 이름이 쓰이게 되면 충돌 같은 게 일어나 에러가 뜨게 되는 것 같은데 이렇게 되는 게 맞나요? 아니면, 컴파일러가 이 상황 자체를 비정상적이라고 인지해서 프로그래머에게 알려주는 건가요? 또, 어떤 local scope 안에서 같은 이름으로 변수 또는 함수가 여러 번 선언되었을 때에도 같은 원리로 컴파일 에러가 뜨게 되나요?
-
미해결자바스크립트 비기너: 튼튼한 기본 만들기
A가 왜 TRUE 인가요?
문자열은 TRUE로 보는건가요?
-
홍정모의 따라하며 배우는 C++
.cpp와 .h를 분리하는 것이 어떤 면에서 좋은 건가요?
삭제된 글입니다