묻고 답해요
131만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
passport-naver
passport-naver을 이용해보려 하는데 porfile.displayName 값이 계속 undefind여서 nick값에 들어가지가 않습니다... naver 앱등록할때 권한도 다 설정 해줬는데 왜 정보를 받아오지 못할까요 제로초님 ㅠㅠ const passport = require('passport'); const NaverStrategy = require('passport-naver').Strategy; const User = require('../models/user'); module.exports = () => { passport.use(new NaverStrategy ({ clientID: process.env.NAVER_ID, // 네이버에서 발급받을 ID clientSecret: process.env.NAVER_SECRET, callbackURL: '/auth/naver/callback', // 네이버로부터 인증결과를 받을 라우터 주소 }, async (accessToken, refreshRoken, response, done) => { // 네[이버에서 인증 후 Token 과 profile을 보내준다. console.log('naver profile', response); try { const exUser = await User.findOne({ // 기존의 User가 있는지 조회 where: { snsId: response.id, provider: 'naver' }, }); if(exUser) { // 기존 User의 정보가 있다면 User정보를 done과 호출하고 전략을 종료 done(null, exUser); } else { // 기존의 User정보가 없다면 회원가입을 진행 const newUser = await User.create({ email: response.emails[0].value, nick: response.id, snsId: response.id, provider: 'naver', naver: response._json }); done(null, newUser); // 사용자 생성 후 done함수 호출 } } catch (error) { console.log(error); done(error); } })); }; 이렇게 작성했습니다 naver profile { provider: 'naver', id: '60727489', displayName: undefined, emails: [ { value: 'juren528@gmail.com' } ], _json: { email: 'juren528@gmail.com', nickname: undefined, profile_image: undefined, age: undefined, birthday: undefined, id: '60727489' } } 가져온 결과 콘솔로 확인해보니 이렇게 나오구요 좀더 공부해보려다 안되서 막막합니다 ㅠㅠ 혹시 이유를 아실까요 ㅠㅠ
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
이런 에러는 왜 생기는건가요?
(node:17608) [DEP0148] DeprecationWarning: Use of deprecated folder mapping "./" in the "exports" field module resolution of the package at C:\Users\oksos\Desktop\study\PTE\loginWeb\client\node_modules\postcss-safe-parser\node_modules\postcss\package.json. Update this package.json to use a subpath pattern like "./*". (Use `node --trace-deprecation ...` to show where the warning was created) createProxyMiddleware is not a function
-
해결됨[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
deserializeUser findAll()실행시 로그인 성공 후 화면이 그대로입니다.
로그인을 하면 세션까지는 올바르게 잘 넣어집니다. 그런데 deserializeUser를 실행할때 findOne을 findAll로 실행하면 req.user까지만 되고 나머지 user.id user.nick 등이 받아와지지 않습니다. findAll 과 findOne에 id를 조건으로 입력하면 같은 결과가 나온다고 생각했는데 왜 안되는지 혹시 알려주실수 있나요 ㅠㅠ
-
미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
Node.js 교과서
안녕하세요 제로초님 Node.js 교과서를 사서 열심히 수업을 듣고 있는 한 학생입니다! 다름이 아니고 유튜브를보며 노드교과서 개정판 4-5. 쿠키 이해하기에서 코드 질문이 있어서 여쭤보러 왔습니다. 이것은 되는 코드이고 const parseCookies = (cookie = '') => cookie .split(';') .map(v => v.split('=')) .reduce((acc, [k,v]) => { acc[k.trim()] = decodeURIComponent(v) return acc; }, {}); 이것은 안되는 코드입니다. const parseCookies = (cookie = '') => { cookie .split(';') .map(v => v.split('=')) .reduce((acc, [k,v]) => { acc[k.trim()] = decodeURIComponent(v) return acc; }, {}); }; 둘의 차이점은 함수를 {} 로 감싸냐 안감싸냐의 차이인데 화살표함수에서 중괄호는 선택사항이라고 배웠습니다. 만약 아래 코드를 사용하게 되면 (node:9452) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'name' of undefined at Server.<anonymous> (C:\Users\ksy\Desktop\Node.js\ch04\ex03\cookie2.js:30:22) at Server.emit (events.js:315:20) at parserOnIncoming (_http_server.js:874:12) at HTTPParser.parserOnHeadersComplete (_http_common.js:126:17) (Use `node --trace-warnings ...` to show where the warning was created) (node:9452) 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(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1) (node:9452) [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. 라는 에러가 뜹니다. 함수를 제대로 사용하지 못해서 그런거 같은데 왜 중괄호를 붙이면 함수가 실행이 안되는건지 궁금합니다
-
해결됨프론트엔드 개발환경의 이해와 실습 (webpack, babel, eslint..)
npm install -D
npm install -D @babel/preset-env 라 적혀 있는데 실제론 npm install @babel/preset-env 라고 하기도 하고.... -D가 dev에 추가한다. 라고는 알고 있는데, 실제로 바벨 프리셋들은 dev에 했을 때와 아닐때 차이가 없나요? 아니면 차이점으로 어떤 것들이 있나요?
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 쇼핑몰 사이트 만들기[전체 리뉴얼]
선생님 질문있습니다.
다른분이 질문하신건데 9:30초에 const productId = props.match.params.productId; 여기서 props.match.params.productId 가 어디서 나온건지 잘 모르겠습니다 ㅠㅠ. App.js 에서 Auth로 감싸줘서 props가 있는건 알겠는데 match.params.productId가 어디서 나온건지 모르겠네요 ㅠㅠ App.js -> hoc/auth.js -> user_actions.js->index.js-> routes/users.js 까지 가봤는데 잘 모르겠네요 ㅠㅠ
-
propery 'nickname' of undefined
삭제된 글입니다
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
rootReduecer함수에서 리듀의 초기화
reducers 폴더의 index파일의 rootReducer함수에서 defalut: return state 들어가는이유 설명해주실때 액션타입해서 그 다음상태 만들어주는것을 처리해주는대 리듀서 초기화할때 또 rootReducer함수가 실행이되는대 그때defalut: return state이 부분이 없으면 리턴값이 undefined된다 이렇게 설명해주셨는대 리듀서가 왜 초기화되는지 이유가 궁금합니다!
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
user를 찾을 수 없다고 나와요ㅠㅠㅠㅠ
AppLayout에서 store에서 IsLoggedIn 가져오는데서 에러가 발생합니다. const isLoggedIn = useSelector((state) => state.user.isLoggedIn); 에러 코드 TypeError: Cannot read property 'user' of undefined const initialState = { user: { isLoggedIn: false, user: null, signUpdata: {}, loginData: {}, }, post: { mainPosts: [], }, }; const rootReducer = (state = initialState, action) => { switch (action.type) { case "LOG_IN": return { ...state, user: { ...state.user, isLoggedIn: true, user: action.data, }, }; case "LOG_OUT": return { ...state, user: { ...state.user, isLoggedIn: false, user: null, }, }; default: return; } }; 뭐가 문제일까여...힝ㅜㅜㅜㅜ
-
미해결리액트로 나만의 블로그 만들기(MERN Stack)
새로고침시 로그인이 유지 되지 않습니다.
되게 여러번 따라 했는데, 새로고침 하고난 후 로그인이 유지가 되지 않습니다..ㅠㅠ authSaga 속의 함수들이 제대로 작동하지 않는것 같습니다.... authoSaga속 함수를 호출하는 시작이 어딘지 순서 또한 잘 파악되지 않습니다..ㅠ 계속 401에러가 뜹니다. ㅠㅠ
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
12강, POST를 보내면 [ERR_HTTP_HEADERS_SENT] 에러
- Postman으로 email, PW를 보내며 '비밀번호가 틀렸습니다' 가 Response로 돌아오면서 아래 에러가 나옵니다... 비번은 분명 맞는데 이런 에러가 나옵니다ㅜ 혹시 이유를 알 있나요? - 좀 길지만 전체 코드 복붙했습니다. 감사합니다! CODE ERROR _http_outgoing.js:558 throw new ERR_HTTP_HEADERS_SENT('set'); ^ Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at ServerResponse.setHeader (_http_outgoing.js:558:11) at ServerResponse.header (/Users/user/VS Code/project_with_NodeJS/boiler-plate/node_modules/express/lib/response.js:771:10) at ServerResponse.send (/Users/user/VS Code/project_with_NodeJS/boiler-plate/node_modules/express/lib/response.js:170:12) at ServerResponse.json (/Users/user/VS Code/project_with_NodeJS/boiler-plate/node_modules/express/lib/response.js:267:15) at /Users/user/VS Code/project_with_NodeJS/boiler-plate/index.js:48:20 at /Users/user/VS Code/project_with_NodeJS/boiler-plate/models/user.js:62:9 at /Users/user/VS Code/project_with_NodeJS/boiler-plate/node_modules/bcrypt/bcrypt.js:210:13 at processTicksAndRejections (internal/process/task_queues.js:75:11) { code: 'ERR_HTTP_HEADERS_SENT' } npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! boiler-late@1.0.0 start: `node index.js` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the boiler-late@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! /Users/user/.npm/_logs/2020-12-28T03_02_38_926Z-debug.log
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
제이쿼리와 리액트 합칠 수 있다는 점에서 궁금한 점이 생겻는데요.
리액트 네이티브와 네이티브 언어(스위프트, 코틀린)도 합쳐서 개발을 할 수 있는 걸까요?
-
미해결프론트엔드 개발환경의 이해와 실습 (webpack, babel, eslint..)
콘솔찍은건 잘 뜨는데 콘솔이 알랏으로 변경되지 않습니다
module.exports = function myWebpackLoader (content){ console.log("실행"); return content.replace('console.log(','alert('); } 으로 빌드하면 실행 콘솔 찍은것 2번 나오고 [webpack-cli] Compilation finished뜹니다 npx lite-server로 서버 구동하여 확인하면 알랏이 안뜨고 콘솔로 3이 뜹니다 일부러 module.exports = function myWebpackLoader (content){ console.log("실행"); return content.replace('console','alert('); } 이런식으로 콘솔글자를 바꿔서 빌드하면 You may need an additional loader to handle the result of these loaders. | import * as math from './math.js'; > alert(.log(math.sum(1,2)); 라는 에러가 뜹니다 replace가 동작을 하는것 같긴 한데 왜 콘솔을 알랏으로 바꾸지 못하는것일까요?
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
redux-saga 의 흐름.
질문1. 리덕스사가에 액션이 전달되는 과정 dispatch({ type: LOG_IN_REQUEST, data: { email, password }, }); 위와 같이 로그인 버튼을 눌렀을때 인자로 전달된 액션을 dispatch 하게 되는데. function* watchLogIn() { yield takeLatest(LOG_IN_REQUEST, logIn); } 이후 사가에서 LOG_IN REQUEST 에관한 액션이 왔을떄 login 함수가 실행된다는 흐름은 이해를 했습니다. 하지만 액션객체의 type 속성인 LOG_IN_REQUEST 가 어떻게 위에 takeLatest 의 첫번째 인자로 인식이되어 login 함수가 실행되는지 직관적으로 이해가 가지않습니다. 이미 사가 라이브러이에서 정해진 규칙같은 건가요 ? 액션을 디스패치 할때 {type: `액션타입`} 형태여야만 takeLatest('액션타입') 이 인식이되는지 궁금합니다. 질문2. yield function* logIn(action) { try { console.log('saga logIn'); // const result = yield call(logInAPI); yield delay(1000); => 멈춤? yield put({ => 멈춤? type: LOG_IN_SUCCESS, data: action.data, }); } catch (err) { console.error(err); yield put({ type: LOG_IN_FAILURE, error: err.response.data, }); } } yield 는 중단점 역활을 한다고 이해했습니다. 그럼 위에 takeLatest 의 두번째인자로 위 login 함수가 실행될때 첫번째 yield delay(1000) 이 실행되고 멈추는게아니라 계속에서 아래 yelid put 쪽을 실행되는부분이 이해가 잘 가지않습니다.! 영상 몇번 돌려보고 찾아도 봤는데 스스로 해결하지 못해 질문 드립니다 ㅜㅠ..
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
axios.defaults.baseURL 지정 후, 다른 서버에 요청을 보내려면?
/front/sagas/index.js 에서 axios.defaults.baseURL = 'http://localhost:3065'; axios.defaults.withCredentials = true; 이렇게 공통으로 지정을 해주는데, 만약에 예외적으로 다른 URL을 사용하고 싶으면 어떻게 하나요? function loadPostsAPI(data) { return axios.get('http://naver.com/test', data); } 이런식으로 개별적으로 URL 넣어주면 될까요? 아니면 애초에 공통URL을 지정해주지 말고 각자 넣어줘야 하는걸까요? 공통URL과 더불어 withCredentials 값도 각자 넣으려면 어떻게 해야하는지 궁금합니다!
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
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 입니다. 문제가 무엇일까요, ㅠ
-
미해결프론트엔드 개발환경의 이해와 실습 (webpack, babel, eslint..)
compiler.plugin 이 undefined라고 뜹니다.
안녕하세요 TypeError: compiler.plugin is not a function 위와 같은 에러가 떠서 compiler를 찍어봤더니 plugin이 존재하지 않아서 undefined라고 뜹니다. compiler.hooks.emit.tapAsync( 'emit', (compilation, callback) => { const source = compilation.assets['main.js'].source(); console.log(source); callback(); }) } 이 방식을 사용하면 똑같이 나오는데 버전이 바뀐 것인가요?
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
models 최신 문법으로 변경 후
index 페이지에 /Posts 요청에서 sequelizeeagerloadingerror Image is not associated to Comment 에러가 나고 로그인도 안되요 models 폴더 말고 다른 파일도 수정해야하는 곳이 있나요?
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
Router 를 사용해 SSR 페이지 이동할 때 질문입니다!
/user/[id].js 로 Link 태그를 통해 접근했을 때 userInfo 가 null 인 에러를 해결하려고 이것저것 해보던중 /user/[id].js 안에 {/* <title>{userInfo.nickname}님의 글</title> <meta name="description" content={`${userInfo.nickname}님의 게시글`} /> <meta property="og:title" content={`${userInfo.nickname}님의 게시글`} /> <meta property="og:description" content={`${userInfo.nickname}님의 게시글`} /> <meta property="og:image" content="https://nodebird.com/favicon.ico" /> <meta property="og:url" content={`https://nodebird.com/user/${id}`} /> */} Head 안에 위 부분을 주석처리하니까 정상적으로 렌더링 되었어요! 혹시 원인이 뭔지 알 수 있을까요? 스크립트가 실행되기 전 Head 안에 userInfo 를 찾다가 에러를 나는 것인지.. 다른 이유에서인지.. 그리고 제로초님 깃헙 클론받아서 실행할 때 next 디펜던시 버전을 9.5.3으로 변경해서 실행해보니 저와 동일한 에러가 났었어요 혹시 확인 가능하실까요?
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
로그아웃시 에러
리액트 강의 마지막 인증처리 빼고 로그아웃 강의까지 들으면서 따라 했는데 로그아웃에서 에러가 나옵니다 로그아웃시에 콘솔창에는 { isAuth: false, error: true } 뜨는데요 이건 auth 미들웨어에서 사용자를 찾지 못했을 때 나타나는 에러인데 왜 로그인이 됐고 토큰도 생성이 됐는데 사용자를 찾지 못하는 지 모르겠어요ㅠㅠ 깃허브에 올려주신 코드 비교도 해봤는데 안 되네요...