수강이 제한됩니다.
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
강사님 질문이있습니다.
미들웨어에서 req, res ,next 를 꺼내서 쓸수있는것을보니 미들웨어에서는 req,res,next 가 없는것은 그것이 적혀있지않으면 생략되어있을뿐 언제든지 꺼내쓸수있고 미들웨어확장은 딱 그위치에 원하는 커스텀한 로직을 넣고싶어서 라고 생각하면 될까요? 그리고 cors({ origin:true, credentials : true })(req,res,next); 부분에서는 next() 가없어도 넘어갈수 있는 이유가 cors 모듈 자체적으로 next()가 포함되어있는 로직이 내재해있다 라고 생각하면 되는것이죠? 항상 감사합니다
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
강사님 질문이있습니다.
카카오같은 대형 서버에서는 저희가 api 키를 발급신청을할때 DB에 저희가 사용할 url을 저장해주고 app.use(cors({ origin: [ 리스트], credentials: true, })); 이 origin 배열안에 그많은 사용자들의 url이 다 담기는건가요?
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
강사님 질문이있습니다.
fs 모듈은 callback 만 지원하고 fs.promises 는 프로미스를 지원하는 것같더라구요? 보통 기존 콜백으로 나왔던 모듈 이나 그안의 함수는 저렇게 프로미스를 지원하게 업그레이드를 해주나요?
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
useCreateIndex 를 사용하면 DB 연결이 안됩니다.
useCreateIndex: true, 를 사용 하면 DB 연결이 안됩니다. 이 라인을 지우면 연결이 되고요. 그 이유가 뭔지 알수 있을까요?? ㅠㅠ 몽고디비 연결이 끊겼습니다. 연결을 재시도합니다. 만 계속 출력을 합니다.
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
강사님 질문이있습니다.
강의 목록을 보던도중 nest js 라는 자바로치면 스프링과 비슷하게 획일화된 프레임워크가 있더라구요 실무에서 급하게 작업을 하려는 상황일떄는 nest가 더 유용할까요? 그리고 소개해주신 모던 javascript 튜토리얼 페이지도 보고있는데 점점 볼수록 난해한 부분이 좀있는데요 저페이지를 모두 마스터하지않아도 실무코딩하는데 크게 상관이없을까요? 마지막질문은요 제가 강의 두개를 본바로 강사님은 보통 세션값을 서버에 저장하시는것같은데 디비통해서 저장하는것은 이용자가 많아졌을때 소스를 바꾸시나요 ?
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
질문있습니다
.ejs 파일에서 이미지를 올리려고 하는데요 app.js파일에서 res.render를 했을 때 이미지가 안뜹니다. .ejs파일을 확장자를 html로 바꾸어서 그냥 파일을 열어봤을 때는 이미지가 잘 보여서 경로문제는 아닌 거 같은데요 혹시 다른 문제가 있을까요?
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
비동기 에러처리 질문
제로초님비동기 관련하여 질문이 있습니다 현재 FCM 푸시알림을 보내줄때 try{ await admin.messaging().send(msg); }catch(err){ console.log(err); } 이런식으로 await을 만들어서 동기적으로 에러처리를 해주고있었는데, 아무래도 서버 cpu가 한번씩 100 위로 튀는 이유가 이것을 await으로 처리해줘서 밀려있던 작업들이 봇물터지는 쏟아져서 그런거라고 생각하여 await을 빼줬습니다. 생각해보니 이렇게되면 try catch는 동기에러만 잡아주니 뒤늦게 들어오는 에러는 잡아주지 못한다고 생각했는데, 에러를 잡아주지 못하나요?? 그리고 맞다면 푸시알림에서 에러 발생시에 잡아주지 못하니까 서버 프로세스가 종료되는건가요..? 만약 비동기적으로 빠르게 에러 처리를 하고싶다면 then().catch()를 써야하는건지 궁금합니다.
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
미들웨어에 미들웨어를 붙이는 이유가 이해가 잘 안됩니다. ㅠ
안녕하세요 제로초님. 혹시 미들웨어에 미들웨어를 붙이는 이유와 주로 어떤 상황에서 붙여서 사용하는지 자세하게 알고싶습니다 . 답변 주시면 감사하겠습니다 ㅠㅠ 코드에서는 대표적으로 로그인에서 사용하고 있긴한데 .. router.post('/login', isNotLoggedIn, async (req, res, next) => { passport.authenticate('local', (authError, user, info) => { if (authError) { console.error(authError); return next(authError); } if (!user) { return res.redirect(`/?loginError=${info.message}`); } return req.login(user, (loginError) => { if (loginError) { console.error(loginError); return next(autnError); } return res.redirect('/'); }); })(req, res, next); }); 자세히 알고싶어서 질문드립니다 ㅠ
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
강사님 질문이있습니다.
const test = { "_declaration": { "_attributes": { "version": "1.0", "encoding": "UTF-8", "standalone": "yes" } }, "response": { "header": { "resultCode": { "_text": "00" }, "resultMsg": { "_text": "NORMAL SERVICE." } }, "body": { "items": { "item": [ { "as1": { "_text": "경상남도" }, "as2": { "_text": "창원마산회원구" }, "as3": { "_text": "내서읍" }, "as4": { "_text": "삼계리" }, "bjdCode": { "_text": "4812725028" }, "kaptCode": { "_text": "A63085232" }, "kaptName": { "_text": "마산삼계2" } }, }, "numOfRows": { "_text": "10" }, "pageNo": { "_text": "1" }, "totalCount": { "_text": "18496" } } } } 노드기반으로 공공api를 xml 구조이길래 xml2json 모듈을 이용해서 json 구조로 바꾼다음에 sequelize 모델에 create 해주려고하는데 JSON 구조의 값을 test['response']['body']['items']['item'] 요런구조로 못받나요? 자꾸 console찍어보면 undefined 가나오네요
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
node.js 교과서 예제 질문
교제의 url.js 와 searchParams.js 예제를 보면 각각 아래 부분은 굳이 왜 작성을 했을까요? const { URL } = url; const { URL } = require('url'); 없어도 예제 실행에는 문제가 없는데요.
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
제이쿼리 ( jQuery ) 에 관해서 질문 있습니다.
안녕하세요. 제로초님 다름이 아니라, "제이쿼리" 에 대한 궁금증이 있어서 이렇게 글을 남깁니다. 요즘은 제이쿼리를 워낙 안 쓰고, 사용하는 걸 추천하지 않는다고 해서 부트캠프에서도 배우지 않았는데요. 생각보다 많은 곳에서 아직까지도 제이쿼리를 사용하는 것을 볼 수 있고, 제이쿼리에 대한 강의도 많이 나오는 것을 보면, 제가 취업하기 전에 배우고 가는 게 맞는지 아니면, 몰라도 상관없는 것인지 궁금합니다. Q) 실무에서 아직도 제이쿼리를 많이 사용하나요?? 신입 개발자의 역량 중에 하나로 제이쿼리 사용 능력도 필요한가요??
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
express-session 원리, 세션 보안 질문
express-session 미들웨어를 사용하면 좋은 점이 req.session을 id를 따로 지정해주지 않아도 개인의 저장공간 처럼 사용할 수 있다고 하셨는데, 4장에서 const session = {key:data}로 고유한 key로 사용자를 구분해 특정 사용자의 데이터만 객체로 넘겨주는 처리를 미들웨어 내부에서 알아서 해주는 건가요? 예를 들어 모든 사용자의 세션이 저장된 session 객체가 있다고 하면 요청으로 받은 key값으로 사용자 의 정보를 꺼내 req에 넣어 다음 미들웨어로 넘겨주는 형태인가요? const session = { key1: { id: "id1", password: "pw1111", }, key2: { id: "id2", password: "pw2222", }, ... }; req.session <= { id: "id2", password: "pw2222", } 위가 맞다면 세션을 사용하면 유저의 데이터는 서버 안에 둬서 지킬 수 있지만 결국 브라우저에서 세션이 탈취되면 해커가 유저아이디로 로그인 할 수 있는거 아닌가요?
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
강사님 질문이있습니다.
시퀄라이즈를 복습하던 도중 최대한 강의내용을 기억하고 공식문서를 참조하면서 해보려고 하는데 공식문서를 보면 cli 관련된 것은 없고 공식문서에 적혀있는대로 작성해보면 cli로 init 한것과는 좀많이다르고 실행시키기도 따라서 쳐보는데도 쉽지않네요 저런공식문서는 좀 잘 참조하고 사용하는법이있나요? 연차가 쌓이는만큼 공식문서를 못보면 안되는상황이라서요
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
(cookie ='') 요부분
const parse Cookies = (cookie ='') => cookie.split(':')~~ 구문은 무슨 문법인가요 이해가잘안가서요 const cookies = parseCookies(req.headers.cookie) cookies 는 req.headers.cookie 는 스트링인데 (cookie ='') 이렇게생긴거에 어떻게 대입이 되는건가요?
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
조현영님께서는 switch 구문을 사용하는것에 대해 어떻게 생각하시나요?
라우트 매개변수를 활용해서 url에 데이터베이스의 id 컬럼값을 입력하면 그 id 컬럼에 해당하는 로우를 보여주는 라우터를 스위치 구문을 사용해서 나타내보았습니다. router.get("/:id/info", async (req, res, next) => { try { let productInfo = await Product.findAll({}); switch (req.params.id) { case "1": productInfo = productInfo[1]; break; case "2": productInfo = productInfo[2]; break; case "3": productInfo = productInfo[3]; break; case "4": productInfo = productInfo[4]; break; case "5": productInfo = productInfo[5]; break; case "6": productInfo = productInfo[6]; break; case "7": productInfo = productInfo[7]; break; case "8": productInfo = productInfo[8]; break; case "9": productInfo = productInfo[9]; break; case "10": productInfo = productInfo[10]; break; case "11": productInfo = productInfo[11]; break; default: res.locals.message = "No more product on that url"; res.render("noProduct"); return 0; } res.locals.id = req.params.id; res.locals.productName = productInfo.name; res.locals.productPrice = productInfo.price; res.locals.productOrigin = productInfo.origin; res.locals.productType = productInfo.type; res.render("productInfo"); } catch (err) { console.error(err); next(err); } }); 근데 이런 방식의 단점은 id컬럼이 증가할 때마다 제가 수동으로 케이스문을 추가해야 한다는 것입니다. 조현영님께서는 스위치문을 현업에서 사용해보신 경험이 있으신가요? 사용하신다면 어떤 방향으로 사용하시나요?
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
강사님 질문이있습니다.
제가 스프링할때에는 jsp 뷰페이지를 써서 MVC패턴이라는걸로 url 접속을하면 안에 데이터를 불러오는 로직 + 가야하는 view 페이지 경로 로 했는데요 넉스트로 트위터 페이지 만들기 강의를 들엇는데 보통 nuxt에서 폴더구조로 라우터를 잡고 fetch 나 NuxtserverInit 등 비동기 형식으로 ? api 요청을 통해 데이터를 불러와서 상태관리에 데이터를 세팅해주고 그값을 라우터 화면들에서 사용하는 구조로 사용하는것 같더라구요? 이건무슨 패턴인가요? 요즘 트렌드가 이런건지 궁금해서요 리액트도 이런형식이 주를 이루나요? 강의외질문 : 실무에서는 react 가 vue 보다 더 자주쓰이는편인가요? ,웹은 react 앱은 react native 로 프론트를 구성하고 같은 백엔드를 사용하면 되는건가요? 감사합니다
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
안녕하세요 강사님 질문이있습니다.
fs.writeFile('./writeme.txt', '써보자123') .then(()=> console.log('성공')) .then(()=>{return fs.readFile('./writeme.txt') }) .then((data)=>{console.log(data.toString()); return data.toString()}) .then((data)=>console.log("테스트2",data)) .catch((err)=> console.error(err)); Promise .then .catch 문에서 3번쨰줄처럼 return 을 해준것은 다음 then 문에서만 인자로 받을수 있는게 맞는것인가요?
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
passport 사용 시 localstrategy 부분에서 오류가 나는 것 같습니다
안녕하세요. passport local 로그인 실습을 하다가 막히는 부분이 있어 질문드립니다. 현재 postman으로 실험 시 회원가입은 정상적으로 진행이 되는 것 같은데, postman으로 로그인 시도 시 다음과 같은 오류코드가 발생합니다. Error: Invalid value <ref *1> IncomingMessage { _readableState: ReadableState { objectMode: false, highWaterMark: 16384, buffer: BufferList { head: null, tail: null, length: 0 }, length: 0, pipes: [], flowing: true, ended: true, endEmitted: true, reading: false, sync: false, needReadable: false, emittedReadable: false, readableListening: false, resumeScheduled: false, errorEmitted: false, emitClose: true, autoDestroy: false, destroyed: false, errored: null, closed: false, closeEmitted: false, defaultEncoding: 'utf8', awaitDrainWriters: null, multiAwaitDrain: false, readingMore: false, decoder: null, encoding: null, [Symbol(kPaused)]: false }, _events: [Object: null prototype] { end: [Function: clearRequestTimeout] }, _eventsCount: 1, _maxListeners: undefined, socket: Socket { connecting: false, _hadError: false, _parent: null, _host: null, _readableState: [ReadableState], _events: [Object: null prototype], _eventsCount: 8, _maxListeners: undefined, _writableState: [WritableState], allowHalfOpen: true, _sockname: null, _pendingData: null, _pendingEncoding: '', server: [Server], _server: [Server], parser: [HTTPParser], on: [Function: socketListenerWrap], addListener: [Function: socketListenerWrap], prependListener: [Function: socketListenerWrap], _paused: false, _httpMessage: [ServerResponse], _peername: [Object], [Symbol(async_id_symbol)]: 78, [Symbol(kHandle)]: [TCP], [Symbol(kSetNoDelay)]: false, [Symbol(lastWriteQueueSize)]: 0, [Symbol(timeout)]: null, [Symbol(kBuffer)]: null, [Symbol(kBufferCb)]: null, [Symbol(kBufferGen)]: null, [Symbol(kCapture)]: false, [Symbol(kBytesRead)]: 0, [Symbol(kBytesWritten)]: 0, [Symbol(RequestTimeout)]: undefined }, httpVersionMajor: 1, httpVersionMinor: 1, httpVersion: '1.1', complete: true, headers: { 'content-type': 'application/json', 'user-agent': 'PostmanRuntime/7.29.0', accept: '*/*', 'postman-token': '667cd00d-55cb-434f-80ee-6800fe7e4d60', host: 'localhost:3000', 'accept-encoding': 'gzip, deflate, br', connection: 'keep-alive', 'content-length': '76', cookie: 'connect.sid=s%3Atv5OOUthLZaPN8ZQChSAm4qaJB0CZbgU.MrtvXtMcWOoYkXGY0dY4H%2F6tGs25VsY8vJoRPQvx%2FMI' }, rawHeaders: [ 'Content-Type', 'application/json', 'User-Agent', 'PostmanRuntime/7.29.0', 'Accept', '*/*', 'Postman-Token', '667cd00d-55cb-434f-80ee-6800fe7e4d60', 'Host', 'localhost:3000', 'Accept-Encoding', 'gzip, deflate, br', 'Connection', 'keep-alive', 'Content-Length', '76', 'Cookie', 'connect.sid=s%3Atv5OOUthLZaPN8ZQChSAm4qaJB0CZbgU.MrtvXtMcWOoYkXGY0dY4H%2F6tGs25VsY8vJoRPQvx%2FMI' ], trailers: {}, rawTrailers: [], aborted: false, upgrade: false, url: '/login', method: 'POST', statusCode: null, statusMessage: null, client: Socket { connecting: false, _hadError: false, _parent: null, _host: null, _readableState: [ReadableState], _events: [Object: null prototype], _eventsCount: 8, _maxListeners: undefined, _writableState: [WritableState], allowHalfOpen: true, _sockname: null, _pendingData: null, _pendingEncoding: '', server: [Server], _server: [Server], parser: [HTTPParser], on: [Function: socketListenerWrap], addListener: [Function: socketListenerWrap], prependListener: [Function: socketListenerWrap], _paused: false, _httpMessage: [ServerResponse], _peername: [Object], [Symbol(async_id_symbol)]: 78, [Symbol(kHandle)]: [TCP], [Symbol(kSetNoDelay)]: false, [Symbol(lastWriteQueueSize)]: 0, [Symbol(timeout)]: null, [Symbol(kBuffer)]: null, [Symbol(kBufferCb)]: null, [Symbol(kBufferGen)]: null, [Symbol(kCapture)]: false, [Symbol(kBytesRead)]: 0, [Symbol(kBytesWritten)]: 0, [Symbol(RequestTimeout)]: undefined }, _consuming: true, _dumped: false, next: [Function: next], baseUrl: '/auth', originalUrl: '/auth/login', _parsedUrl: Url { protocol: null, slashes: null, auth: null, host: null, port: null, hostname: null, hash: null, search: null, query: null, pathname: '/login', path: '/login', href: '/login', _raw: '/login' }, params: {}, query: {}, res: ServerResponse { _events: [Object: null prototype], _eventsCount: 2, _maxListeners: undefined, outputData: [], outputSize: 0, writable: true, destroyed: false, _last: false, chunkedEncoding: false, shouldKeepAlive: true, _defaultKeepAlive: true, useChunkedEncodingByDefault: true, sendDate: true, _removedConnection: false, _removedContLen: false, _removedTE: false, _contentLength: null, _hasBody: true, _trailer: '', finished: false, _headerSent: false, socket: [Socket], _header: null, _keepAliveTimeout: 5000, _onPendingData: [Function: bound updateOutgoingData], _sent100: false, _expect_continue: false, req: [Circular *1], locals: [Object: null prototype] {}, _startAt: undefined, _startTime: undefined, writeHead: [Function: writeHead], __onFinished: [Function], end: [Function: end], [Symbol(kCapture)]: false, [Symbol(kNeedDrain)]: false, [Symbol(corked)]: 0, [Symbol(kOutHeaders)]: [Object: null prototype] }, _startAt: [ 779390, 642704127 ], _startTime: 2022-02-06T14:57:51.132Z, _remoteAddress: '::1', body: { email: 's2s2ss@naver.com', name: 'ddd', password: '12343' }, _body: true, length: undefined, secret: 'nodepracticesecret', cookies: {}, signedCookies: [Object: null prototype] { 'connect.sid': 'tv5OOUthLZaPN8ZQChSAm4qaJB0CZbgU' }, _parsedOriginalUrl: Url { protocol: null, slashes: null, auth: null, host: null, port: null, hostname: null, hash: null, search: null, query: null, pathname: '/auth/login', path: '/auth/login', href: '/auth/login', _raw: '/auth/login' }, sessionStore: MemoryStore { _events: [Object: null prototype], _eventsCount: 2, _maxListeners: undefined, sessions: [Object: null prototype] {}, generate: [Function (anonymous)], [Symbol(kCapture)]: false }, sessionID: '8oW9NcDPX2SJzfB5KT6guRURg59uUftq', session: Session { cookie: [Object] }, flash: [Function: _flash], _passport: { instance: [Authenticator] }, logIn: [Function (anonymous)], login: [Function (anonymous)], logOut: [Function (anonymous)], logout: [Function (anonymous)], isAuthenticated: [Function (anonymous)], isUnauthenticated: [Function (anonymous)], _sessionManager: SessionManager { _key: 'passport', _serializeUser: [Function: bound ] }, route: Route { path: '/login', stack: [Array], methods: [Object] }, [Symbol(kCapture)]: false, [Symbol(RequestTimeout)]: undefined } at Object.escape (/Users/macintosh/Desktop/node_practice/node_practice/node_modules/sequelize/dist/lib/sql-string.js:52:11) at MySQLQueryGenerator.escape (/Users/macintosh/Desktop/node_practice/node_practice/node_modules/sequelize/dist/lib/dialects/abstract/query-generator.js:709:22) at MySQLQueryGenerator.whereItemQuery (/Users/macintosh/Desktop/node_practice/node_practice/node_modules/sequelize/dist/lib/dialects/abstract/query-generator.js:1733:102) at /Users/macintosh/Desktop/node_practice/node_practice/node_modules/sequelize/dist/lib/dialects/abstract/query-generator.js:1646:25 at Array.forEach (<anonymous>) at MySQLQueryGenerator.whereItemsQuery (/Users/macintosh/Desktop/node_practice/node_practice/node_modules/sequelize/dist/lib/dialects/abstract/query-generator.js:1644:35) at /Users/macintosh/Desktop/node_practice/node_practice/node_modules/sequelize/dist/lib/dialects/abstract/query-generator.js:1752:30 at Array.map (<anonymous>) at MySQLQueryGenerator._whereGroupBind (/Users/macintosh/Desktop/node_practice/node_practice/node_modules/sequelize/dist/lib/dialects/abstract/query-generator.js:1751:21) at MySQLQueryGenerator.whereItemQuery (/Users/macintosh/Desktop/node_practice/node_practice/node_modules/sequelize/dist/lib/dialects/abstract/query-generator.js:1702:19) (node:8940) UnhandledPromiseRejectionWarning: TypeError: done is not a function at Strategy._verify (/Users/macintosh/Desktop/node_practice/node_practice/passport/localStrategy.js:30:13) (Use `node —trace-warnings …` to show where the warning was created) (node:8940) 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: 2) (node:8940) [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. PromiseRejectionWarning 부분이 async await 에러 핸들링을 안 해줘서 생긴다고 하는데, 교재에 나와있는대로 localstrategy부분의 에러 핸들링 부분은 교재와 비슷하게 적은 것 같은데...왜 오류가 나는지 잘 모르겠습니다ㅠㅠ //localStrategy.js const passport = require('passport'); const localStrategy = require('passport-local').Strategy; const bcrypt = require('bcrypt'); const { user } = require('../models'); module.exports = () => { passport.use(new localStrategy({ passReqToCallback : true, usernameField:'email', passwordField:'password', }, async (email, password, done) => { try{ const exUser = await user.findOne({where:{email}}); if (exUser) { const result = await user.findOne({where:{password}}); // const result = await bcrypt.compare(password, exUser.password); if(result){ done(null, exUser); } else { done(null, false, {message:'비밀번호가 불일치'}); } } else { done(null, false, {message:'가입되지 않은 회원입니다'}); } } catch (err) { console.error(err); done(err); } } )); }; 위의 코드는 passport/localStrategy.js 파일이며, 아래 코드는 routes/auth.js 파일입니다. const express = require('express'); const passport = require('passport'); const bcrypt = require('bcrypt'); const { isLoggedIn, isNotLoggedIn } = require('./middlewares'); const { user } = require('../models'); const router = express.Router(); //회원가입 라우터 router.post('/join', isNotLoggedIn, async (req,res,next) => { const { email, name, password } = req.body; try { const exUser = await user.findOne({where:{ email }}); if (exUser) { req.flash('joinError', '이미 가입된 이메일입니다') return res.redirect('/join') } await user.create({ email, name, password, }); return res.redirect('/'); } catch (error) { console.error(error); return next(error); } }); //db 확인 router.get('/list', async(req,res)=>{ try{ const rows = await user.findAll(); if (rows) return res.status(200).json({result : rows}); else throw console.log(error); } catch(err){ console.error(err); } }); //로그인 라우터 router.post('/login', isNotLoggedIn, (req,res,next)=>{ //로컬 로그인 전략 성공 시 수행되는 매서드 passport.authenticate('local', {session: false}, (authError, user, info)=>{ if (authError){ console.error(authError); return next(authError); } if (!user) { req.flash('login-error', info.message); return res.redirect('/'); } console.log(user); return req.login(user, (loginError) =>{ if (loginError) { console.error(loginError); return next(loginError); } return res.redirect('/'); }); })(req, res, next); }); //로그아웃 라우터 router.get('/logout', isLoggedIn, (req,res)=>{ req.logOut(); req.session.destroy(); res.redirect('/'); }); module.exports = router;
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
혹시 강의교안이랑
실제 node.js 교과서 교재랑 동일한 내용인건가요? 영상으로는 뭔가 이해가 잘 안가서 책을 사야하나 고민이어서요..
- 해결됨[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
이전 질문에 이어서 새로운 문제가 생겼습니다.
이전에 제가 아래 코드를 사용해서 변경점을 나타내려 하였습니다. const modified = await User.update( { name, age, married, comment, }, { where: { name: params }, } ); 이 코드를 사용한다 한들 변경만 해줄 뿐, 변경점을 나타낼수는 없었습니다. 그래서 저는 코드를 아래 처럼 수정했습니다. const { name, age, married, comment } = req.body; try { const params = decodeURIComponent(req.params.who); const getOld = async () => { const usersBefore = await User.findAll({ where: { name: params }, }); return JSON.stringify(usersBefore[0].dataValues); }; await User.update( { name, age, married, comment, }, { where: { name: params }, } ); const getNew = async () => { const usersAfter = await User.findAll({ where: { name: params }, }); return JSON.stringify(usersAfter[0].dataValues); }; const result1 = await getOld(); const result2 = await getNew(); const message = "유저가 변경되었습니다!"; res.render("show", { result1, result2, message }); } catch (err) { console.error(err); next(err); } 간략하게 제 기준에서 설명드리자면 update()함수를 쓰기 전, 즉 변경전에 데이터를 getOld 함수안에 User.findAll()안에 where옵션으로 라우트 매개변수를 가져옵니다. 저는 여기서 데이터를 바꾸기 전에 데이터가 getOld함수안에 저장되어 있을 거라고 생각했습니다. 그 다음에 User.update() 함수로 데이터를 변경합니다. 그리고 데이터가 변경 되어 있을테니 데이터베이스에서 다시한번 getNew() 함수를 통해서 User.findAll()함수로 바꿔져 있을(제 기준입니다.) 데이터를 getNew함수안에 저장되었을 거라 생각했습니다. 즉 'User.update()를 기준으로 getOld와 getNew에는 각각 변경전과 변경후 데이터가 담겨져 있을거다' 라고 생각했습니다. 하지만 저의 예상은 보기좋게 빗나갔네요 ㅋㅋ getOld와 getNew에는 둘다 똑같이 변경후의 데이터가 저장되어있었습니다. 나름 괜찮은 발상이었는데 변경전 데이터와 변경후 데이터를 어찌 나누면 좋을지 궁금합니다.