무료
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
dispatch(loginUser(body))
dispatch(loginUser(body)) 로 인자를 LoginPage.js 에서 user_action.js 로 넘겨준건데 왜 Loginpage.js 에서 user_action.js를 import받는거죠? 원래대로라면 export아닌가요..?ㅠ
- 미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
if(err) throw err 과 req.token = token 에 대한 질문입니다
auth.js에서 User.findByToken(token, (err, user) => { if(err) throw err; if(!user) return res.json({isAuth: false, error: true}) req.token = token; req.user = user; next(); }) 이곳에서 if(err) return err 가 아닌 throw err 를 하는 이유가 있나요? 그리고, req.token에 token 을 넣어주고, req.user에 user를 넣어주는 이유도 궁금합니다. token과 user는 변한 것이 없지 않나요? 감사합니다!
- 미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
Route.get() requires a callback function but got a [object Object]
인자를 객체로 넘겼다고 에러가 뜨는데, auth를 구현하는 app.get에서 자꾸 문제가 있다고 합니다. 오타는 도저히 못찾겠는데,, 문제가 무엇일까요 const express = require('express') const app = express() const port = 5000 const bodyParser = require('body-parser'); const { User } = require("./models/User"); const config = require('./config/key'); const cookieParser = require('cookie-parser'); const auth = require('./middleware/auth'); // application / x-www-form-urlencoded app.use(bodyParser.urlencoded({extended : true})); // application / json app.use(bodyParser.json()); app.use(cookieParser()); const mongoose = require('mongoose'); //mongoDB 연결 mongoose.connect(config.mongoURI,{ useNewUrlParser: true, useUnifiedTopolongy: true, useCreateIndex: true, useFindAndModify: false }).then(() => console.log('MongoDB connected !')) .catch(err => console.log('MongoDB Error !')); //Hello world 출력 app.get('/', (req, res) => { res.send('Hello World!') }); //register 라우트 app.post('/api/users/register', (req, res) => { // 회원가입 할 때 필요한 정보들을 client으로부터 받아오면 // 그것들을 database에 넣어준다. const user = new User(req.body) user.save((err, userInfo) => { if(err) return res.json({ success : false, err }) return res.status(200).json({ success: true }); }); }); // login 라우트 app.post('/api/users/login', (req, res) => { // console.log('ping') //요청된 이메일을 데이터베이스에서 있는지 찾는다. User.findOne({ email: req.body.email }, (err, user) => { // console.log('user', user) if (!user) { return res.json({ loginSuccess: false, message: "제공된 이메일에 해당하는 유저가 없습니다." }) } //요청된 이메일이 데이터 베이스에 있다면 비밀번호가 맞는 비밀번호 인지 확인. user.comparePassword(req.body.password, (err, isMatch) => { // console.log('err',err) // console.log('isMatch',isMatch) if (!isMatch) return res.json({ loginSuccess: false, message: "비밀번호가 틀렸습니다." }) //비밀번호 까지 맞다면 토큰을 생성하기. user.generateToken((err, user) => { if (err) return res.status(400).send(err); // 토큰을 저장한다. 어디에 ? 쿠키 , 로컳스토리지 res.cookie("x_auth", user.token) .status(200) .json({ loginSuccess: true, userId: user._id }) }) }) }) }) // auth 라우트 (미들웨어로 사용될 것입니다.) app.get('/api/users/auth', auth, (req, res) => { //여기 까지 미들웨어를 통과해 왔다는 얘기는 Authentication 이 True 라는 말. res.status(200).json({ _id: req.user._id, isAdmin: req.user.role === 0 ? false : true, isAuth: true, email: req.user.email, name: req.user.name, lastname: req.user.lastname, role: req.user.role, image: req.user.image }) }) app.get('/api/users/logout', auth, (req, res) => { // console.log('req.user', req.user) User.findOneAndUpdate({ _id: req.user._id }, { token: "" } , (err, user) => { if (err) return res.json({ success: false, err }); return res.status(200).send({ success: true }) }) }) // 포트를 통해 index.js 를 실행합니다. app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`) }); 위는 index.js const { User } = require('../models/User'); let auth = (req, res, next) => { //인증 처리를 하는곳 //클라이언트 쿠키에서 토큰을 가져온다. let token = req.cookies.x_auth; // 토큰을 복호화 한후 유저를 찾는다. User.findByToken(token, (err, user) => { if (err) throw err; if (!user) return res.json({ isAuth: false, error: true }) // console.log('userh', user) req.token = token; req.user = user; next(); }) } module.exports = { auth }; auth.js // 모듈 (User에서는 데이터 베이스를 위한 몽구스, 유저의 비밀번호 암호화를 위한 비크립트, 유저의 개개인 토큰을 얻기 위한 제이슨웹토큰을 가져온다.) const mongoose = require('mongoose'); const bcrypt = require('bcrypt'); const jwt = require('jsonwebtoken'); // 비밀번호 암호화를 위한 salt 값 설정. salt 값은 암호화된 비밀번호를 해킹하기 어렵게 만들 수 있음. const saltRounds = 10; // 유저의 정보들을 객체화, 이른 바 유저 스키마를 생성한다. ( 몽구스의 메소드 ) // 각 유저들의 이름, 이메일, 비밀번호 등 개인정보를 담기 위한 객체임. const userSchema = mongoose.Schema({ name : { type: String, maxlength: 50 }, email : { type: String, trim: true, unique: 1 }, password : { type: String, minlength: 5 }, lastname : { type: String, maxlength: 50, }, role : { type: Number, default: 0 }, token: { type: String, }, tokenExp: { type: Number }, image : String }) // 유저 스키마 이전에 실행될 것임. userSchema.pre('save', function (next) { var user = this; if (user.isModified('password')) { //비밀번호를 암호화 시킨다. bcrypt.genSalt(saltRounds, function (err, salt) { if (err) return next(err) bcrypt.hash(user.password, salt, function (err, hash) { if (err) return next(err) user.password = hash next() }) }) } else { next() } }) // comparePassword 라는 이름의 유저 스키마 메소드를 생성합니다. ( 당연히 비밀번호 비교를 위한 메소드이겠지요? ) userSchema.methods.comparePassword = function (plainPassword, cb) { //plainPassword 1234567 암호회된 비밀번호 $2b$10$l492vQ0M4s9YUBfwYkkaZOgWHExahjWC bcrypt.compare(plainPassword, this.password, function (err, isMatch) { if (err) return cb(err); cb(null, isMatch); }) } userSchema.methods.generateToken = function (cb) { var user = this; // console.log('user._id', user._id) // jsonwebtoken을 이용해서 token을 생성하기 var token = jwt.sign(user._id.toHexString(), 'secretToken') // user._id + 'secretToken' = token // -> // 'secretToken' -> user._id user.token = token user.save(function (err, user) { if (err) return cb(err) cb(null, user) }) } userSchema.statics.findByToken = function(token, cb) { var user = this; // 토큰을 decode 한다. jwt.verify(token, 'secretToken', function(err, decoded) { // 유저 아이디를 통해서 유저를 찾은 다음에 // 클라이언트에서 가져온 token과 DB에서 가져온 토큰이 일치하는지 확인합니다. user.findOne({ "_id" : decoded, "token" : token }, function(err, user) { if(err) return cb(err); cb(null, user); }) }) } // 유저스키마 => User 라는 이름으로 모델화. const User = mongoose.model('User', userSchema); // 방금 모델화한 User 밖에서도 사용가능하도록 exports. module.exports = { User }; user.js 입니다. 문제가 무엇일까요, ㅠ
- 미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
module.exports = { auth } 에 대한 질문입니다.
안녕하세요 선생님, auth.js의 마지막 부분에 있는 module.exports = { auth } 에서 {} 를 빼먹었다가 에러가 났는데요, 왜 꼭 {}를 붙여야 작동이 되는 것인지 궁금합니다.
- 해결됨따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
질문드립니다 ㅠㅠㅠ
안녕하세요 선생님 좋은 강의 감사합니다ㅠㅠㅠ 열심히 수강하고 있는 취준생인데요 hoc/auth에 return <SpecificComponent {...props} />; 을 리턴해 주는게 LoginPage나 RegisterPage는 왜 적용하지 않는지 질문 드려도 될까요 ...ㅠㅠ
- 미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
로그인 구현시 자꾸 비밀번호가 틀렸다고 나옵니다..
안녕하세요 선생님. 강의 잘 보고 있습니다. 감사합니다. bcrypt.compare(plainpassword, this.password, function(err, isMatch){ console.log(isMatch); // 비밀번호가 다르다면 // callbackfunction에 err를 넣어 return if(err) return callbackfunction(err); // 비밀번호가 같다면 // isMatch는 true값임, err는 없으므로 unll값을 넣는다 callbackfunction(null, isMatch); }) 이와 같은 코드에서 isMatch가 undefined로 출력됩니다. 비밀번호를 맞는 비밀번호로 입력하여도 undefined로 출력이 되는데, 어떤게 잘못 되었는지 알 수 있을까요? 저의 깃허브 주소는 https://github.com/onejaejae/SignUp입니다 !!
- 미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
User.findOne({ email: req.body.email }, (err, user) => { 할때
req.body.email 을 user.email 로 하면 안되는건가요? const user = new User(req.body); 로 객체를 만들었으니 req.body = user 가 되는게 아닌가요? 그리고 User.findOne({ email: req.body.email }, (err, user) => 여기서 어떻게 err은 에러가 되고 user는 user가 되는지 원리가 궁금합니다 ㅜ 어디서 받아오는 값인가요?
- 미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
div 줄바꿈 문의
안녕하세요~ 제가 배운 html 지식으로는 div 쓰면 자동 줄바꿈이 되는 것으로 아는데 행으로 길게 나와서 세로로 나오는 방법 문의드립니다. 늘 감사합니다.
- 미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
Postman에서 send시 다음이 뜹니다.
좋은 강의 정말 감사드립니다. CORS Error: The request has been blocked because of the CORS policy 그러면서 Agent를 desktop으로 사용하라고 나와있는데 저는 browser를 쓰고 있었거든요. desktop으로 바꾸면 될까요??
- 미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
질문있습니다!
처음 mongoose를 설치하고 나서 package.json에서 확인한 결과 "moongoose" : "0.0.5"라고 결과가 뜨더라구요. mongoose스펠링도 다르게요. 그냥 무시하고 진행한 결과 8강bodyparser강의 부분에서 최종적으로 실행할 때 schema is not a function이라는 에러가 떴습니다. 그래서 mongoose를 다시 재설치 했는데, found 1 high severity vulnerability 라는 문구가 뜨면서 npm run audir fix라는 커맨드를 실행하라고 되있는데 그냥 이렇게 따라가면 되나요??
- 미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
SSH agent를 백그라운드에서 키려고 할떄 오류납니다
(사진)
- 미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
어떻게 요청 비밀번호와 DB의 비밀번호가 같다고 확인할 수 있는지 모르겠어요
이 부분에서 compare의 첫 번째 인자와 두 번째 인자가 같을 시에 callback함수에 2번째 인자에 true 값을 전달 할 수 있는건 알겠는데, '어디에서 plainpassword를 암호화하는 것이기에' DB의 pw와 비교할 수 있는건지 모르겠어요 ㅠㅠ bcrypt.compare(plainPassword, this.password, (err, isMatch) =>
- 미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
npm run backend 오류 문의 등
안녕하세요~ 똑같이 했는데 missing script: backend 라고 뜨네요. 한번 검토 부탁드립니다.
- 미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
계속하여 암호화에 실패해요
{ "success": false, "err": {} } 포스트맨 결과입니다. 제 아래 코드에요 ㅠㅠ.... userSchema.pre("save", next => { var user = this; if (user.isModified("password")) { //비밀번호 암호화 시킨다 bcrypt.genSalt(saltRounds, (err, salt) => { if (err) return next(err); bcrypt.hash(user.password, salt, (err, hash) => { if (err) return next(err); user.password = hash; next(); }); }); } });
- 해결됨따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
isModified 부분..
안녕하세요 선생님, 수업 잘 보고 있습니다! 저는 isModified 부분 들어가면 포스트맨에서 결과가 false로 나오는데 무슨 문제 일까요..? 뒷강의에서 else 부분 추가 했는데도 계속 false 로 나오네요. 해당 조건 부분만 주석처리 하면 비밀번호가 정상적으로 암호화 처리되어 저장되는 것은 확인 했습니다.
- 미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
도저히 에러를 잡을 수 없어 질문드립니다 TT
× Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem. ▶ 2 stack frames were collapsed. usePromise C:/Users/98_07/Desktop/노드리액트/src/usePromise.ts:10 7 | }); 8 | const isMounted = useRef(false); 9 | useEffect(() => {> 10 | isMounted.current = true; | ^ 11 | if (!promiseOrFn) { 12 | setState({ 13 | loading: false,View compiled ▶ 2 stack frames were collapsed. Module../src/index.js C:/Users/98_07/Desktop/노드리액트/boiler-plate/client/src/index.js:20 17 | 18 | ReactDOM.render( 19 | <Provider> 20 | store={createStoreWithMiddleware( 21 | Reducer, 22 | window.__REDUX_DEVTOOLS_EXTENSION__ && // google redux 확장 사용 위함 23 | window.__REDUX_DEVTOOLS_EXTENSION__()View compiled __webpack_require__ C:/Users/98_07/Desktop/노드리액트/boiler-plate/client/webpack/bootstrap:784 781 | }; 782 | 783 | // Execute the module function> 784 | modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId)); | ^ 785 | 786 | // Flag the module as loaded 787 | module.l = true;View compiled fn C:/Users/98_07/Desktop/노드리액트/boiler-plate/client/webpack/bootstrap:150 147 | ); 148 | hotCurrentParents = []; 149 | }> 150 | return __webpack_require__(request); | ^ 151 | }; 152 | var ObjectFactory = function ObjectFactory(name) { 153 | return {View compiled 1 http://localhost:3000/static/js/main.chunk.js:701:18 __webpack_require__ C:/Users/98_07/Desktop/노드리액트/boiler-plate/client/webpack/bootstrap:784 781 | }; 782 | 783 | // Execute the module function> 784 | modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId)); | ^ 785 | 786 | // Flag the module as loaded 787 | module.l = true;View compiled checkDeferredModules C:/Users/98_07/Desktop/노드리액트/boiler-plate/client/webpack/bootstrap:45 42 | }View compiled Array.webpackJsonpCallback [as push] C:/Users/98_07/Desktop/노드리액트/boiler-plate/client/webpack/bootstrap:32 29 | deferredModules.push.apply(deferredModules, executeModules || []); 30 | 31 | // run deferred modules when all chunks ready> 32 | return checkDeferredModules(); | ^ 33 | }; 34 | function checkDeferredModules() { 35 | var result;View compiled (anonymous function) http://localhost:3000/static/js/main.chunk.js:1:65 This screen is visible only in development. It will not appear if the app crashes in production. 위에가 화면이 뜨는 에러 사항이고 특별히 react나 react dom의 중복 없는 것 같고 코드도 몇번이고 확인해 보았으나 오류 원인을 찾기가 힘이 듭니다. 연관 있을 법한 파일들을 올려 봅니다.... client > pacakge.json { "name": "client", "version": "0.1.0", "private": true, "dependencies": { "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.5.0", "@testing-library/user-event": "^7.2.1", "axios": "^0.20.0", "http-proxy-middleware": "^1.0.5", "react": "^16.13.1", "react-dom": "^16.13.1", "react-native": "^0.63.3", "react-redux": "^7.2.1", "react-scripts": "3.4.3", "redux": "^4.0.5", "redux-promise": "^0.6.0", "redux-thunk": "^2.3.0" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" }, "eslintConfig": { "extends": "react-app" }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] } } server > package.json { "name": "boiler-plate", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "node server/index.js", "backend": "nodemon server/index.js", "test": "echo \"Error: no test specified\" && exit 1", "dev": "concurrently \"npm run backend\" \"npm run start --prefix client\"" }, "author": "ooo", "license": "ISC", "dependencies": { "antd": "^4.6.6", "bcrypt": "^5.0.0", "body-parser": "^1.19.0", "concurrently": "^5.3.0", "cookie-parser": "^1.4.5", "express": "^4.17.1", "jsonwebtoken": "^8.5.1", "mongoose": "^5.10.7", "react-promise": "^3.0.2", "react-router-dom": "^5.2.0" }, "devDependencies": { "nodemon": "^2.0.4" } } LoginPage.js import React, { useState } from 'react'; import Axios from 'axios'; import { useDispatch } from 'react-redux'; import { loginUser } from '../../../_action/user_action'; function LoginPage() { const dispatch = useDispatch(); const [Email, setEmail] = useState(''); // useState 안에 들어가는 내용은 초기 상태 const [Password, setPassword] = useState(''); // Password(state) -> 유저가 입력한 내용이 들어감 const onEmailHandler = (event) => { setEmail(event.currentTarget.value); }; // 타이핑을 즉시 반영하기 위함 const onPasswordHandler = (event) => { setPassword(event.currentTarget.value); }; const onSubmitHandler = (event) => { event.preventDefault(); //아무 것도 ( 이메일이나 비밀번호 입력)하지 않아도 버튼을 누르면 페이지가 리프레쉬됨 let body = { email: Email, password: Password, }; dispatch(loginUser(body)); //redux 사용, LoginUser == action /* 해당 내용은 LoginUser action에서 처리 Axios.post('api/users/login', body) .then(response =>{ })*/ }; return ( <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', width: '100%', height: '100vh', }} > <form style={{ display: 'flex', flexDirection: 'column' }} onSubmit={onSubmitHandler} > <label>Email</label> <input type='email' value={Email} onChange={onEmailHandler} /> <label>Password</label> <input type='password' value={Password} onChange={onPasswordHandler} /> <br /> <button>Login</button> </form> </div> ); } export default LoginPage;
- 미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
postman 출력값 오류 발생 문의
"email": "test1@naver.com", "password": "1234567" } 안녕하세요~ 위와 같이 해서 Send 누르면 아래와 같이 나옵니다. 제가 뭘 잘못했을까요? 한번 확인 부탁드립니다. 이전에 메일과 비번 변경시에는 성공 문자가 잘 뜨네요. <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot POST /login</pre> </body> </html>
- 미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
저는 화면이 다릅니다
저는 로그인 해서 들어오면 화면이 이렇고 cluster 만드는거랑 관련된건 눈 씻고 찾아봐도 없는데 어떡하나요?
- 미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
오류
events.js:291 throw er; // Unhandled 'error' event ^ Error: listen EADDRINUSE: address already in use :::5000 at Server.setupListenHandle [as _listen2] (net.js:1317:16) at listenInCluster (net.js:1365:12) at Server.listen (net.js:1451:7) at Function.listen (C:\Users\ivy\bolier-plate\node_modules\express\lib\application.js:618:24) at Object.<anonymous> (C:\Users\ivy\bolier-plate\index.js:29:5) at Module._compile (internal/modules/cjs/loader.js:1085:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10) at Module.load (internal/modules/cjs/loader.js:950:32) at Function.Module._load (internal/modules/cjs/loader.js:791:14) at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12) at internal/main/run_main_module.js:17:47 Emitted 'error' event on Server instance at: at emitErrorNT (net.js:1344:8) at processTicksAndRejections (internal/process/task_queues.js:80:21) { code: 'EADDRINUSE', errno: -4091, syscall: 'listen', address: '::', port: 5000 } npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! bolier-plate@1.0.0 start: `node index.js` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the bolier-plate@1.0.0 start script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above. npm ERR! A complete log of this run can be found in: npm ERR! C:\Users\ivy\AppData\Roaming\npm-cache\_logs\2020-10-04T08_54_51_132Z-debug.log 처음에 실행할때는 잘 되는데 다시 실행하려고하면 계속해서 똑같은 오류가 나요 해결하려고 별짓을 다해봤는데 안되네요 왜 그런걸까요??
- 미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
findByToken 에러 납니다 ㅠㅠ
함수가 아니라고 하는데 왜 그런걸까요?? TypeError: User.findByToken is not a function