묻고 답해요
161만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결Slack 클론 코딩[실시간 채팅 with React]
ts-node 대신 tsx 사용여부
질문: 1.ts-node로 이어나가도 괜찮을까요?2. outdated 명령어 쳐보니 버전이 강의에서 한두개 추가설치했지만, 이제 빨간 글씨로 10개 정도 다 버전 업그레이드를 요구했습니다.제가 고쳐나가면서 나아가보면될지 궁금합니다.ㅡㅡㅡㅡㅡㅡㅡㅡ상황: 몇주전 타입스크립트를 다른 강의로 시작했습니다.최근 환경설정에서 ts-node 사용시 오류가 계속 떠서 그 강의가 tsx 사용을 권장했고, tsx로 입문했습니다.그래서 ts-node로 잘돌아갈지 의문입니다.
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
실시간 채팅방에서 GIF uploads 하면 GIF가 바로 화면에 보이지 않고 새로 고침을 해야 보이는데 어떻게 해야 할까요?
실시간 채팅방 강좌 코드를 작성하여 작동 시켜 본 결과 메시지 전송 까지는 잘 되는 것을 확인 하였는데 GIF 업로드 시 다음 그림과 같은 현상이 발생하고 있습니다그림 하단에 표시한 부분 처럼 처음에 GIF 올리기를 하면 그림이 보이지 않다가 새로 고침을 하면 위의 다른 GIF 처럼 잘 보이긴 하는데 무슨 문제 일까요?참고로 관련 코드를 같이 올립니다chat.html {% extends 'layout.html' %} {% block content %} <h1>{{title}}</h1> <a href="/" id="exit-btn">방 나가기</a> <fieldset> <legend>채팅 내용</legend> <div id="chat-list"> {% for chat in chats %} {% if chat.user === user %} <div class="mine" style="color: {{chat.user}}"> <div>{{chat.user}}</div> {% if chat.gif %}} <img src="/gif/{{chat.gif}}"> {% else %} <div>{{chat.chat}}</div> {% endif %} </div> {% elif chat.user === 'system' %} <div class="system"> <div>{{chat.chat}}</div> </div> {% else %} <div class="other" style="color: {{chat.user}}"> <div>{{chat.user}}</div> {% if chat.gif %} <img src="/gif/{{chat.gif}}"> {% else %} <div>{{chat.chat}}</div> {% endif %} </div> {% endif %} {% endfor %} </div> </fieldset> <form action="/chat" id="chat-form" method="post" enctype="multipart/form-data"> <label for="gif">GIF 올리기</label> <input type="file" id="gif" name="gif" accept="image/gif"> <input type="text" id="chat" name="chat"> <button type="submit">전송</button> </form> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <script src="/socket.io/socket.io.js"></script> <script> const socket = io.connect('http://localhost:8005/chat', { path: '/socket.io', }); socket.emit('join', new URL(location).pathname.split('/').at(-1)); socket.on('join', function (data) { const div = document.createElement('div'); div.classList.add('system'); const chat = document.createElement('div'); div.textContent = data.chat; div.appendChild(chat); document.querySelector('#chat-list').appendChild(div); }); socket.on('exit', function (data) { const div = document.createElement('div'); div.classList.add('system'); const chat = document.createElement('div'); div.textContent = data.chat; div.appendChild(chat); document.querySelector('#chat-list').appendChild(div); }); socket.on('chat', function (data) { const div = document.createElement('div'); if (data.user === '{{user}}') { div.classList.add('mine'); } else { div.classList.add('other'); } const name = document.createElement('div'); name.textContent = data.user; div.appendChild(name); if (data.chat){ const chat = document.createElement('div'); chat.textContent = data.chat; div.appendChild(chat); } else { const gif = document.createElement('img'); gif.sr = '/gif/' + data.gif; div.appendChild(gif); } div.style.color = data.user; document.querySelector('#chat-list').appendChild(div); }); document.querySelector('#chat-form').addEventListener('submit', function (e) { e.preventDefault(); if (e.target.chat.value) { axios.post('/room/{{room._id}}/chat', { chat: this.chat.value, }) .then( () => { e.target.chat.value = ''; }) .catch( (err) => { console.error(err); }); } }); document.querySelector('#gif').addEventListener('change', function (e) { console.log('******',e.target.files); const formData = new FormData(); formData.append('gif', e.target.files[0]); axios.post('/room/{{room._id}}/gif', formData) .then( () => { e.target.file = null; }) .catch( (err) => { console.error(err); }); }); </script> {% endblock %} routes/index.jsconst express = require('express'); const { renderMain, renderRoom, createRoom, enterRoom, removeRoom, sendChat, sendGif } = require('../controllers'); const multer = require('multer'); const fs = require('fs'); const path = require('path'); const router = express.Router(); router.get('/', renderMain); router.get('/room', renderRoom); router.post('/room', createRoom); router.get('/room/:id', enterRoom); router.delete('/room/:id', removeRoom); router.post('/room/:id/chat', sendChat); try {fs.readdirSync('uploads'); } catch (err) { console.error('uploads 폴더가 없어 uploads 폴더를 생성합니다.'); fs.mkdirSync('uploads'); } const upload = multer({ storage: multer.diskStorage({ destination(req, file, done) { done(null, 'uploads/'); }, filename(req, file, done ) { const ext = path.extname(file.originalname); done(null, path.basename(file.originalname, ext) + Date.now() + ext); }, }), limits: {fileSize: 5 * 1024 *1024 }, }) router.post('/room/:id/gif', upload.single('gif'), sendGif); module.exports = router;controllers/index.jsconst Room = require('../schemas/room'); const Chat = require('../schemas/chat'); const { removeRoom: removeRoomService } = require('../services'); exports.renderMain = async ( req, res, next ) => { try{ const rooms = await Room.find({}); res.render('main', {rooms, title: 'GIF 채팅방'}); } catch (error) { console.error(error); next(error); } }; exports.renderRoom = ( req, res, next ) => { res.render('room', { title: 'GIF 채팅방 생성'}); }; exports.createRoom = async ( req, res, next ) => { try{ const newRoom = await Room.create({ title: req.body.title, max: req.body.max, owner: req.session.color, password: req.body.password, //session data 에서 옮 }); const io = req.app.get('io'); io.of('/room').emit('newRoom', newRoom); // 방에 들어가는 부분 if (req.body.password ) { res.redirect(`/room/${newRoom._id}?password=${req.body.password}`); } else { res.redirect(`/room/${newRoom._id}`); } } catch (error) { console.error(error); next(error); } }; exports.enterRoom = async( req, res, next ) => { try{ const room = await Room.findOne({_id: req.params.id}); if (!room){ return res.redirect('/?error=존재하지 않는 방입니다.'); } if (room.password && room.password !== req.query.password ){ return res.redirect('/?error=비밀번호가 틀렸습니다.'); } const io = req.app.get('io'); const { rooms } = io.of('/chat').adapter; if (room.max <= rooms.get(req.params.id)?.size) { return res.redirect('/?error=허용 인원을 초과하였습니다.'); } const chats = await Chat.find({room: room._id }).sort('createdAt'); res.render('chat', { title: 'GIF 채팅방 생성', chats , room, user: req.session.color }); } catch (error) { console.error(error); next(error); } }; exports.removeRoom = async ( req, res, next ) => { try { await removeRoomService(req.params.id ); res.send('ok'); setTimeout(() => { req.app.get('io').of('/room').emit('removeRoom', req.params.id); }, 2000) } catch (error) { console.error(error); next(error); } }; exports.sendChat = async (req, res, next ) =>{ try { const chat = await Chat.create({ room: req.params.id, user: req.session.color, chat: req.body.chat, }); req.app.get('io').of('/chat').to(req.params.id).emit('chat', chat); res.send('ok'); } catch( error ){ console.error(error); next(error); } } exports.sendGif = async (req, res, next ) => { try { const chat = await Chat.create({ room : req.params.id, user: req.session.color, gif: req.file.filename, }) setTimeout(() => { req.app.get('io').of('/chat').to(req.params.id).emit('chat',chat); }, 1000); res.send('ok'); } catch (error) { console.error(error); next(error); } } [제로초 강좌 질문 필독 사항입니다]질문에는 여러분에게 도움이 되는 질문과 도움이 되지 않는 질문이 있습니다.도움이 되는 질문을 하는 방법을 알려드립니다.https://www.youtube.com/watch?v=PUKOWrOuC0c0. 숫자 0부터 시작한 이유는 1보다 더 중요한 것이기 때문입니다. 에러가 났을 때 해결을 하는 게 중요한 게 아닙니다. 왜 여러분은 해결을 못 하고 저는 해결을 하는지, 어디서 힌트를 얻은 것이고 어떻게 해결한 건지 그걸 알아가셔야 합니다. 그렇지 못한 질문은 무의미한 질문입니다.1. 에러 메시지를 올리기 전에 반드시 스스로 번역을 해야 합니다. 번역기 요즘 잘 되어 있습니다. 에러 메시지가 에러 해결 단서의 90%를 차지합니다. 한글로 번역만 해도 대부분 풀립니다. 그냥 에러메시지를 올리고(심지어 안 올리는 분도 있습니다. 저는 독심술사가 아닙니다) 해결해달라고 하시면 아무런 도움이 안 됩니다.2. 에러 메시지를 잘라서 올리지 않아야 합니다. 입문자일수록 에러메시지에서 어떤 부분이 가장 중요한 부분인지 모르실 겁니다. 그러니 통째로 올리셔야 합니다.3. 코드도 같이 올려주세요. 다만 코드 전체를 다 올리거나, 깃헙 주소만 띡 던지지는 마세요. 여러분이 "가장" 의심스럽다고 생각하는 코드를 올려주세요.4. 이 강좌를 바탕으로 여러분이 응용을 해보다가 막히는 부분, 여러 개의 선택지 중에서 조언이 필요한 부분, 제 경험이 궁금한 부분에 대한 질문은 대환영입니다. 다만 여러분의 회사 일은 질문하지 마세요.5. 강좌 하나 끝날 때마다 남의 질문들을 읽어보세요. 여러분이 곧 만나게 될 에러들입니다.6. 위에 적은 내용을 명심하지 않으시면 백날 강좌를 봐도(제 강좌가 아니더라도) 실력이 늘지 않고 그냥 코딩쇼 관람 및 한컴타자연습을 한 셈이 될 겁니다.
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
app.js 에서 sequelize 를 가져오는 부분이 models/index.js 있는 sequelize 를 가르키는게 맞나요?
[제로초 강좌 질문 필독 사항입니다]세션 6번app.js 시퀄라이즈 싱크에 관한 문의 입니다.const { sequelize } = require('./models');app.js 에서 시퀄라이즈를 가져오는데 해당 모둘안에는 3개의 파일 있습니다 .( user, comment, index ) index 파일만 실행하면 될거 같은데 sequelize 자져오는 이유가 궁금하고 , 여기서 가르키는 sequelize 가 index에 있는 sequelize 인지 궁금합니다.
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
req.login에서 passport.serializeUser 호출 원리
passport로 로그인 실습을 진행중에 있습니다. passport.initialize(); 이후에 localStrategy 등록해둔 메서드를 통해 로그인 여부 확인하는 데까지는 까지는 이해가 되었습니다. 그런데 /controller/auth.js 에서 req.login 이후에 passport.serializeUser이 호출되는 방식이 이해가 안되네요.www.passportjs.org 에서문서를 읽어보고 있는데 꼼꼼함이 부족한지 이해가 잘 안되네요. req.login 메서드 자체를 passport에서 정의하고 있고 login 메서드가 호출될때 자동으로 serializeUser가 호출되는건가요?
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
스스로하기에서 귓속말 구현할때
socket.id로 하면맨첨엔 귓속말 잘되는데 유저가 나갔다가 들어오면 socket.id가 갱신되어서 예전에 보냈던 채팅의 귓속말 버튼으로는 귓속말이 안가게 되는데 저만 이런건가요??
-
해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
노드 삭제 재설치
그러면 안되지만 잘못 설치했을경우 노드 삭제 재설치 및 버전 업데이트 하는 방법에 대해서 혹시 유튜브에라도 해당 내용이 있을실까요?
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
저는왜 렌더링 화면이 다를까요 ?
저는 이 화면으로만 보이고 domain 적는 구간이없는데.. 왜그럴까요 계속 로그인 상태 알람만 발생합니다. <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>API 서버 로그인</title> <style> .input-group label { width: 200px; display: inline-block; } </style> </head> <body> {% if user and user.id %} <span class="user-name">안녕하세요! {{user.nick}}님</span> <a href="/auth/logout"> <button>로그아웃</button> </a> <fieldset> <legend>도메인 등록</legend> <form action="/domain" method="post"> <div> <label for="type-free">무료</label> <input type="radio" id="type-free" name="type" value="free"> <label for="type-premium">프리미엄</label> <input type="radio" id="type-premium" name="type" value="premium"> </div> <div> <label for="host">도메인</label> <input type="text" id="host" name="host" placeholder="ex) zerocho.com"> </div> <button>저장</button> </form> </fieldset> <table> <tr> <th>도메인 주소</th> <th>타입</th> <th>클라이언트 비밀키</th> </tr> {% for domain in domains %} <tr> <td>{{domain.host}}</td> <td>{{domain.type}}</td> <td>{{domain.clientSecret}}</td> </tr> {% endfor %} </table> {% else %} <form action="/auth/login" id="login-form" method="post"> <h2>NodeBird 계정으로 로그인하세요.</h2> <div class="input-group"> <label for="email">이메일</label> <input id="email" type="email" name="email" required autofocus> </div> <div class="input-group"> <label for="password">비밀번호</label> <input id="password" type="password" name="password" required> </div> <div>회원가입은 localhost:8001에서 하세요.</div> <button id="login" type="submit">로그인</button> </form> <script> window.onload = () => { if (new URL(location.href).searchParams.get('error')) { alert(new URL(location.href).searchParams.get('error')); } }; </script> {% endif %} </body> </html> view에 login도 위와 같이 들어가있습니다.const { User, Domain } = require("../models"); const { v4: uuidv4 } = require("uuid"); exports.renderLogin = async (req, res, next) => { try { const user = await User.findOne({ where: { id: res.user?.id || null }, include: { model: Domain } }) res.render("login", { user, domains: user?.Domains }) } catch (err) { console.error(err) next(err); } } exports.createDomain = async (req, res, next) => { try { await Domain.create({ UserId: req.user.id, host: req.body.host, type: req.body.type, client: uuidv4() }) res.redirect("/"); } catch (err) { console.error(err); next(err); } } controller에서도 강의대로 잘 렌더가 들어가있습니다. 그러니 화면이 보이긴하는데 왜 저만안보일까요..- app.js에 passport의 initialize(), session() 함수 선언되어있습니다. - cookie도 있습니다.- db에 user도 있습니다.
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
api호출 제한이 안되는 질문에서 제로초님이 제공해주신 코드중에서의 질문입니다!
해당 질문에서 제로초님이const limiter = rateLimit({ widowMs: 60 * 1000, max: (req, res) => { if (req.user?.type === 'premium') { return 10 } return 1; }, handler(req, res) { res.status(this.statusCode).json({ code: this.statusCode, message: `1분에 ${req.user?.type === 'premium' ? '열' : '한'} 번만 요청 할 수 있습니다...`, }); }, }); exports.apiLimiter = async (req, res, next) => { let user; if (res.locals.decoded) { user = await User.findOne({ where: { id: res.locals.decoded.id } }); } req.user = user; limiter(req, res, next); };이렇게 주셨는데 여기서 limiter을 상수형태로 참조하게끔하면 그럼 다수의 유저가 호출을 하게 될때limiter이 같은 함수를 가르키고있어서 다른 유저가 호출한 api횟수에 영향을 받게 되지않나요? 강의 너무 잘보고있습니다!
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
강사님 질문 드립니다.
제공해주신 멀티스레드 소켓 프로그램에 LPVOID 형을 가지는 매개변수에 일반 변수를 지정하셨는데 LPVOID 는 포인터와 일반변수 모두 가능 한 건지요?주신 프로그램을 보면 SOCKET hClient = 0; // SOCKET 형 변수를 선언 hThread = ::CreateThread( NULL, 0,ThreadFunction, (LPVOID)hClient, // 주소가 아닌 값을 지정0, &dwThreadID); 만약 가능하다면 내부적으로 어떻게 가능한지 확인 부탁드려봅니다. 늘 좋은 강의 감사합니다. 강사님
-
미해결Slack 클론 코딩[실시간 채팅 with React]
배포 관련 질문
안녕하세요포트폴리오를 하나 만들고 싶어서 슬리액 프론트 관련해서 다 클론코딩하였는데강사님이 배포하신거 비슷하게 sleat.nodebird.com 처럼 유사하게 배포할려면 리액트 노드버드 강좌에서aws 나 배포관련 부분만 들으면 될까요?
-
미해결Slack 클론 코딩[실시간 채팅 with React]
[배포하기] webpack에 aws 퍼블릭 IPv4 주소 와 포트 주소를 작성하고 나서 빌드후 실행하면 오류가 발생합니다.
[배포하기]를 수강 이후에 개발한 프로젝트를aws에 배포하는 중에서 문제가 발생하여 질문 드려요 devServer: { historyApiFallback: true, host: '퍼블릭 IPv4 주소', port: 3333, devMiddleware: { publicPath: '/dist/' }, static: { directory: path.resolve(__dirname) }, },host에 퍼블릭 IPv4 주소 을 설정하고 aws에 port 3333 포트를 열어 주었습니다. "scripts": { "dev": "webpack serve --env development", "build": "webpack", "start": "webpack serve" },npm run build 이후에npm run start 할 경우(퍼블릭 IPv4 주소 -> ex: 11.111.111.11 Error: listen EADDRNOTAVAIL: address not available 11.111.111.11:3333 at Server.setupListenHandle [as _listen2] (net.js:1314:21) at listenInCluster (net.js:1379:12) at doListen (net.js:1516:7) at processTicksAndRejections (internal/process/task_queues.js:83:21) { code: 'EADDRNOTAVAIL', errno: -99, syscall: 'listen', address: '11.111.111.11', port: 3333 }오류가 발생했습니다. 무엇이 문제인지 잘 모르겠어서 질문드립니다. [aws 실행상태]aws_인스턴스 한개에 back,front 폴더를 git을 사용 하여 백,프론트를 실행하고 있습니다.[전체 코드 - webpack.config.js]const path = require('path'); const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); const webpack = require('webpack'); const isDevelopment = process.env.NODE_ENV !== 'production'; const config = { name: 'google_meet', mode: isDevelopment ? 'development' : 'production', devtool: isDevelopment ? 'hidden-source-map' : 'inline-source-map', resolve: { extensions: ['.js', '.jsx', '.json'], alias: { '@hooks': path.resolve(__dirname, 'hooks'), '@components': path.resolve(__dirname, 'components'), '@layouts': path.resolve(__dirname, 'layouts'), '@pages': path.resolve(__dirname, 'pages'), '@utils': path.resolve(__dirname, 'utils'), }, }, entry: { app: './client', }, module: { rules: [ { test: /\.jsx?$/, loader: 'babel-loader', options: { presets: [ [ '@babel/preset-env', { targets: { browsers: ['last 2 chrome versions'] }, debug: isDevelopment, }, ], '@babel/preset-react', ], env: { development: { plugins: [require.resolve('react-refresh/babel')], }, }, }, exclude: path.join(__dirname, 'node_modules'), }, { test: /\.css?$/, use: ['style-loader', 'css-loader'], }, ], }, plugins: [new webpack.EnvironmentPlugin({ NODE_ENV: isDevelopment ? 'development' : 'production' })], output: { path: path.join(__dirname, 'dist'), filename: '[name].js', publicPath: '/dist/', }, devServer: { historyApiFallback: true, host: '퍼블릭 IPv4 주소', port: 3333, devMiddleware: { publicPath: '/dist/' }, static: { directory: path.resolve(__dirname) }, }, }; if (isDevelopment && config.plugins) { config.plugins.push(new webpack.HotModuleReplacementPlugin()); config.plugins.push(new ReactRefreshWebpackPlugin()); } if (!isDevelopment && config.plugins) { } module.exports = config;
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
React나 Vue 사용 시 렌더링 질문
서버 사이드 렌더링은 넌적스나 도그스 보니까 이해가 됩니다.React,Vue를 원래 실무에서 사용한다는 뜻은 혹시 클라이언트 사이드렌더링에 관점에서 말씀하신건지 궁금합니다. 서버사이드렌더링 처럼 데이터를 넣어서 static 파일 전달하는 형태를 말씀하신거라면 방법이 궁금합니다 !
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
노드 비동기 동작 질문
0. 대부분 무거운 연산이나 오래걸리는 일들을 비동기로 보내는 것으로 이해했습니다. 그런데 결국 비동기요소들이 Background 대기 후 Task Queue으로 이동 후 Stack이 비었는지 확인 하고 Stack에 이동하여 진행되는 것일 텐데 이것들이 동시에 처리되는 것이라고 볼 수 있나요 ? 아니면 Background에 있는 동안 Promise와 같은 비동기 요소들이 백그라운드에서 동시에 Logic이 처리되고 Queue로 resolve혹은 reject의 값이 Stack으로 넘어가나요 ? 구체적인 동작방식이 궁금합니다.
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
넌적스로 {% include .html} 시 template not found 오류
안녕하세요, 변수에 할당되는 값에 따라서 html 파일을 다르게 include 하고 싶은데,template not found 오류가 뜹니다. 처음에 변수에 값을 넘기고 app.js에서 렌더링할 때 하기와 같이 설정했습니다. 그 뒤, index.html 에해당 코드를 추가하여 viewAlimtalk에 값이 있다면 test.html을 include할 수 있도록 하였습니다. 그런데 오류는 index 템플릿을 찾을 수 없다고 뜹니다. Error: template not found: index at Object._prettifyError (C:\alimtalk\node_modules\nunjucks\src\lib.js:32:11) at C:\alimtalk\node_modules\nunjucks\src\environment.js:464:19 at eval (eval at compile (C:\alimtalk\nodemodules\nunjucks\src\environment.js:527:18), <anonymous>:22:11) at C:\alimtalk\node_modules\nunjucks\src\environment.js:471:11 at eval (eval at compile (C:\alimtalk\nodemodules\nunjucks\src\environment.js:527:18), <anonymous>:16:11) at createTemplate (C:\alimtalk\node_modules\nunjucks\src\environment.js:238:11) at next (C:\alimtalk\node_modules\nunjucks\src\lib.js:260:7) at handle (C:\alimtalk\node_modules\nunjucks\src\environment.js:267:11) at C:\alimtalk\node_modules\nunjucks\src\environment.js:276:9 at next (C:\alimtalk\node_modules\nunjucks\src\lib.js:258:7) index.html에 {% include "test.html" %} 코드를 지우고 실행하면 해당 오류는 없이 index.html이 잘뜨게됩니다 .. 파일구조는 views index.htmltest.html로 되어있고, 넌적스 configure도 views 파일로 설정하였습니다. 왜이런 오류가 뜨게 되는걸까요?? if 값에 따라 html을 동적으로 삽입할 수 있는 다른 방법이 있을까요? 혹은, 버튼 클릭 시 router 을 통한 render가 아닌 바로 넌적스 변수를 변경할 수 있는 코드를 작성할 수는 없을까요?
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
ws 프로토콜 연결시 사이트 연결할 수 없음 메세지가 나오고 페이지 호출이 되지 않습니다.
브라우저 사파리에서는 정상동작 합니다참고로 크롬 버젼은 123.0.6312.107(공식 빌드) (arm64)맥에서 실행했습니다.
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
9장 스스로하기 캐싱문제..
지금까지 9장 스스로하기 문제들을 겨우겨우 해결해 나가고 있는데요, 그래도 다른 것들은 제로초님의 강의를 돌려보면서 검색과 함께 해볼만한 난이도였지만, 마지막 캐싱은 어떻게 해야할지 감도 안잡힙니다. 객체를 선언하라는 것도 전역변수에 User 배열을 선언해서 전부 집어넣고 Post도 배열을 만들어서 집어넣으라는 소린지.. 만약 만든다면 어떤 파일에 전역변수를 선언해야할까가 문제입니다. ㅜ 쓰이는 곳도 많아서 쓰이는 곳 마다 해당 파일에 전역변수를 설정해야할까요?
-
해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
좋아요 기능 구현중
models/user에서 static associate(db){ db.User.belongsToMany(db.Post,{ foreignKey: 'postId', as: 'LikedPosts', through: 'Like', }); } 그리고 models/post에서static associate(db){ db.Post.belongsToMany(db.User,{ foreignKey: 'userId', as: 'LikingUsers', through: 'Like', }); }이렇게 해놓았는데이러면 좋아요와 좋아요취소기능은 잘 작동하고 이를통해 프로필을 볼때 사용자가 좋아요한 게시글들만 볼 수 있는 기능도 잘 작동합니다.하지만 mysql workbench를 보면이와같이 userId에 post의 Id가, postId에는 userId가 들어가있는데요, 그래서 foreignKey를 post에선 postId로, user 에선 userId로 바꿨더니 Like 테이블에 삽입하려는 postId가 users 테이블의 id와 관련하여 참조 무결성 제약 조건을 위반했다는 오류가 뜹니다! ㅜ왜이런 현상들이 일어나는지 검색을 해도 안나와서 여쭤봅니다!
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
res.locals에 follower에 관해 저장할때 다른방법
수업중에서 res.locals에 follower에 관해 저장할때 deserialize 에서 include를 하면서 req.user에 추가를 해주었는데요,제로초님이 await으로 userfindOne을 해서 어떻게 하는 다른방법도 있다고 하셨는데 그 코드를 알려줄수있을까요?저 혼자 해보는데 잘 안되네요.
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
upload2를 안쓰고 그냥 해도 되지않나요?
강의중 제로초님이 routes폴더의 post.js를 작성하실때const upload2 = multer();router.post('/', isLoggedIn,upload2.none(), uploadPost);이렇게 작성하셨는데,그냥 router.post('/', isLoggedIn, uploadPost);로 작성해도 되지않나요?
-
미해결Slack 클론 코딩[실시간 채팅 with React]
users 호출 시 쿠키가 담기지 않는 이슈 질문드립니다.
users 호출 시 쿠키가 담기지 않는 이슈 질문드립니다.강의 중간에 proxy 설정은 로컬에서 개발을 진행할때 설정을 한다고 말씀을 해주셨는데webpack.config에 proxy 설정을 하고 credential true 설정후 /api/users 와 /api/users/login으로 요청하면 users 요청 안에 쿠키가 담기는데proxy 설정을 주석 처리하고프론트 서버 3090 에서 백 서버 3095로 직접 요청을 하는 풀 도메인 경로를 다 작성해서 요청을 하면 users에 쿠키가 안담기는데 이유가 있을까요??application 탭에는 쿠키가 생성 되어있습니다. [제로초 강좌 질문 필독 사항입니다]질문에는 여러분에게 도움이 되는 질문과 도움이 되지 않는 질문이 있습니다.도움이 되는 질문을 하는 방법을 알려드립니다.https://www.youtube.com/watch?v=PUKOWrOuC0c0. 숫자 0부터 시작한 이유는 1보다 더 중요한 것이기 때문입니다. 에러가 났을 때 해결을 하는 게 중요한 게 아닙니다. 왜 여러분은 해결을 못 하고 저는 해결을 하는지, 어디서 힌트를 얻은 것이고 어떻게 해결한 건지 그걸 알아가셔야 합니다. 그렇지 못한 질문은 무의미한 질문입니다.1. 에러 메시지를 올리기 전에 반드시 스스로 번역을 해야 합니다. 번역기 요즘 잘 되어 있습니다. 에러 메시지가 에러 해결 단서의 90%를 차지합니다. 한글로 번역만 해도 대부분 풀립니다. 그냥 에러메시지를 올리고(심지어 안 올리는 분도 있습니다. 저는 독심술사가 아닙니다) 해결해달라고 하시면 아무런 도움이 안 됩니다.2. 에러 메시지를 잘라서 올리지 않아야 합니다. 입문자일수록 에러메시지에서 어떤 부분이 가장 중요한 부분인지 모르실 겁니다. 그러니 통째로 올리셔야 합니다.3. 코드도 같이 올려주세요. 다만 코드 전체를 다 올리거나, 깃헙 주소만 띡 던지지는 마세요. 여러분이 "가장" 의심스럽다고 생각하는 코드를 올려주세요.4. 이 강좌를 바탕으로 여러분이 응용을 해보다가 막히는 부분, 여러 개의 선택지 중에서 조언이 필요한 부분, 제 경험이 궁금한 부분에 대한 질문은 대환영입니다. 다만 여러분의 회사 일은 질문하지 마세요.5. 강좌 하나 끝날 때마다 남의 질문들을 읽어보세요. 여러분이 곧 만나게 될 에러들입니다.6. 위에 적은 내용을 명심하지 않으시면 백날 강좌를 봐도(제 강좌가 아니더라도) 실력이 늘지 않고 그냥 코딩쇼 관람 및 한컴타자연습을 한 셈이 될 겁니다.