묻고 답해요
156만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결[개정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. 위에 적은 내용을 명심하지 않으시면 백날 강좌를 봐도(제 강좌가 아니더라도) 실력이 늘지 않고 그냥 코딩쇼 관람 및 한컴타자연습을 한 셈이 될 겁니다.
-
해결됨비전공자를 위한 진짜 입문 올인원 개발 부트캠프
강의제공자의 답변을 원합니다 AI 답변만 있고 더이상 직접 답변을 안해주시네요?
AI 답변이 어느정도 편리할 수 있단 건 인정하지만, 질문 답변도 강의서비스에 포함된 것인데 어느 순간부터 강의제공자님의 직접답변은 달리지 않고 AI 답변만 달리네요. 그것만으로 전혀 충분하지 않은데 말이죠그리고 AI 답변은 기존 데이터가 없으면 답변을 못해줍니다. 강의제공자로부터 피드백을 받을 수 있을 것을 기대하고 강의를 수강하는데 이렇게 질문답변 조차 제대로 해결이 되지 않고 있는 것은 문제라고 봅니다.몇년 동안 강의를 걸어놓으 실 거면, 그리고 여러 API를 사용하실 거면 적어도 일년에 한번은 UI나 기능에 변화나 업데이트 가 있는지 확인하고 강의에 반영해주셔야 할 것 같은데 아직도 2022년 버전을 그대로 강의에 걸어두셔서 현재 UI와 완전달라 강의 진행이 제대로 안되고 있습니다.이게 정말 제대로 되고 있는게 맞나요? 무료 강의도 아니고 돈내고 듣는 강의에서 기본적인 내용 업데이트 및 강의에 포함된 질문 답변조차 제대로 진행 되지 않는다는 건 매우 실망 스럽습니다.강의 제공자님의 빠른 직접 답변과 피드백 부탁드립니다.
-
미해결이미지 관리 풀스택(feat. Node.js, React, MongoDB, AWS)
강의에 사용된 코드 다운 받는 사이트 주소 있나요?
강의에 사용된 코드 다운 받는 사이트 주소 있나요?
-
미해결비전공자를 위한 진짜 입문 올인원 개발 부트캠프
Postman UI가 또 바뀌어서 Mockserver 를 찾을 수가 없습니다
제목 그대로 입니다. 가장 최근에 업데이트 해주신게 벌써 2년전인데, 강의를 계속 걸어놓으시려면 적어도 매년 단위로UI 상태에 맞게 해당 부분만이라도 강의를 업데이트 해주셔야 할 것 같습니다.Mock server 부분 도저히 찾지못해 시간만 보내고 진척이 없습니다. 대체 어떻게 해야 하나요?
-
미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
로그 관리에 대해 질문 있습니다.
안녕하세요. 최근에 프로젝트를 완성해서 배포까지 성공리에 마쳤는데요. 이제 운영을 해야하는데 몇가지 궁금한 점이 생겨서 질문 남기게 되었습니다.운영을 하다보면 배포하기 전 진행한 테스트 외에도 예기치 못한 오류가 생길 수 있기때문에 서버에서 로깅하는게 굉장히 중요하다고 생각이 드는데요. 실무에서는 로깅을 따로 어떻게 하는지에 대해 궁금함이 생겼습니다.현재 서비스의 중요한 비즈니스 로직에는 Logger를 사용해서 호출 될 때 마다, 시간과 함께 넘어가는 데이터를 같이 로깅하게끔 개발 해놨습니다. 약간 문제라고 생각되는 것은 에러가 발생 할 때, 호스팅하고있는 온프레미스 서버에 직접 접속해서 도커 컨테이너 로그를 일일이 확인해야 하는 번거로움이 있는 점입니다. 실무에서 모든 개발자들이 이렇게 확인하지 않을 것이라고 생각하는데 보통 실무에서는 어떻게 로그를 관리하시나요? 조언 부탁드립니다!
-
미해결코로나맵 개발자와 함께하는 지도서비스 만들기 2
키워드 검색 데이터 받아오기 강의중 문제 발생
카카오 api 받아서 지도 잘 작동하고 검색창도 떳는데키워드 검색 데이터 받아오기 강의 들으면서 잘 따라갔는데 갑자기 안됩니다 upload.js:1 Uncaught ReferenceError: require is not definedat upload.js:1:20 f12누르니까 이렇게 나옵니다 ㅠㅠ 추가적으로 vs코드에서는파일이 CommonJS 모듈입니다. ES 모듈로 변환될 수 있습니다.ts(80001) 이런 문구가 나오네요 +그래서 upload 파일은 무시하고 지도위에 저장한 데이터 표시하기 강의까지 들었는데 이번엔 main.js:1 Uncaught ReferenceError: require is not defined at main.js:1:20 이렇게 뜨네요 require 함수가 지금까지 잘 되다가 수업이 진행될수록 왜 문제가 될까요 ㅠㅠ
-
해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
CORS 에러 질문 있습니다.
안녕하세요. 프로젝트를 배포하는 과정에서 왜인지 모를 CORS 에러가 계속 생겨서 질문 드립니다.CORS 문제를 해결하기 위해서는 응답 헤더에 Acess-Control-Allow-Origin이 필요한데, nestjs와 같은 was에서 enableCors를 설정해주거나, Nginx의 server 블럭에 add_header를 통해서 헤더를 추가 해 줄 수 있는 것으로 알고 있습니다.웹 서버가 was보다 앞에 있으니까 웹 서버에서 설정해줘야겠다는 생각에 nginx.conf에 allowed_origin은 동적으로 Access-Control-Allow-Origin 헤더의 값을 받기 위해서 설정해뒀습니다.이렇게 작성하고 reload를 해줬는데, 왜인지 응답헤더에 추가한 헤더가 생기지 않습니다...테스트 서버에 위와 같은 설정으로 올렸을 때는 잘 해결됐는데 라이브에 올리니까 이런 문제가 발생하는데 어디를 살펴봐야 할 지 모르겠습니다... access to XMLHttpRequest at '도메인 주소' from origin '서버 ip' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.이런식으로 404에러가 나옵니다.
-
해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
배포 환경 DB 연결 질문 있습니다.
안녕하세요. 배포를 하고 있는 중 에러를 만났는데 도저히 이해가 가지 않아서 여쭤봅니다.[Nest] 1 - 05/23/2024, 2:56:25 PM ERROR [TypeOrmModule] Unable to connect to the database. Retrying (1)... Error: Access denied for user '유저'@'호스트 서버 IP' (using password: YES)제가 지금 만난 에러인데요. 현재 배포하고 있는 서버와 DB로 켜놓은 서버가 각각 다른 서버입니다.데이터베이스 사용자에 당연히 프로젝트에서 연결 해둔 유저를 추가해두었고, 배포하고 있는 서버의 접근도 허용해뒀습니다. 또한, GRANT ALL PRIVILEGES ON . TO '유저'@'호스트 서버 IP' IDENTIFIED BY '비밀번호'; flush privileges;이렇게 모든 권한도 주었습니다. 그런데 계속 위의 에러가 발생하는데 이유를 도통 모르겠습니다. 어떻게 접근해야 할까요?
-
미해결[개정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 인지 궁금합니다.
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 영화 사이트 만들기
movieTitle
movieTitle 값이 안나와요ㅜㅜㅜ
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 영화 사이트 만들기
npm run dev 연결이 안됩니다ㅜㅜ
PS C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master>npm run dev> react-boiler-plate@1.0.0 dev> concurrently "npm run backend" "npm run start --prefix client"[0] [0] > react-boiler-plate@1.0.0 backend[0] > nodemon server/index.js[0] [1] [1] > client@0.1.0 start[1] > react-scripts start[1] [0] [nodemon] 1.19.4[0] [nodemon] to restart at any time, enter rs[0] [nodemon] watching dir(s): .[0] [nodemon] watching extensions: js,mjs,json[0] [nodemon] starting node server/index.js[0] node:internal/modules/cjs/loader:1147[0] throw err;[0] ^[0][0] Error: Cannot find module 'bcrypt'[0] Require stack:[0] - C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\server\models\User.js[0] - C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\server\routes\users.js[0] - C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\server\index.js[0] at Module._resolveFilename (node:internal/modules/cjs/loader:1144:15)[0] at Module._load (node:internal/modules/cjs/loader:985:27) [0] at Module.require (node:internal/modules/cjs/loader:1235:19) [0] at require (node:internal/modules/helpers:176:18)[0] at Object.<anonymous> (C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\server\models\User.js:2:16)[0] at Module._compile (node:internal/modules/cjs/loader:1376:14) [0] at Module._extensions..js (node:internal/modules/cjs/loader:1435:10)[0] at Module.load (node:internal/modules/cjs/loader:1207:32) [0] at Module._load (node:internal/modules/cjs/loader:1023:12) [0] at Module.require (node:internal/modules/cjs/loader:1235:19) [0] at require (node:internal/modules/helpers:176:18)[0] at Object.<anonymous> (C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\server\routes\users.js:3:18)[0] at Module._compile (node:internal/modules/cjs/loader:1376:14) [0] at Module._extensions..js (node:internal/modules/cjs/loader:1435:10)[0] at Module.load (node:internal/modules/cjs/loader:1207:32) [0] at Module._load (node:internal/modules/cjs/loader:1023:12) { [0] code: 'MODULE_NOT_FOUND',[0] requireStack: [[0] 'C:\\Users\\Samsung\\Desktop\\project\\boilerplate-mern-stack-master\\server\\models\\User.js',[0] 'C:\\Users\\Samsung\\Desktop\\project\\boilerplate-mern-stack-master\\server\\routes\\users.js',[0] 'C:\\Users\\Samsung\\Desktop\\project\\boilerplate-mern-stack-master\\server\\index.js'[0] ][0] }[0][0] Node.js v20.11.0[0] [nodemon] app crashed - waiting for file changes before starting...[1] [HPM] Proxy created: / -> http://localhost:5000[1] i 「wds」: Project is running at http://192.168.11.5/[1] i 「wds」: webpack output is served from[1] i 「wds」: Content not from webpack is served from C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\client\public[1] i 「wds」: 404s will fallback to /[1] Starting the development server...[1][1] Error: error:0308010C:digital envelope routines::unsupported[1] at new Hash (node:internal/crypto/hash:68:19)[1] at Object.createHash (node:crypto:138:10)[1] at module.exports (C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\client\node_modules\webpack\lib\util\createHash.js:135:53)[1] at NormalModule._initBuildHash (C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\client\node_modules\webpack\lib\NormalModule.js:417:16)[1] at handleParseError (C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\client\node_modules\webpack\lib\NormalModule.js:471:10)[1] at C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\client\node_modules\webpack\lib\NormalModule.js:503:5[1] at C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\client\node_modules\webpack\lib\NormalModule.js:358:12[1] at C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\client\node_modules\loader-runner\lib\LoaderRunner.js:373:3 [1] at iterateNormalLoaders (C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\client\node_modules\loader-runner\lib\LoaderRunner.js:214:10)[1] at iterateNormalLoaders (C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\client\node_modules\loader-runner\lib\LoaderRunner.js:221:10)[1] C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\client\node_modules\react-scripts\scripts\start.js:19[1] throw err;[1] ^[1][1] Error: error:0308010C:digital envelope routines::unsupported [1] at new Hash (node:internal/crypto/hash:68:19)[1] at Object.createHash (node:crypto:138:10)[1] at module.exports (C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\client\node_modules\webpack\lib\util\createHash.js:135:53)[1] at NormalModule._initBuildHash (C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\client\node_modules\webpack\lib\NormalModule.js:417:16)[1] at C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\client\node_modules\webpack\lib\NormalModule.js:452:10[1] at C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\client\node_modules\webpack\lib\NormalModule.js:323:13[1] at C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\client\node_modules\loader-runner\lib\LoaderRunner.js:367:11 [1] at C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\client\node_modules\loader-runner\lib\LoaderRunner.js:233:18 [1] at context.callback (C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\client\node_modules\loader-runner\lib\LoaderRunner.js:111:13)[1] at C:\Users\Samsung\Desktop\project\boilerplate-mern-stack-master\client\node_modules\babel-loader\lib\index.js:59:103 {[1] opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ],[1] library: 'digital envelope routines',[1] reason: 'unsupported',[1] code: 'ERR_OSSL_EVP_UNSUPPORTED'[1] }[1][1] Node.js v20.11.0[1] npm run start --prefix client exited with code 1
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 영화 사이트 만들기
npm run dev 오류
npm run dev 하면 > react-boiler-plate@1.0.0 dev> concurrently "npm run backend" "npm run start --prefix client"sh: concurrently: command not found다음과 같은 오류가 발생합니다. npm install server과, client 모두에서 진행했고gpt가 알려주는 npm install -g concurrently도 진행했고npm update 후 다시 실행해보아도 해결되지 않고 있습니다. 도와주세요 ..!
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
ssh xxxxx로 우분투에 들어가려니까 port 22: Connection timed out
nginx 부분을 따라하다가실수로 서버에서 나갔다가 다시 들어가려니까ssh: connect to host zzimzzim-front port 22: Connection timed out위와같은 에러가나면서 갑자기 들어가지지 않습니다.검색했는데도 해결되지 않아서 답답해다가이럴땐 어떤걸 참고하면 좋을지 조언 주시면 감사하겠습니다. ㅠ
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
sudo certbot --nginx 에러
ubuntu@ip-172-31-37-191:~/react-nodebird/prepare/front$ sudo certbot --nginx Saving debug log to /var/log/letsencrypt/letsencrypt.log Which names would you like to activate HTTPS for? We recommend selecting either all domains, or all domains in a VirtualHost/server block. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1: zzimzzim.com - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Select the appropriate numbers separated by commas and/or spaces, or leave input blank to select all options shown (Enter 'c' to cancel): Requesting a certificate for zzimzzim.com Certbot failed to authenticate some domains (authenticator: nginx). The Certificate Authority reported these problems: Domain: zzimzzim.com Type: connection Detail: 3.37.101.58: Fetching http://zzimzzim.com/.well-known/acme-challenge/SNUl0WTK7OKWJ-oYyHTrIFuh67ww_P11CUJXw2zWRZk: Timeout during connect (likely firewall problem) Hint: The Certificate Authority failed to verify the temporary nginx configuration changes made by Certbot. Ensure the listed domains point to this nginx server and that it is accessible from the internet. Some challenges have failed. Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.위와같은 에러가 발생합니다.다른 질문들을 보고 제로초님https://www.zerocho.com/category/NodeJS/post/5ef450a5701d8a001f84baeb 따라해보았는데 해결되지 않아서 여쭤봅니다.
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
Minified React error 콘솔에러 (hydrate)
안녕하세요 선생님카카오톡 공유하기 까지 듣고 화면을 테스트해보고 있는데Minified React error 이 에러가 떠서 질문드립니다. 메인화면, 상세보기에서 게시글이 있을때 나옵니다.Uncaught Error: Minified React error #418; visit https://reactjs.org/docs/error-decoder.html?invariant=418 for the full message or use the non-minified dev environment for full errors and additional helpful warnings. at lg (framework-ecc4130bc7a58a64.js:9:46457) at i (framework-ecc4130bc7a58a64.js:9:121052) at oO (framework-ecc4130bc7a58a64.js:9:99019) at framework-ecc4130bc7a58a64.js:9:98886 at oF (framework-ecc4130bc7a58a64.js:9:98893) at oS (framework-ecc4130bc7a58a64.js:9:93932) at x (framework-ecc4130bc7a58a64.js:33:1364) at MessagePort.T (framework-ecc4130bc7a58a64.js:33:1894)검색해봤더니 hydrate 쪽 이슈더라구요.혼자서 풀어보다가 잘 풀리지 않아서 여쭤봅니다.혹시 제로초님은 저런 에러가 나지 않으시는지난다면 어느 로직을 확인해야할지 조언 부탁드립니다./pages/post/[id].jsimport axios from 'axios'; import Head from 'next/head'; import { useRouter } from 'next/router'; import { useSelector } from 'react-redux'; import AppLayout from '../../components/AppLayout'; import PostCard from '../../components/PostCard'; import { loadPost } from '../../reducers/post'; import { loadMyInfo } from '../../reducers/user'; import wrapper from '../../store/configurStore'; const Post = () => { const router = useRouter(); const { id } = router.query; const { singlePost } = useSelector((state) => state.post); return ( <AppLayout> {singlePost ? ( <> <Head> <title> {singlePost?.User.nickname} 님의 글 </title> <meta name="description" content={singlePost.content} /> <meta property="og:title" content={`${singlePost.User.nickname}님의 게시글`} /> <meta property="og:description" content={singlePost.content} /> <meta property="og:image" content={ singlePost.Images[0] ? singlePost.Images[0].src : 'https://nodebird.com/favicon.ico' } /> <meta property="og:url" content={`https://nodebird.com/post/${id}`} /> </Head> <PostCard post={singlePost}>{id}번 게시글</PostCard> </> ) : ( <div>존재하지 않는 게시물입니다.</div> )} </AppLayout> ); }; export const getServerSideProps = wrapper.getServerSideProps( (store) => async ({ req, params }) => { const cookie = req ? req.headers.cookie : ''; axios.defaults.headers.Cookie = ''; // 쿠키가 브라우저에 있는경우만 넣어서 실행 // (주의, 아래 조건이 없다면 다른 사람으로 로그인 될 수도 있음) if (req && cookie) { axios.defaults.headers.Cookie = cookie; } await store.dispatch(loadMyInfo()); await store.dispatch(loadPost(params.id)); }, ); export default Post; /components/PostCard.jsimport { RetweetOutlined, HeartOutlined, HeartTwoTone, MessageOutlined, EllipsisOutlined, } from '@ant-design/icons'; import { Card, Popover, Button, Avatar, List } from 'antd'; import dayjs from 'dayjs'; import Link from 'next/link'; import PropTypes from 'prop-types'; import { useState, useCallback, useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import CommentForm from './CommentForm'; import Followbutton from './FollowButton'; import PostCardContent from './PostCardContent'; import PostImages from './PostImages'; import { removePostRequestAction, likePostRequestAction, unLikePostRequestAction, retweetRequestAction, } from '../reducers/post'; dayjs.locale('ko'); const PostCard = ({ post }) => { // const { me: {id} } = useSelector((state) => state.user); // const id = me && me.id; // const id = me?.id; // 옵셔널 체이닝 연산자 const { removePostLoading } = useSelector((state) => state.post); const dispatch = useDispatch(); const [commentFormOpend, setCommentFormOpend] = useState(false); const id = useSelector((state) => state.user.me?.id); const liked = post.Likers.find((d) => d.id === id); const onLike = useCallback(() => { if (!id) { alert('로그인이 필요합니다.'); } dispatch(likePostRequestAction(post.id)); }, [id]); const onUnLike = useCallback(() => { if (!id) { alert('로그인이 필요합니다.'); } dispatch(unLikePostRequestAction(post.id)); }, [id]); const onToggleComment = useCallback(() => { setCommentFormOpend((prev) => !prev); }, []); const onRemovePost = useCallback(() => { if (!id) { alert('로그인이 필요합니다.'); } dispatch(removePostRequestAction({ id: post.id })); }, [id]); const onRetweet = useCallback(() => { if (!id) { alert('로그인이 필요합니다.'); } dispatch(retweetRequestAction(post.id)); }, [id]); return ( <div style={{ marginTop: 10 }}> <Card cover={post.Images[0] && <PostImages images={post.Images} />} actions={[ // 배열안에 들어가는 것들은 다 key를 넣어줘야 한다. <RetweetOutlined key="retweet" onClick={onRetweet} />, liked ? ( <HeartTwoTone key="heart" twoToneColor="#eb2f96" onClick={onUnLike} /> ) : ( <HeartOutlined key="heart" onClick={onLike} /> ), <MessageOutlined key="comment" onClick={onToggleComment} />, <Popover key="more" content={ <Button.Group> {id && post.User?.id === id ? ( <> <Button type="primary" key="modify"> 수정 </Button> <Button type="danger" key="delete" onClick={onRemovePost} loading={removePostLoading} > 삭제 </Button> </> ) : ( <Button type="dashed" key="report"> 신고 </Button> )} </Button.Group> } > <EllipsisOutlined /> </Popover>, ]} extra={id && <Followbutton post={post} />} title={ post.RetweetId ? `${post.User.nickname}님이 리트윗하셨습니다.` : null } > {post.RetweetId && post.Retweet ? ( <Card cover={ post.Retweet.Images[0] && ( <PostImages images={post.Retweet.Images} /> ) } > <div style={{ float: 'right' }}> {dayjs(post.createdAt).format('YYYY.MM.DD')} </div> <Card.Meta avatar={ <Link href={`/user/${post.Retweet.User.id}`}> <Avatar>{post.Retweet.User?.nickname[0]}</Avatar> </Link> } title={post.Retweet.User?.nickname} description={<PostCardContent postData={post.Retweet.content} />} /> </Card> ) : ( <> <div style={{ float: 'right' }}> {dayjs(post.createdAt).format('YYYY.MM.DD')} </div> <Card.Meta avatar={ <Link href={`/user/${post.User.id}`}> <Avatar>{post.User?.nickname[0]}</Avatar> </Link> } title={post.User?.nickname} description={<PostCardContent postData={post.content} />} /> </> )} </Card> {commentFormOpend && ( <div> {/* 게시글의 아이디 위해서 post 넘겨줌 */} <CommentForm post={post} /> <List header={`${post.Comments.length}개의 댓글`} itemLayout="horizontal" dataSource={post.Comments} renderItem={(item) => ( <List.Item key={item.id}> <List.Item.Meta title={item.User.nickname} avatar={ <Link href={`/user/${item.User.id}`}> <Avatar>{item.User.nickname[0]}</Avatar> </Link> } description={item.content} /> </List.Item> )} /> </div> )} </div> ); }; PostCard.propTypes = { post: PropTypes.shape({ id: PropTypes.number, User: PropTypes.object, content: PropTypes.string, createdAt: PropTypes.string, Comments: PropTypes.arrayOf(PropTypes.object), Images: PropTypes.arrayOf(PropTypes.object), Likers: PropTypes.arrayOf(PropTypes.object), RetweetId: PropTypes.number, Retweet: PropTypes.objectOf(PropTypes.any), }).isRequired, }; export default PostCard; 여유되실때 한번 봐주시면 감사하겠습니다
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
카카오 공유했을 때 이전에 작성했던 글이 나오는 버그
안녕하세요 선생님보너스 강의 전까지 보고 카카오 공유하기 까지 테스트하고 있는데버그를 발견한것 같아서 어떻게 해결할지 여쭤보려 올립니다.위처럼 post/5의 게시글을 작성하고카카오톡에 공유를 하면이전에 썼던 (로컬에서 썼었던) 내용이 보여집니다.혹시 기존 데이터베이스를 리셋하거나 추가적인 작업이 필요한건지 궁금합니다.
-
해결됨비전공자를 위한 진짜 입문 올인원 개발 부트캠프
CRUD에서 CR만 배우는건가요
수정 삭제는 sqlite로 직접 만져야되나요
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
프론트서버 배포 후 EADDRINUSE에러 발생
안녕하세요 제로초님덕분에 front배포 잘 하게 되었습니다.그후 접속해서 테스트했는데, 회원가입할 때 connect_refused가 발생해 로그를 찾아보았습니다.EADDRINUSE를 발견하고 원인을 찾으려고 뒤져봤는데 해결되지 않아 여쭤봅니다. ㅠfront = 13.125.119.94 back = 13.125.252.5 아래는 설정한 내용/front/package.json"scripts": { "dev": "next dev", "build": "cross-env ANALYZE=true NODE_ENV=production next build", "start": "cross-env NODE_ENV=production next start -p 80", }, /back/packge.json"scripts": { "dev": "nodemon app", "start": "cross-env NODE_ENV=production pm2 start app.js" }, /back/app.js// node에서는 import / export 안쓰고 require / module.exports 사용 const express = require('express'); const cors = require('cors'); const session = require('express-session'); const cookieParser = require('cookie-parser'); const passport = require('passport'); const dotenv = require('dotenv'); const morgan = require('morgan'); const path = require('path'); const hpp = require('hpp'); const helmet = require('helmet'); const postRouter = require('./routes/post'); const postsRouter = require('./routes/posts'); const userRouter = require('./routes/user'); const hashtahRouter = require('./routes/hashtag'); const db = require('./models'); // sequelize에서 model 모두 등록 // express에서 그 sequelize를 등록해야 한다. const passportConfig = require('./passport'); dotenv.config(); const app = express(); db.sequelize .sync() .then(() => { console.log('db연결 성공!'); }) .catch(console.error); passportConfig(); // 운영용 빌드 if (process.env.NOD_ENV === 'production') { app.use(morgan('combined')); // 로그볼 수 있게 해주는 것 // 보안에 도움되는 패키지들 app.use(hpp()); app.use(helmet()); } else { app.use(morgan('dev')); // 로그볼 수 있게 해주는 것 } app.use( cors({ origin: ['http://localhost:3000', 'nodebird.com', 'http://13.125.119.94'], credentials: true, }) ); app.use('/', express.static(path.join(__dirname, 'uploads'))); app.use(express.urlencoded({ extended: true })); app.use(cookieParser(process.env.COOKIE_SECRET)); app.use( session({ saveUninitialized: false, resave: false, secret: process.env.COOKIE_SECRET, }) ); app.use(passport.initialize()); app.use(passport.session()); app.use('/post', postRouter); app.use('/posts', postsRouter); app.use('/user', userRouter); app.use('/hashtag', hashtahRouter); app.listen(80, () => { console.log('서버 실행 중'); }); 프론트 실행화면백엔드 실행 화면 아래는 에러 내용입니다./front 에러AxiosError: connect ECONNREFUSED 13.125.252.5:443 0|npm | at AxiosError.from (file:///home/ubuntu/react-nodebird/prepare/front/node_modules/axios/lib/core/AxiosError.js:89:14) 0|npm | at RedirectableRequest.handleRequestError (file:///home/ubuntu/react-nodebird/prepare/front/node_modules/axios/lib/adapters/http.js:610:25) 0|npm | at RedirectableRequest.emit (node:events:517:28) 0|npm | at eventHandlers.<computed> (/home/ubuntu/react-nodebird/prepare/front/node_modules/follow-redirects/index.js:38:24) 0|npm | at ClientRequest.emit (node:events:517:28) 0|npm | at TLSSocket.socketErrorListener (node:_http_client:501:9) 0|npm | at TLSSocket.emit (node:events:517:28) 0|npm | at emitErrorNT (node:internal/streams/destroy:151:8) 0|npm | at emitErrorCloseNT (node:internal/streams/destroy:116:3) 0|npm | at process.processTicksAndRejections (node:internal/process/task_queues:82:21) 0|npm | at Axios.request (file:///home/ubuntu/react-nodebird/prepare/front/node_modules/axios/lib/core/Axios.js:45:41) 0|npm | at process.processTicksAndRejections (node:internal/process/task_queues:95:5) 0|npm | at async y (/home/ubuntu/react-nodebird/prepare/front/.next/server/chunks/414.js:1:1838) { 0|npm | port: 443, 0|npm | address: '13.125.252.5', 0|npm | syscall: 'connect', 0|npm | code: 'ECONNREFUSED', 0|npm | errno: -111, 0|npm | config: { 0|npm | transitional: { 0|npm | silentJSONParsing: true, 0|npm | forcedJSONParsing: true, 0|npm | clarifyTimeoutError: false 0|npm | }, cause: Error: connect ECONNREFUSED 13.125.252.5:443 0|npm | at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1555:16) { 0|npm | errno: -111, 0|npm | code: 'ECONNREFUSED', 0|npm | syscall: 'connect', 0|npm | address: '13.125.252.5', 0|npm | port: 443 0|npm | } back 에러 | Warning: connect.session() MemoryStore is not 0|app | designed for a production environment, as it will leak 0|app | memory, and will not scale past a single process. 0|app | Error: listen EADDRINUSE: address already in use / 0|app | at Server.setupListenHandle [as _listen2] (node:net:1800:21) 0|app | at listenInCluster (node:net:1865:12) 0|app | at Server.listen (node:net:1964:5) 0|app | at Function.listen (/home/ubuntu/react-nodebird/prepare/back/node_modules/express/lib/application.js:635:24) 0|app | at Object.<anonymous> (/home/ubuntu/react-nodebird/prepare/back/app.js:75:5) 0|app | at Module._compile (node:internal/modules/cjs/loader:1364:14) 0|app | at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) 0|app | at Module.load (node:internal/modules/cjs/loader:1203:32) 0|app | at Module._load (node:internal/modules/cjs/loader:1019:12) 0|app | at Object.<anonymous> (/home/ubuntu/react-nodebird/prepare/back/node_modules/pm2/lib/ProcessContainerFork.js:33:23) { 0|app | code: 'EADDRINUSE', 0|app | errno: -98, 0|app | syscall: 'listen', 0|app | address: '/', 0|app | port: -1 0|app | } front monit back monit 비슷한 질문들이 올라와 있어서 (sudo) npx pm2 kill 해보거나 다른 검색들을 해봤는데 원인을 모르겠더라구요어떤 부분을 수정해야할지 어떤부분을 확인해봐야할지 봐주시면 정말 감사하겠습니다.
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
npm run build 에러
안녕하세요 제로초님프론트 서버를 npm run build 하니까아래와 같은 에러가 나오는데검색해서 찾아봐도 잘 모르겠더라구요.혹시 어느 부분을 확인해보고 어떤 부분을 수정해야할지 조언해주실 수 있을까요?빌드하는것만 몇일째라 ㅠ답답합니다. Collecting page data ./home/ubuntu/react-nodebird/prepare/front/node_modules/rc-util/es/omit.js:1 import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2"; ^^^^^^ SyntaxError: Cannot use import statement outside a module at internalCompileFunction (node:internal/vm:76:18) at wrapSafe (node:internal/modules/cjs/loader:1283:20) at Module._compile (node:internal/modules/cjs/loader:1328:27) at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) at Module.load (node:internal/modules/cjs/loader:1203:32) at Module._load (node:internal/modules/cjs/loader:1019:12) at Module.require (node:internal/modules/cjs/loader:1231:19) at mod.require (/home/ubuntu/react-nodebird/prepare/front/node_modules/next/dist/server/require-hook.js:65:28) at require (node:internal/modules/helpers:177:18) at 5514 (/home/ubuntu/react-nodebird/prepare/front/.next/server/pages/signup.js:7:10601) /home/ubuntu/react-nodebird/prepare/front/node_modules/rc-util/es/omit.js:1 import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2"; ^^^^^^ SyntaxError: Cannot use import statement outside a module at internalCompileFunction (node:internal/vm:76:18) at wrapSafe (node:internal/modules/cjs/loader:1283:20) at Module._compile (node:internal/modules/cjs/loader:1328:27) at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) at Module.load (node:internal/modules/cjs/loader:1203:32) at Module._load (node:internal/modules/cjs/loader:1019:12) at Module.require (node:internal/modules/cjs/loader:1231:19) at mod.require (/home/ubuntu/react-nodebird/prepare/front/node_modules/next/dist/server/require-hook.js:65:28) at require (node:internal/modules/helpers:177:18) at 5514 (/home/ubuntu/react-nodebird/prepare/front/.next/server/pages/signup.js:7:10601) > Build error occurred Error: Failed to collect page data for /signup at /home/ubuntu/react-nodebird/prepare/front/node_modules/next/dist/build/utils.js:1268:15 at process.processTicksAndRejections (node:internal/process/task_queues:95:5) { type: 'Error' } /pages.index.jsimport axios from 'axios'; import { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import AppLayout from '../components/AppLayout'; import PostCard from '../components/PostCard'; import PostForm from '../components/PostForm'; import { loadPosts, loadPostsError } from '../reducers/post'; import { loadMyInfo } from '../reducers/user'; import wrapper from '../store/configurStore'; // 프론트, 브라우저 같이 실행 const Home = () => { const { me } = useSelector((state) => state.user); const { mainPosts, hasMorePosts, loadPostsLoading, retweetError } = useSelector((state) => state.post); const dispatch = useDispatch(); useEffect(() => { if (retweetError) { alert(retweetError); } }, [retweetError]); useEffect(() => { const onScroll = () => { if ( window.scrollY + document.documentElement.clientHeight > document.documentElement.scrollHeight - 300 ) { if (hasMorePosts && !loadPostsLoading) { const lastId = mainPosts[mainPosts.length - 1]?.id; dispatch(loadPosts({ lastId, limit: 10 })); } } }; window.addEventListener('scroll', onScroll); return () => { window.removeEventListener('scroll', onScroll); }; }, [hasMorePosts, loadPostsLoading, mainPosts.length]); return ( <AppLayout> {me && <PostForm />} {mainPosts && mainPosts[0] ? mainPosts.map((post) => <PostCard key={post.id} post={post} />) : null} </AppLayout> ); }; export const getServerSideProps = wrapper.getServerSideProps( (store) => async ({ req }) => { console.log('getServerSideProps start--------------------------'); console.log(req.headers); const cookie = req ? req.headers.cookie : ''; axios.defaults.headers.Cookie = ''; // 쿠키가 브라우저에 있는경우만 넣어서 실행 // (주의, 아래 조건이 없다면 다른 사람으로 로그인 될 수도 있음) if (req && cookie) { axios.defaults.headers.Cookie = cookie; } await store.dispatch(loadPosts()); await store.dispatch(loadMyInfo()); }, ); export default Home;
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
front 서버 npm run build 중에 발생한 에러들
안녕하세요 제로초님front 서버를 빌드하던중에 빌드가 된줄알고 pm2 monit으로 확인해보니 Could not find a production build in the '.next' directory 이런 에러가 떠있었습니다. 확인해봤더니 아래와 같은 에러 들이 엄청 나오더라구요.warning도 아니고 다 error들이라 검색해보고 .eslintrc를 고쳐봤는데도 잘 안되서 여쭤봅니다 ㅠ 다른 분들은 이런 에러 없이 잘 되는거같은데 전 왜이런지 도와주시면 감사하겠습니다 ㅠ ㅠ npm run build 했을때 나타나는 에러중 일부/components/LoginForm.js 11:1 Error: Unexpected tab character. no-tabs 14:1 Error: Unexpected tab character. no-tabs 17:19 Error: Function component is not a function declaration react/function-component-definition 18:1 Error: Unexpected tab character. no-tabs 18:1 Error: Expected indentation of 2 spaces but found 1 tab. indent 19:1 Error: Unexpected tab character. no-tabs 19:1 Error: Expected indentation of 4 spaces but found 2 tabs. indent 20:1 Error: Unexpected tab character. no-tabs 20:1 Error: Expected indentation of 4 spaces but found 2 tabs. indent 21:1 Error: Unexpected tab character. no-tabs 21:1 Error: Expected indentation of 4 spaces but found 2 tabs. indent 22:1 Error: Unexpected tab character. no-tabs 22:1 Error: Expected indentation of 2 spaces but found 1 tab. indent 23:1 Error: Unexpected tab character. no-tabs 23:1 Error: Expected indentation of 2 spaces but found 1 tab. indent 25:1 Error: Unexpected tab character. no-tabs 25:1 Error: Expected indentation of 2 spaces but found 1 tab. indent 26:1 Error: Unexpected tab character. no-tabs 26:1 Error: Expected indentation of 4 spaces but found 2 tabs. indent 27:1 Error: Unexpected tab character. no-tabs 27:1 Error: Expected indentation of 6 spaces but found 3 tabs. indent 27:4 Warning: Unexpected alert. no-alert 28:1 Error: Unexpected tab character. no-tabs 28:1 Error: Expected indentation of 4 spaces but found 2 tabs. indent 29:1 Error: Unexpected tab character. no-tabs 29:1 Error: Expected indentation of 2 spaces but found 1 tab. indent 31:1 Error: Unexpected tab character. no-tabs 31:1 Error: Expected indentation of 2 spaces but found 1 tab. indent 32:1 Error: Unexpected tab character. no-tabs 32:1 Error: Expected indentation of 2 spaces but found 1 tab. indent 33:1 Error: Unexpected tab character. no-tabs 33:1 Error: Expected indentation of 4 spaces but found 2 tabs. indent 34:1 Error: Unexpected tab character. no-tabs 34:1 Error: Expected indentation of 2 spaces but found 1 tab. indent 36:1 Error: Unexpected tab character. no-tabs 36:1 Error: Expected indentation of 2 spaces but found 1 tab. indent 37:1 Error: Unexpected tab character. no-tabs 37:3 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 38:1 Error: Unexpected tab character. no-tabs 38:4 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 39:1 Error: Unexpected tab character. no-tabs 39:5 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 39:20 Error: Unexpected usage of singlequote. jsx-quotes 40:1 Error: Unexpected tab character. no-tabs 40:5 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 41:1 Error: Unexpected tab character. no-tabs 41:5 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 42:1 Error: Unexpected tab character. no-tabs 42:6 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent-props 42:11 Error: Unexpected usage of singlequote. jsx-quotes 43:1 Error: Unexpected tab character. no-tabs 43:6 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent-props 44:1 Error: Unexpected tab character. no-tabs 44:6 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent-props 45:1 Error: Unexpected tab character. no-tabs 45:1 Error: Expected indentation of 7 spaces but found 6 tabs. indent 46:1 Error: Unexpected tab character. no-tabs 46:1 Error: Expected indentation of 7 spaces but found 6 tabs. indent 47:1 Error: Unexpected tab character. no-tabs 48:1 Error: Unexpected tab character. no-tabs 48:6 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent-props 49:1 Error: Unexpected tab character. no-tabs 49:7 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 50:1 Error: Unexpected tab character. no-tabs 50:8 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 50:29 Error: Unexpected usage of singlequote. jsx-quotes 50:42 Error: Unexpected usage of singlequote. jsx-quotes 50:62 Error: Unexpected usage of singlequote. jsx-quotes 51:1 Error: Unexpected tab character. no-tabs 51:8 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 52:1 Error: Unexpected tab character. no-tabs 53:1 Error: Unexpected tab character. no-tabs 54:1 Error: Unexpected tab character. no-tabs 55:1 Error: Unexpected tab character. no-tabs 56:1 Error: Unexpected tab character. no-tabs 56:4 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 57:1 Error: Unexpected tab character. no-tabs 57:5 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 57:20 Error: Unexpected usage of singlequote. jsx-quotes 58:1 Error: Unexpected tab character. no-tabs 58:5 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 59:1 Error: Unexpected tab character. no-tabs 59:5 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 60:1 Error: Unexpected tab character. no-tabs 60:6 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent-props 60:11 Error: Unexpected usage of singlequote. jsx-quotes 61:1 Error: Unexpected tab character. no-tabs 61:6 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent-props 62:1 Error: Unexpected tab character. no-tabs 62:6 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent-props 63:1 Error: Unexpected tab character. no-tabs 63:1 Error: Expected indentation of 7 spaces but found 6 tabs. indent 64:1 Error: Unexpected tab character. no-tabs 64:1 Error: Expected indentation of 7 spaces but found 6 tabs. indent 65:1 Error: Unexpected tab character. no-tab .eslintrc, next.config.js 는 제로초님의 깃헙과 동일하게 했습니다..eslintrc{ "parser": "@babel/eslint-parser", "parserOptions": { "ecmaVersion": 2020, "sourceType": "module", "ecmaFeatures": { "jsx": true }, "babelOptions": { "presets": ["next/babel"] }, "requireConfigFile": false }, "env": { "browser": true, "node": true, "es6": true }, "extends": ["airbnb"], "plugins": ["import", "react-hooks", "jsx-a11y"], "rules": { "jsx-a11y/label-has-associated-control": "off", "jsx-a11y/anchor-is-valid": "off", "no-console": "off", "no-underscore-dangle": "off", "react/forbid-prop-types": "off", "react/jsx-filename-extension": "off", "react/jsx-one-expression-per-line": "off", "react/jsx-props-no-spreading": "off", "object-curly-newline": "off", "linebreak-style": "off", "no-param-reassign": "off", "max-len": "off", "react/react-in-jsx-scope": "off" } } next.config.jsconst withBundleAnalyzer = require("@next/bundle-analyzer")({ enabled: process.env.ANALYZE === "true", }); module.exports = withBundleAnalyzer({ images: { domains: ["react-nodebird.s3.ap-northeast-2.amazonaws.com", "react-nodebird-s3.s3.amazonaws.com"], }, compress: true, compiler: { styledComponents: { ssr: true, displayName: true, }, }, webpack(config, { webpack }) { const prod = process.env.NODE_ENV === "production"; return { ...config, mode: prod ? "production" : "development", devtool: prod ? "hidden-source-map" : "inline-source-map", plugins: [...config.plugins], }; }, }); /package.json{ "name": "react-nodebird", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "next dev", "build": "cross-env ANALYZE=true NODE_ENV=production next build", "start": "cross-env NODE_ENV=production next start -p 80" }, "author": "", "license": "MIT", "dependencies": { "@ant-design/icons": "^5.3.6", "@next/bundle-analyzer": "^14.2.3", "@reduxjs/toolkit": "^2.2.3", "antd": "^5.8.3", "axios": "^1.6.8", "babel-plugin-styled-components": "^2.1.4", "cross-env": "^7.0.3", "dayjs": "^1.11.11", "lodash": "^4.17.21", "next": "^14.2.3", "next-redux-wrapper": "^8.1.0", "pm2": "^5.3.1", "prop-types": "^15.8.1", "react": "^18.3.1", "react-dom": "^18.3.1", "react-hook-form": "^7.51.3", "react-redux": "^9.1.1", "react-slick": "^0.30.2", "redux": "^5.0.1", "redux-saga": "^1.3.0", "shortid": "^2.2.16", "styled-components": "^6.1.8", "swr": "^2.2.5" }, "devDependencies": { "@babel/eslint-parser": "^7.24.5", "@faker-js/faker": "^8.4.1", "babel-eslint": "^10.1.0", "eslint": "^8.57.0", "eslint-config-airbnb": "^19.0.4", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jsx-a11y": "^6.8.0", "eslint-plugin-react": "^7.34.1", "eslint-plugin-react-hooks": "^4.6.2" } } 깃헙 : https://github.com/dydcodydco/react-nodebird