묻고 답해요
161만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨탄탄한 백엔드 NestJS, 기초부터 심화까지
추가 업데이트 관련 건
예전에 추가 업데이트 했던 부분은 삭제 된거 같아서,없어진걸까요?원래 이거보고 결제헀었는데..안보인거같아서요.
-
미해결배달앱은 어떻게 내 주변의 맛집을 찾을까?
아래 질문 내용 추가 질문 사항 입니다.
안녕하세요 우선 답변 정말 감사드립니다.일단 말씀 해주신대로해당 프로젝트에서set PYTHONUTF8=1명령어를 입력하고 다시 실행 했지만 계속 동일한 에러가 발생하고 있습니다. poetry shell 해당 명령어도 잘 되는 걸까요? 음... 라이브러리 설치가 안되서.. 강의 진행이 더 이상 안되네요... ChatGPT 도움도 요청 해보았지만 매끄러운 답변은 못 해주고 있어서 어쩔 수 없이 여기로 질문 글 드립니다. 기왕 돈 지불 하고 구입 한 강의 인데.. 여기서 포기 할 수 없습니다.ㅠㅠ 그래도 끝까지 들어야 하지 않나 해서요... 답변 부탁드립니다 ㅠ,ㅠ 참고로 OS 는 윈도우 입니다.
-
해결됨가장 쉽고 깊게 알려주는 MongoDB 완벽 가이드 [ By. 비전공자 & Kakao 개발자 ]
섹션8. CAP 퀴즈 질문
CAP 이론 관점에서, 네트워크 분할 상황 시 MongoDB가 기본적으로 무엇을 우선할까요?A. 세 가지 모두B. 가용성과 분할 내성C. 일관성과 분할 내성D. 일관성과 가용성--정답과 설명 부탁드립니다.생각했던 답이 오답이라고 나와서 질문 드립니다.
-
미해결탄탄한 백엔드 NestJS, 기초부터 심화까지
nest js 버전문제
수강생분들의 질문을 기다립니다! - 에러에 해당하는 질문은 "에러가 발생한 상황에 대한 충분한 설명", "에러 메세지", "에러가 난 코드 스크린샷"을 함께 첨부해주세요. - 언어에 해당하는 질문은 구글링 및 서치 후에 구체적으로 질문해주시면 좋습니다. - 간단한 진로 및 방향성에 대한 질문은 메일로 보내주세요.- 패키지 버전 관리은 실무 환경과 트랜드에 맞추어 강의를 업데이트 하고 있습니다. 강의를 그대로 따라갔는데 에러가 발생한다면 패키지 버전을 강의에서 사용하는 버전과 동일하게 맞춰주세요!- 강의 노트, QA 목록, 공지 사항을 먼저 확인해주세요.- 논리적이고 구체적인 질문은 학습 효과를 올립니다 🙂 노드 버전 20으로 맞추고 강의 node.js 설치된 모듈대로 설치를 했었는데 문법적인 오류가 뜹니다. 이경우는 어떻게 해야되나요?
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 쇼핑몰 사이트 만들기[전체 리뉴얼]
강의자료는 어디서 볼 수있나요??
강의자료는 어디서 볼 수있나요??1강에 강의자료는 코드뿐이던데,,
-
미해결배달앱은 어떻게 내 주변의 맛집을 찾을까?
파이참을 이용해서 Python Interpreter 통해 라이브러리 설치가 안되는데 도움이 필요합니다.
안녕하세요 선생님 일단 좋은 강의 만들어 주셔서 정말 감사드립니다. OS 는 윈도우 사용자이고 말씀해주신 python 3.11.3poetry 1.4.2 설치를 끝냈습니다. 파이참 들어가서 말씀해주신대로 설정을 하고 OK 버튼을 클릭하면 여기서 라이브러리 목록이 나와야 하는데 목록이 안나오는 문제가 발생 하고 있습니다.여기서 OK 버튼을 클릭하면 이렇게 문제가 발생 하고 있는데... 어떻게 해결 해야 할까요?...
-
미해결Do it! Node.js 프로그래밍 입문
몽고db security 설정
15강 몽고DB설정하기 영상의 6분경security 밑에 quickstart 메뉴가 안보이는데아이디와 비밀번호 설정을 어떻게 해야하나요?
-
해결됨React, Node.js, MongoDB로 만드는 나만의 회사 웹사이트: 완벽 가이드
ipify.org api 호출 시 클라이언트 ip주소를 반환하는지?
ch-7-2에서포스트 상세 조회 router 안에서 ipify.org api를 호출하는데포스트 상세 조회 API를 클라이언트에서 호출할 경우서버에서 ipify.org api를 호출하기 때문에 의도한바와 다르게 서버 ip 주소가 나오고 클라이언트 IP는 req.ip를 통해서만 얻을 수 있지않나요??const response = await axios.get("https://api.ipify.org?format=json"); ip = response.data.ip;
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
node.js 버전 및 typescript 적용 문의
안녕하세요 강사님.node.js 강의 수강을 이제 막 시작한 프론트엔드 개발자 수강생입니다.1. 모든 강의는 node.js 14 버전 기준으로 녹화가 된게 맞나요? 맞다면 22LTS 버전으로 설치해도 강의를 수강하는데 문제는 없을까요? 2. 그리고 프로젝트 생성 처음부터 typescript 적용하고 싶은데, 초보자에게 괜찮을까요?비추천이시라면 typescript 없이 시작하려고 합니다.감사합니다.
-
해결됨은행 서버 프로젝트 실습을 통해 배우는 코틀린 마스터 클래스
access_token Db 저장건
휘발성이 강한 access_token 을 redis 에 저장하지 않고, 굳이 mysql 에 저장하는 이유가 있을까요??
-
해결됨은행 서버 프로젝트 실습을 통해 배우는 코틀린 마스터 클래스
data class 관련 질문입니다
강사님 안녕하세요!강의를 듣다가 궁금한 부분이 있어서 질문드립니다. 다름이 아니라, 검색을 해보면 코틀린에서 Entity 정의 시, data class는 권장하지 않고 사용하지 말라는 글들도 나오는데 강의에서는 data class를 사용하셔서 조금 혼란이 오는데요 ㅠㅠ 혹시 실제 코틀린을 사용하는 회사들은 Entity를 정의할 때, 일반 class가 아닌 data class를 사용하나요?
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
12.7. 방장기능(강퇴) 질문드립니다.
socket.on('kicked', (data) => { console.log('강퇴 이벤트 수신'); alert(data.message); window.location.href = data.redirectUrl; }); socket.on('kickUser', (userId) => { console.log('강퇴 요청 받음:', userId); const targetSocket = chat.sockets.get(userId); if (targetSocket) { console.log('강퇴 대상 소켓 찾음'); targetSocket.emit('kicked', { message: '강퇴되었습니다.', redirectUrl: '/' }); setTimeout(() => { // 강퇴된 소켓 연결 해제 targetSocket.disconnect(true); console.log(`사용자 ${userId} 강퇴 완료`); }, 100); } else { console.log(`사용자 ${userId} 소켓을 찾을 수 없음`); } }); socket.on('kicked',가 작동을안하네요 서버쪽에서는 targetSocket.disconnect(true)정상작동합니다.
-
미해결[리뉴얼] 처음하는 MongoDB(몽고DB) 와 NoSQL(빅데이터) 데이터베이스 부트캠프 [입문부터 활용까지] (업데이트)
강의 자료 1,2,7단원만 뜨고 압축 아무리 풀어도 나오지 않는데
이런 식으로 뜨는데 확인 부탁드립니다...!!
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
12.7 socket.js코드 그대로 뱃겨서 했는데, socket.request.session.color가안나오네요
socket.request.session은 서버쪽으로 잘 전달되는데, socket.request.session.color가 전달이안되네요 cors에러도 잡았는데 그래도 안잡히네요
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
12.7 코드 그대로 뱃겨서 햇는데 스샷같이 오류가뜹니다.
완전히 똑같이 복붙하고 실행했는데 계속 이메시지가 프론트엔트에 뜨네요
-
해결됨React, Node.js, MongoDB로 만드는 나만의 회사 웹사이트: 완벽 가이드
ch5-1 관리자 페이지 IP블랙리스트 기능구현 관련
안녕하세요..아래와 같이 에러가뜨는데요;; code: 'MODULE_NOT_FOUND', requireStack: [ '/Users/sungwon/Desktop/Project/Web/company_website/backend/index.js' ]}Node.js v24.4.0[nodemon] app crashed - waiting for file changes before starting....backend > index.js코드 입니다.require("dotenv").config(); const express = require("express"); const mongoose = require("mongoose"); const cookieParser = require("cookie-parser"); const cors = require("cors"); const app = express(); const PORT = 3000; const userRoutes = require("./routes/user"); app.use(express.json()) app.use(express.urlencoded()) app.use(cookieParser()); app.use(cors({ origin: "*", credentials: true, })); app.use("/api/auth", userRoutes); app.get("/", (req, res) => { res.send("Hello world"); }); app.get("/api/check-ip", (req, res) => { const clientIP = req.ip || req.connection.remoteAddress; const blacklistedIPs = JSON.parse(process.env.IP_BLACKLIST || '[]'); console.log("Client IP:", clientIP); console.log("Blacklisted IPs:", blacklistedIPs); if (blacklistedIPs.includes(clientIP)) { return res.status(403).json({ allowed: false, message: "Access denied - IP is blacklisted" }); } res.json({ allowed: true }); }); mongoose .connect(process.env.MONGO_URI) .then(() => console.log("MongoDB와 연결이 되었습니다.")) .catch((error) => console.log("MongoDB와 연결에 실패했습니다: ", error)); app.listen(PORT, () => { console.log("Server is running"); });
-
해결됨React, Node.js, MongoDB로 만드는 나만의 회사 웹사이트: 완벽 가이드
ch4-6 관리자 계정 로그아웃 , 삭제 관련
7:27 시점에서, 터미널에서 선생님은,,eyJhbGcioiJOUzI1N,......주소명이 뜹니다만,,,저의 경우, 아래와 같이 몽고DB에 연결이 되었습니다만 뜹니다.... 이 경우 어떻게 해야할가요... [nodemon] starting node index.js[dotenv@17.2.1] injecting env (2) from .env -- tip: 🔐 prevent committing .env to code: https://dotenvx.com/precommitServer is runningMongoDB와 연결이 되었습니다.[nodemon] restarting due to changes...[nodemon] starting node index.js[nodemon] restarting due to changes...[nodemon] starting node index.js[dotenv@17.2.1] injecting env (2) from .env -- tip: ⚙ suppress all logs with { quiet: true }Server is runningMongoDB와 연결이 되었습니다. 아래는 routes폴더에 있는 user.jsconst express = require("express"); const router = express.Router(); const bcrypt = require("bcrypt"); const User = require("../models/User"); const axios = require("axios"); const jwt = require("jsonwebtoken"); router.post("/signup", async (req, res) => { try { const { username, password } = req.body; const existingUser = await User.findOne({ username }); if (existingUser) { return res.status(400).json({ message: "이미 존재하는 사용자입니다." }); } const hashedPassword = await bcrypt.hash(password, 10); const user = new User({ username, password: hashedPassword, }); await user.save(); res.status(201).json({ message: "회원가입이 완료되었습니다." }); } catch (error) { res.status(500).json({ message: "서버 오류가 발생했습니다." }); console.log(error); } }); router.post("/login", async (req, res) => { try { const { username, password } = req.body; const user = await User.findOne({ username }).select("+password"); if(!user) { return res.status("401").json({message: "사용자를 찾을 수 없습니다."}); } if(!user.isActive){ return res .status(401) .json({ message: "비활성화된 계정입니다. 관리자에게 문의 주세요."}); } if(user.isLoggedIn){ return res .status(401) .json({message: "이미 다른 기기에서 로그인되어 있습니다."}); } const isValidPassword = await bcrypt.compare(password, user.password); if(!isValidPassword){ user.failedLoginAttempts += 1; user.lastLoginAttempt = new Date(); if(user.failedLoginAttempts >= 5){ user.isActive = false; await user.save(); return res.status(401).json({ message: "비밀번호를 5회이상 틀려 계정이 비활성화되었습니다.", }); } await user.save(); return res.status(401).json({ message: "비밀번호가 일치하지 않습니다.", remainingAttempts: 5 - user.failedLoginAttempts, }); } user.failedLoginAttempts = 0; user.lastLoginAttempt = new Date(); user.isLoggedIn = true; try { const response = await axios.get("https://api.ipify.org?format=json"); const ipAddress = response.data.ip; user.ipAddress = ipAddress; } catch (ipError) { console.error("IP 주소를 가져오는 중 오류 발생:", ipError.message); } await user.save(); const token = jwt.sign( { userId: user._id, username: user.username }, process.env.JWT_SECRET, { expiresIn: "24h" } ); res.cookie("token", token, { httpOnly: true, secure: "production", sameSite: "strict", maxAge: 24 * 60 * 60 * 1000, }); const userWithoutPassword = user.toObject(); delete userWithoutPassword.password; res.json({ user: userWithoutPassword }); } catch (error) { console.error("서버 오류:", error.message); res.status(500).json({ message: "서버 오류가 발생했습니다." }); } }); router.post("/logout", async (req, res) => { try { const token = req.cookies.token; if (!token) { return res.status(400).json({ message: "이미 로그아웃된 상태입니다." }); } try { const decoded = jwt.verify(token, process.env.JWT_SECRET); const user = await User.findById(decoded.userId); if (user) { user.isLoggedIn = false; await user.save(); } } catch (error) { console.log("토큰 검증 오류: ", error.message); } res.clearCookie("token", { httpOnly: true, secure: "production", sameSite: "strict", }); res.json({ message: "로그아웃되었습니다." }); } catch (error) { console.log("로그아웃 오류: ", error.message); res.status(500).json({ message: "서버 오류가 발생했습니다." }); } }); router.delete("/delete/:userId", async (req, res) => { try { const user = await User.findByIdAndDelete(req.params.userId); if (!user) { return res.status(404).json({ message: "사용자를 찾을 수 없습니다." }); } res.json({ message: "사용자가 성공적으로 삭제되었습니다." }); } catch (error) { res.status(500).json({ message: "서버 오류가 발생했습니다." }); } }); module.exports = router; env.에 표기한 부분MONGO_URI=mongodb+srv://sungwon5623:cho121101!@sungwon.oirqw5d.mongodb.net/?retryWrites=true&w=majority&appName=Sungwon JWT_SECRET=c21b6ba5372fa2b8 models폴더에 있는 User.jsconst mongoose = require("mongoose"); const userSchema = new mongoose.Schema( { username: { type: String, required: true, trim: true, minlength: 2, maxlength: 30, }, password: { type: String, required: true, select: false, }, isLoggedIn: { type: Boolean, default: false, }, isActive: { type: Boolean, default: true, }, failedLoginAttempts: { type: Number, default: 0, }, lastLoginAttempt: { type: Date, }, ipAddress: { type: String, trim: true, }, createdAt: { type: Date, default: Date.now, }, }, { timestamps: true, } ); const User = mongoose.model("User", userSchema); module.exports = User;
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
12.7.1스스로 해보기 질문되나요
//채팅창에 현재 참여자 수나 목록표시하기구현한chat.html코드와 socket.j코드입니다. 그런데 chat: ${socket.request.session.color} 이부분이 undefined으로 계속 나옵니다. console.log에 찍어보면 socket.request.session에 color만 빼고 나오네요.{% extends 'layout.html' %} {% block content %} <h1>{{title}}</h1> <a href="/" id="exit-btn">방 나가기</a> <fieldset> <legend>채팅 내용</legend> <div style="display: flex; gap: 20px;"> <!-- 채팅 목록 --> <div id="chat-list" style="flex: 3;"> {% 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> <!-- 참여자 목록 --> <div style="flex: 1;"> <h3>참여자</h3> <ul id="user-list"></ul> </div> </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', transports: ['websocket'] }); 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'); chat.textContent = data.chat; div.appendChild(chat); document.querySelector('#chat-list').appendChild(div); if (data.userList) { const ul = document.querySelector('#user-list'); // 참여자 목록이 들어갈 ul ul.innerHTML = ''; // 기존 목록 초기화 data.userList.forEach(function (user) { const li = document.createElement('li'); li.textContent = user; ul.appendChild(li); }); } }); socket.on('exit', function (data) { const div = document.createElement('div'); div.classList.add('system'); const chat = document.createElement('div'); chat.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.src = '/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 %} const SocketIO = require('socket.io');const { removeRoom } = require('./services'); module.exports = (server, app, sessionMiddleware) => { const io = SocketIO(server, { path: '/socket.io',transports: ['websocket'] }); app.set('io', io); const room = io.of('/room'); const chat = io.of('/chat'); const wrap = middleware => (socket, next) => middleware(socket.request, {}, next); chat.use(wrap(sessionMiddleware)); room.on('connection', (socket) => { console.log('room 네임스페이스에 접속'); socket.on('disconnect', () => { console.log('room 네임스페이스 접속 해제'); }); }); chat.on('connection', (socket) => { console.log('chat 네임스페이스에 접속'); console.log(socket.request.session); socket.on('join', (roomId) => { socket.join(roomId); const room = socket.adapter.rooms.get(roomId); // Set const userList = room ? Array.from(room) : []; // 시스템 메시지 + 사용자 목록 전송 socket.to(roomId).emit('join', { user: 'system', chat: `${socket.request.session.color}님이 입장하셨습니다.`, userList, }); }); socket.on('disconnect', async () => { console.log('chat 네임스페이스 접속 해제'); const { referer } = socket.request.headers; // 브라우저 주소가 들어있음 const roomId = new URL(referer).pathname.split('/').at(-1); const currentRoom = chat.adapter.rooms.get(roomId); const userCount = currentRoom?.size || 0; if (userCount === 0) { // 유저가 0명이면 방 삭제 await removeRoom(roomId); // 컨트롤러 대신 서비스를 사용 room.emit('removeRoom', roomId); console.log('방 제거 요청 성공'); } else { socket.to(roomId).emit('exit', { user: 'system', chat: `${socket.request.session.color}님이 퇴장하셨습니다.`, }); } }); });}
-
미해결[리뉴얼] 처음하는 MongoDB(몽고DB) 와 NoSQL(빅데이터) 데이터베이스 부트캠프 [입문부터 활용까지] (업데이트)
강의9분 조건연산자 관련 질문입니다
db.users.find({age: {$lt:30, $gt:40}})안녕하세요강의 9분쯤 사용하신 이 구문이 작동되지 않아서 ai에게 물어보니 틀린 문법이라고 $or 를 사용하라고 합니다.그런데 선생님 화면에는 잘 출력이 되어서 여쭤봅니다.어떤게 맞는건가요?
-
해결됨React, Node.js, MongoDB로 만드는 나만의 회사 웹사이트: 완벽 가이드
ch4-5 관리자 계정 로그인, JWT토큰 관련
덕분에 무사히 다음 강의 듣고있는데요또 막혔습니다;;; MongoDB는 연결이 잘되는데요;;{ id : new ObjectId(''''')등등 터미널에 admin과 패스워드 등의 데이터카 안뜹니다;;;