묻고 답해요
156만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결[개정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)정상작동합니다.
-
해결됨Slack 클론 코딩[실시간 채팅 with React]
기본 셋팅과 관련하여
settings/ts 폴더 front로 바꿔서 진행할 경우 셋팅 강의 하나도 들을 필요없이 바로 섹션2부터 진행해도 되는건가요?
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
12.7 socket.js코드 그대로 뱃겨서 했는데, socket.request.session.color가안나오네요
socket.request.session은 서버쪽으로 잘 전달되는데, socket.request.session.color가 전달이안되네요 cors에러도 잡았는데 그래도 안잡히네요
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
12.7 코드 그대로 뱃겨서 햇는데 스샷같이 오류가뜹니다.
완전히 똑같이 복붙하고 실행했는데 계속 이메시지가 프론트엔트에 뜨네요
-
미해결Slack 클론 코딩[실시간 채팅 with React]
초기 셋팅 back과 front만 남겨두고 다 지운 후 진행 방법
강좌에서 언급한대로 직접 세팅하기보다는 그냥 settings/ts 폴더 클론받아서 하시는 것을 추천드립니다. 직접 세팅하기에는 버전이 자꾸 달라져서 세팅법이 바뀌고, 입문자분들한테는 버겁습니다. 폴더가 많아서 헷갈리니 back 폴더는 백엔드 용으로 남겨두시고, setting/ts 폴더를 front 폴더로 바꾼 뒤 나머지 폴더는 전부 지워버리세요. 라는 말씀에 따라다음과 같이 세팅을 했는데,alecture 폴더로 들어가 npm init 을 하라고 하시는 부분이 이해가 어렵습니다.
-
미해결[개정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}님이 퇴장하셨습니다.`, }); } }); });}
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
스타,워크와 같은 디스창 (Disconnected)도 비정상 종료에 대응하는 시스템으로 봐야할까요?
-우아하지 않는 비정상 종료를 보고...랜뽑을 듣고 생각났던 것이 워크3와 스타크래프트의 디스(Disconnected)가 생각이 났습니다. 연결이 불안정한 유저가 누적 60초 동안 응답이 없으면 강퇴되는 시스템인데, 해당 방법이 비정상적인 종료에 대응에 대한 것이 맞는지 궁금해져서 질문드립니다.
-
해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
시퀄라이즈 실습하기 질문드립니다.
실습 중에 댓글 작성하려고 하는데 오류가 발생해서 오류 로그를 보다가 sqlMessage 로 "Unknown column 'commenter' in 'field list'", 라는 문구를 봤습니다. 따로 commenter 라는 필드를 만드신건 못본거같은데 제가 강의를 흘려 들은건지 잘 모르겠습니다. 근데 이상한건, 맨 처음에 실행하고 댓글을 작성할땐 댓글이 작성이 되고, MySQL 에 들어가서 comment 테이블을 확인해보면 댓글이 들어가긴 했습니다.근데 두번째 댓글 작성시도부터 오류가 발생했습니다.
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
<7-5. 시퀄라이즈 사용하기>수업 질문 드립니다.
안녕하세요. 수업 중 막히는 것이 있어서 질문 글 올립니다.수업을 다 따라가고 연결테스트를 하려고 했는데,이렇게 에러가 생겼습니다.분명히 config폴더가 있고 그안에 config.json 파일이 존재하는데 없다고 하길래, 일단 npx sequelize init 을 했더니 이번에는 config 파일이 이미 존재한다는 소리를 하길래 --force 를 하긴했습니다.그런 다음에 다시 실행하니까,이렇게 오류메시지가 생겼어요.강의에는 models 폴더에 user라는 파일을 만들라는 건 듣도보도 못했는데, 뭐가 잘못된건지 잘 모르겠습니다.
-
미해결Slack 클론 코딩[실시간 채팅 with React]
focus 시에만 화면 업데이트 되는 이유 + 해결방법
웹소켓 커넥션은 유지되어 데이터까지 들어오지만 view update는 브라우저 focus되어야만 발생하는걸 보여주셨는데요 원인과 대중적인 해결방법이 있는지 궁금합니다(사파적 방식x, 대중적인 정파적 방식o)
-
미해결Slack 클론 코딩[실시간 채팅 with React]
useEffect 개수 관리
useEffect가 잘못짜면 디버깅이 골치아파서 관리에 신경을 쓰는데요. 제로초님의 useEffect 사용패턴이 궁금합니다 deps가 같은 것 끼리는 전부 묶어둔다deps가 같아도 로직 범주가 다르면 분리한다 저는 보통 2번을 선호하는데 useEffect 많아져서 드러워집니다. 그렇다고 1번은 더 머리가 아픈데,, 제로초님의 기준이나 이 문제에 대한 나름의 best practice가 있으신지 궁금합니다
-
미해결Slack 클론 코딩[실시간 채팅 with React]
라이브러리 서치 방법
강의에서 말씀주시는 것 처럼 가급적 라이브러리를 쓰고 싶은데요. 제가 경력이 짧아서인지 라이브러리 서치에 애를 먹습니다 "가장 대중 픽" 찾는다고 할 때 어떤 방법으로 접근하시는지 궁금합니다제 생각엔 다운로드 수..는 순위가 아닌 절대량이라 모호하고 이 기능은 요즘 이게 좋더라하는 얘기를 나누는 커뮤니티가 따로 있으려나요? npm이나 구글링해서 나오는 무수한 라이브러리들 다 비교하는건 거시기한 상황입니다
-
미해결Slack 클론 코딩[실시간 채팅 with React]
함수 정의 패턴
react 개발하다보면 대부분의 파일에서 export default 하나만을 하게 되는데요. 아래 2가지 패턴 중 2번을 주로 사용하시는 것 같아서 이유가 있으신지 궁금합니다export default function ABC()const ABC = () => {}export default ABC; 저는 1번을 강하게 선호하고 왜 굳이 하나의 함수에 대한 정의를 둘로 나눠 거리를 벌리는지 이해가 안 가는데요, 코딩 고수(?)들이 주로 2번 패턴을 사용하셔서 이유가 궁금합니다
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
수업과 관련해서 읽어볼 만한 책 있나요?
내용은 없음
-
해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
크롬에서 user id를 인풋에 입력하고 등록하면 404 에러처리 페이지가 뜹니다.
제로초님 깃헙 소스코드 복사해서 실행한 파일로 크롬에서 실행했는데, input 폼에 id 넣고 등록을 누르면 404 에러 페이지가 뜹니다.사파리 브라우저는 문제 없이 돌아가고 크롬브라우저에서만 이렇게 됩니다. 어떤 문제인가요?에러 메세지도 안떠서 당황스러운데 이런건 구글링 해봐도 잘 안찾아지는데 앞으로 이런 문제는 어떻게 검색해야 찾을 수 있을까요 ?
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
구매 결제관련 질문입니다 !
강사님 최근에 node.js교과서 강의를 구입하여 듣게되었습니다 !강의들이 다 유튜브에 연결이 되는데 이미 유튜브 재생목록에 다 무료로 풀려있는 강의들인가요 ?! ㅠ
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
다수의 supertest 가 실행될 때 force:true로 인한 DB 초기화 문제
supertest 를 통해서 다른 라우터도 테스트 코드를 생성하려고 했는데요각각의 supertest 파일에서 sequelize.sync({force:true})가 병렬로 실행되니까 전체적인 테스트가 끝나지 않았는데 위 코드로 인해 DB가 초기화 되어버려 테스트를 실패하는 케이스가 발생했습니다.이게 항상 발생하는 것도 아니고 테스트 수행 시간이 달라짐에 따라 결과가 매번 다르더라구요.그래서 이 부분을 어떻게 해결해야하는지 찾아보려고 했으나 검색 키워드를 잘몰라서 도움이 될만한 정보를 찾지 못했습니다.혹시 이런 부분은 어떻게 해야하나요? [제로초 강좌 질문 필독 사항입니다]질문에는 여러분에게 도움이 되는 질문과 도움이 되지 않는 질문이 있습니다.도움이 되는 질문을 하는 방법을 알려드립니다.https://www.youtube.com/watch?v=PUKOWrOuC0c0. 숫자 0부터 시작한 이유는 1보다 더 중요한 것이기 때문입니다. 에러가 났을 때 해결을 하는 게 중요한 게 아닙니다. 왜 여러분은 해결을 못 하고 저는 해결을 하는지, 어디서 힌트를 얻은 것이고 어떻게 해결한 건지 그걸 알아가셔야 합니다. 그렇지 못한 질문은 무의미한 질문입니다.1. 에러 메시지를 올리기 전에 반드시 스스로 번역을 해야 합니다. 번역기 요즘 잘 되어 있습니다. 에러 메시지가 에러 해결 단서의 90%를 차지합니다. 한글로 번역만 해도 대부분 풀립니다. 그냥 에러메시지를 올리고(심지어 안 올리는 분도 있습니다. 저는 독심술사가 아닙니다) 해결해달라고 하시면 아무런 도움이 안 됩니다.2. 에러 메시지를 잘라서 올리지 않아야 합니다. 입문자일수록 에러메시지에서 어떤 부분이 가장 중요한 부분인지 모르실 겁니다. 그러니 통째로 올리셔야 합니다.3. 코드도 같이 올려주세요. 다만 코드 전체를 다 올리거나, 깃헙 주소만 띡 던지지는 마세요. 여러분이 "가장" 의심스럽다고 생각하는 코드를 올려주세요.4. 이 강좌를 바탕으로 여러분이 응용을 해보다가 막히는 부분, 여러 개의 선택지 중에서 조언이 필요한 부분, 제 경험이 궁금한 부분에 대한 질문은 대환영입니다. 다만 여러분의 회사 일은 질문하지 마세요.5. 강좌 하나 끝날 때마다 남의 질문들을 읽어보세요. 여러분이 곧 만나게 될 에러들입니다.6. 위에 적은 내용을 명심하지 않으시면 백날 강좌를 봐도(제 강좌가 아니더라도) 실력이 늘지 않고 그냥 코딩쇼 관람 및 한컴타자연습을 한 셈이 될 겁니다.
-
미해결Slack 클론 코딩[실시간 채팅 with React]
npm run dev 에러
npm run dev시 새로운 에러가 발생하여 재질문 드립니다.http://localhost:3090/Login 연결시, 크롬에서 Failed to compile. 가 발생하였습니다.Module not found: Can't resolve '@utils/fetcher' in '/Users/kanghyun/Desktop/study/react/zerocho/sleact/setting/front/layouts' layouts/workspace.tsx터미널 메세지입니다.ERROR in ./pages/Login/index.tsx 17:0-39Module not found: Error: Can't resolve '@hooks/useInput' in '/Users/kanghyun/Desktop/study/react/zerocho/sleact/setting/front/pages/Login'@ ./layouts/App.tsx 7:9-31@ ./client.tsx 9:0-32 12:95-98ERROR in ./pages/Login/index.tsx 19:0-37Module not found: Error: Can't resolve '@utils/fetcher' in '/Users/kanghyun/Desktop/study/react/zerocho/sleact/setting/front/pages/Login'@ ./layouts/App.tsx 7:9-31@ ./client.tsx 9:0-32 12:95-98ERROR in ./pages/SignUp/index.tsx 17:0-39Module not found: Error: Can't resolve '@hooks/useInput' in '/Users/kanghyun/Desktop/study/react/zerocho/sleact/setting/front/pages/SignUp'@ ./layouts/App.tsx 11:9-32@ ./client.tsx 9:0-32 12:95-98ERROR in ./pages/SignUp/index.tsx 23:0-37Module not found: Error: Can't resolve '@utils/fetcher' in '/Users/kanghyun/Desktop/study/react/zerocho/sleact/setting/front/pages/SignUp'@ ./layouts/App.tsx 11:9-32@ ./client.tsx 9:0-32 12:95-98 ㅡtsconfig.json 파일입니다"paths": { "@hooks/*": ["hooks/*"], "@components/*": ["components/*"], "@layouts/*": ["layouts/*"], "@pages/*": ["pages/*"], "@utils/*": ["utils/*"], "@typings/*": ["typings/*"] }ㅡwebpack.config.ts 파일입니다resolve: { extensions: ['.js', '.jsx', '.front', '.tsx', '.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'), '@typings': path.resolve(__dirname, 'typings'), // 경로 폴더들 }, },ㅡ현재 터미널 경로입니다/Desktop/study/react/zerocho/sleact/setting/frontts 폴더에서 설정 후, front 라는 폴더명으로 바꾸어서 진행중입니다. 감사합니다
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
서버가 끊어버리는것에 대한 질문
11:00 에 클라가 도배를 하면 서버에서 끊어버린다는 내용이 있어서 질문 드립니다. 서버에서 먼저 끊으면 안된다고 하셨는데,도배나 어떤 악질 유저 같은 경우에는 TIME_WAIT 남더라도 끊어버리는것이 맞나요?
-
미해결Slack 클론 코딩[실시간 채팅 with React]
npx webpack 후 에러
강의를 클론 받은 후, /sleact/setting/ts 경로에서 npm i 후 npx webpack을 입력하면 아래와 같이 에러가 나옵니다.다른 컴퓨터로 했을때는 작동 되지만, 제가 사용중인 컴퓨터에서는 작동되지 않습니다.npm i 입력 후 터미널 메세지ㅡup to date, audited 643 packages in 4s74 packages are looking for funding run npm fund for details26 vulnerabilities (3 low, 8 moderate, 12 high, 3 critical)To address issues that do not require attention, run: npm audit fixTo address all issues (including breaking changes), run: npm audit fix --forceRun npm audit for details. npx webpack 명령후 입력후 터미널 메세지[webpack-cli] Failed to load '/Users/kanghyun/Desktop/study/React/zerocho/sleact/setting/ts/webpack.config.ts' config[webpack-cli] SyntaxError: The requested module 'webpack' does not provide an export named 'Configuration' at ModuleJobSync.runSync (node:internal/modules/esm/module_job:387:37) at ModuleLoader.importSyncForRequire (node:internal/modules/esm/loader:427:47) at loadESMFromCJS (node:internal/modules/cjs/loader:1565:24) at Module._compile (node:internal/modules/cjs/loader:1716:5) at Object.loadTS [as .ts] (node:internal/modules/cjs/loader:1826:10) at Module.load (node:internal/modules/cjs/loader:1469:32) at Function._load (node:internal/modules/cjs/loader:1286:12) at TracingChannel.traceSync (node:diagnostics_channel:322:14) at wrapModuleLoad (node:internal/modules/cjs/loader:235:24) at Module.require (node:internal/modules/cjs/loader:1491:12)