묻고 답해요
121만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
passport 미들웨어를 express-session 밑에다가 반드시 적어야하는 이유
[passport 세팅 및 회원가입 만들기] 강의 중 passport 미들웨어를 왜 express-session 밑에다가 반드시 적어야한다고 하셨는데 이유는 나오지 않았었습니다이유는 무엇일까요?GPT도 써보았지만 생성형 AI라서 틀린 대답일 수 있으므로 강의자분께 질문드립니다.
-
미해결처음하는 MongoDB(몽고DB) 와 NoSQL(빅데이터) 데이터베이스 부트캠프 [입문부터 활용까지] (2023년까지 업데이트)
nosql 섹션3. 몽고DB 데이터 수정하기부분 질문
안녕하세요. 다름이 아니라 강의 17:00에 replace 부분을 보다가 생긴 궁금증인데요 $set 수정부분 키값에서 age와 hobbies 에는 쌍따옴표가 없는데 name에는 있어서 혹시 특별한 의미가 있는지 궁금해서 문의글 남깁니다. name 부분 쌍따옴표가 없어도 실행은 되어서 여쭤 봅니다.
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
9장 게시글 업로드하기 post 오류
[제로초 강좌 질문 필독 사항입니다]질문에는 여러분에게 도움이 되는 질문과 도움이 되지 않는 질문이 있습니다.도움이 되는 질문을 하는 방법을 알려드립니다.https://www.youtube.com/watch?v=PUKOWrOuC0c0. 숫자 0부터 시작한 이유는 1보다 더 중요한 것이기 때문입니다. 에러가 났을 때 해결을 하는 게 중요한 게 아닙니다. 왜 여러분은 해결을 못 하고 저는 해결을 하는지, 어디서 힌트를 얻은 것이고 어떻게 해결한 건지 그걸 알아가셔야 합니다. 그렇지 못한 질문은 무의미한 질문입니다.1. 에러 메시지를 올리기 전에 반드시 스스로 번역을 해야 합니다. 번역기 요즘 잘 되어 있습니다. 에러 메시지가 에러 해결 단서의 90%를 차지합니다. 한글로 번역만 해도 대부분 풀립니다. 그냥 에러메시지를 올리고(심지어 안 올리는 분도 있습니다. 저는 독심술사가 아닙니다) 해결해달라고 하시면 아무런 도움이 안 됩니다.2. 에러 메시지를 잘라서 올리지 않아야 합니다. 입문자일수록 에러메시지에서 어떤 부분이 가장 중요한 부분인지 모르실 겁니다. 그러니 통째로 올리셔야 합니다.3. 코드도 같이 올려주세요. 다만 코드 전체를 다 올리거나, 깃헙 주소만 띡 던지지는 마세요. 여러분이 "가장" 의심스럽다고 생각하는 코드를 올려주세요.4. 이 강좌를 바탕으로 여러분이 응용을 해보다가 막히는 부분, 여러 개의 선택지 중에서 조언이 필요한 부분, 제 경험이 궁금한 부분에 대한 질문은 대환영입니다. 다만 여러분의 회사 일은 질문하지 마세요.5. 강좌 하나 끝날 때마다 남의 질문들을 읽어보세요. 여러분이 곧 만나게 될 에러들입니다.6. 위에 적은 내용을 명심하지 않으시면 백날 강좌를 봐도(제 강좌가 아니더라도) 실력이 늘지 않고 그냥 코딩쇼 관람 및 한컴타자연습을 한 셈이 될 겁니다. 사진업로드를 하려할때 미리보기가 뜨지 않습니다. uploads에는 올린 사진들이 잘 뜹니다.게시글을 업로드하려 짹짹을 누르면 post 라우터가 없다고 뜹니다. POST /post 라우터가 없습니다.404Error: POST /post 라우터가 없습니다. at C:\Users\jyoun\udr_node\lecture\ch9\app.js:53:18 at Layer.handle [as handle_request] (C:\Users\jyoun\udr_node\lecture\ch9\node_modules\express\lib\router\layer.js:95:5) at trim_prefix (C:\Users\jyoun\udr_node\lecture\ch9\node_modules\express\lib\router\index.js:328:13) at C:\Users\jyoun\udr_node\lecture\ch9\node_modules\express\lib\router\index.js:286:9 at Function.process_params (C:\Users\jyoun\udr_node\lecture\ch9\node_modules\express\lib\router\index.js:346:12) at next (C:\Users\jyoun\udr_node\lecture\ch9\node_modules\express\lib\router\index.js:280:10) at C:\Users\jyoun\udr_node\lecture\ch9\node_modules\express\lib\router\index.js:646:15 at next (C:\Users\jyoun\udr_node\lecture\ch9\node_modules\express\lib\router\index.js:265:14) at C:\Users\jyoun\udr_node\lecture\ch9\routes\page.js:12:3 at Layer.handle [as handle_request] (C:\Users\jyoun\udr_node\lecture\ch9\node_modules\express\lib\router\layer.js:95:5) controllers/post.jsconst Post = require('../models/post'); const Hashtag = require('../models/hashtag'); exports.afterUploadImage = (req, res) => { console.log(req.file); res.json({ url: `/img/${req.file.filename}` }); }; exports.uploadPost = async (req, res, next) => { try { const post = await Post.create({ content: req.body.content, img: req.body.url, UserId: req.user.id, }); const hashtags = req.body.content.match(/#[^\s#]*/g); if (hashtags) { const result = await Promise.all(hashtags.map((tag) => { return Hashtag.findOrCreate({ where: { title: tag.slice(1).toLowerCase() } }); })); console.log('result', result); await post.addHashtags(result.map(r => r[0])); } res.redirect('/'); } catch (error) { console.error(error); next(error); } }; routes/post.jsconst express = require('express'); const multer = require('multer'); const path = require('path'); const fs = require('fs'); const { afterUploadImage, uploadPost } = require('../controllers/post'); const { isLoggedIn } = require('../middlewares'); const router = express.Router(); try { fs.readdirSync('uploads'); } catch (error) { console.error('uploads 폴더가 없어 uploads 폴더를 생성합니다.'); fs.mkdirSync('uploads'); } const upload = multer({ storage: multer.diskStorage({ destination(req, file, cb) { cb(null, '/uploads'); }, filename(req, file, cb) { const ext = path.extname(file.originalname); cb(null, path.basename(file.originalname, ext) + Date.now() + ext); }, }), limits: { fileSize: 5 * 1024 * 1024 }, }); // POST /post/img router.post('/img', isLoggedIn, upload.single('img'), afterUploadImage); // POST /post const upload2 = multer(); router.post('/', isLoggedIn, upload2.none(), uploadPost); module.exports = router; 개발자 도구로 보면 짹짹을 눌렀을때 갈곳이 없다는데 저는 깃헙 복사해서 똑같이 했는데 뭐가 문제인지 모르겠습니다. app.jsconst express = require('express'); const cookieParser = require('cookie-parser'); const morgan = require('morgan'); const path = require('path'); const session = require('express-session'); const nunjucks = require('nunjucks'); const dotenv = require('dotenv'); const passport = require('passport'); dotenv.config(); const pageRouter = require('./routes/page'); const authRouter = require('./routes/auth'); const { sequelize } = require('./models'); const passportConfig = require('./passport'); const app = express(); passportConfig(); // 패스포트 설정 app.set('port', process.env.PORT || 8001); app.set('view engine', 'html'); nunjucks.configure('views', { express: app, watch: true, }); sequelize.sync({ force: false }) .then(() => { console.log('데이터베이스 연결 성공'); }) .catch((err) => { console.error(err); }); app.use(morgan('dev')); app.use(express.static(path.join(__dirname, 'public'))); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser(process.env.COOKIE_SECRET)); app.use(session({ resave: false, saveUninitialized: false, secret: process.env.COOKIE_SECRET, cookie: { httpOnly: true, secure: false, }, })); app.use(passport.initialize()); app.use(passport.session()); app.use('/', pageRouter); app.use('/auth', authRouter); app.use((req, res, next) => { const error = new Error(`${req.method} ${req.url} 라우터가 없습니다.`); error.status = 404; next(error); }); app.use((err, req, res, next) => { res.locals.message = err.message; res.locals.error = process.env.NODE_ENV !== 'production' ? err : {}; res.status(err.status || 500); res.render('error'); }); app.listen(app.get('port'), () => { console.log(app.get('port'), '번 포트에서 대기중'); }); main.html{% extends 'layout.html' %} {% block content %} <div class="timeline"> {% if user %} <div> <form id="twit-form" action="/post" method="post" enctype="multipart/form-data"> <div class="input-group"> <textarea id="twit" name="content" maxlength="140"></textarea> </div> <div class="img-preview"> <img id="img-preview" src="" style="display: none;" width="250" alt="미리보기"> <input id="img-url" type="hidden" name="url"> </div> <div> <label id="img-label" for="img">사진 업로드</label> <input id="img" type="file" accept="image/*"> <button id="twit-btn" type="submit" class="btn">짹짹</button> </div> </form> </div> {% endif %} <div class="twits"> <form id="hashtag-form" action="/hashtag"> <input type="text" name="hashtag" placeholder="태그 검색"> <button class="btn">검색</button> </form> {% for twit in twits %} <div class="twit"> <input type="hidden" value="{{twit.User.id}}" class="twit-user-id"> <input type="hidden" value="{{twit.id}}" class="twit-id"> <div class="twit-author">{{twit.User.nick}}</div> {% if not followingIdList.includes(twit.User.id) and twit.User.id !== user.id %} <button class="twit-follow">팔로우하기</button> {% endif %} <div class="twit-content">{{twit.content}}</div> {% if twit.img %} <div class="twit-img"><img src="{{twit.img}}" alt="섬네일"></div> {% endif %} </div> {% endfor %} </div> </div> {% endblock %} {% block script %} <script> if (document.getElementById('img')) { document.getElementById('img').addEventListener('change', function(e) { const formData = new FormData(); console.log(this, this.files); formData.append('img', this.files[0]); axios.post('/post/img', formData) .then((res) => { document.getElementById('img-url').value = res.data.url; document.getElementById('img-preview').src = res.data.url; document.getElementById('img-preview').style.display = 'inline'; }) .catch((err) => { console.error(err); }); }); } document.querySelectorAll('.twit-follow').forEach(function(tag) { tag.addEventListener('click', function() { const myId = document.querySelector('#my-id'); if (myId) { const userId = tag.parentNode.querySelector('.twit-user-id').value; if (userId !== myId.value) { if (confirm('팔로잉하시겠습니까?')) { axios.post(`/user/${userId}/follow`) .then(() => { location.reload(); }) .catch((err) => { console.error(err); }); } } } }); }); </script> {% endblock %}
-
미해결따라하며 배우는 TDD 개발 [2023.11 업데이트]
res.status(201) 부분에서 typeerror가 발생합니다
에러메시지: TypeError: Cannot read properties of undefined (reading 'status')res.status(200); 해당 코드에서 발생하는 에러인데 강사님이 코드돌리실때는 해당 에러가 발생하지 않는데 제 pc에서는 왜 에러가 발생하는지 잘 모르겠습니다...코드는 강의에서 입력하신 그대로 따라서 했습니다
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 쇼핑몰 사이트 만들기[전체 리뉴얼]
2강 eslint
코드 똑같이 따라쳤는데도 04:42처럼 밑줄이 안뜹니다. 그리고 도표강의자료는 왜 안열리는건가요?
-
미해결따라하며 배우는 TDD 개발 [2023.11 업데이트]
따라하며 배우는 TDD 개발 [2023.11 업데이트] 강의 질문
따라하며 배우는 TDD 개발 [2023.11 업데이트]2023.11 업데이트라고 되어 있는데, 이게 업데이트 반영 된건가요?
-
미해결배달앱은 어떻게 내 주변의 맛집을 찾을까?
test.sh 파일 실행 후 에러 처리 방법
질문하실 땐 https://gist.github.com/ 를 사용하시면 코드를 쉽게 공유할 수 있습니다!원하고자 하는 것실제 작성한 코드실행한 결과원하는 결과이렇게 4가지를 꼭 적어주셔야 도와드릴 수 있습니다 :) 처음 프로젝트를 실행 후 test.sh 파일을 실행했는데에러가 두개 발생했습니다.에러 처리는 어떻게 하나요?제 에러는 첨부한 사진과 같습니다.파이썬(3.11.3), poetry(1.4.2) 모두 강의에 나온 버전 설치했습니다.
-
해결됨배달앱은 어떻게 내 주변의 맛집을 찾을까?
테스트를 실행했을 때 RuntimeError: Event loop is closed 에러가 발생합니다.
질문하실 땐 https://gist.github.com/ 를 사용하시면 코드를 쉽게 공유할 수 있습니다!원하고자 하는 것실제 작성한 코드실행한 결과원하는 결과 이렇게 4가지를 꼭 적어주셔야 도와드릴 수 있습니다 :) test_shop_insert_one() 함수를 추가하여 테스트를 실행했을 때 RuntimeError: Event loop is closed 에러가 발생하여 테스트가 실패합니다. app/tests/entities/collections/shop/test_shop_collection.py F [100%] ============================================================================= FAILURES ============================================================================= _______________________________________________________________________ test_shop_insert_one _______________________________________________________________________ @pytest.mark.asyncio async def test_shop_insert_one() -> None: # Given name = "치킨집" category_codes = [CategoryCode.CHICKEN] delivery_areas = [ ShopDeliveryAreaSubDocument( poly=GeoJsonPolygon(coordinates=[[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]]]), ) ] # When > shop = await ShopCollection.insert_one(name, category_codes, delivery_areas) app/tests/entities/collections/shop/test_shop_collection.py:21: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ app/entities/collections/shop/shop_collection.py:20: in insert_one result = await cls._collection.insert_one( /PATH/OF/POETRY/CACHE/lib/python3.11/site-packages/motor/metaprogramming.py:73: in method return framework.run_on_executor( /PATH/OF/POETRY/CACHE/lib/python3.11/site-packages/motor/frameworks/asyncio/__init__.py:85: in run_on_executor return loop.run_in_executor(_EXECUTOR, functools.partial(fn, *args, **kwargs)) /PATH/OF/PYTHON/lib/python3.11/asyncio/base_events.py:816: in run_in_executor self._check_closed() _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_UnixSelectorEventLoop running=False closed=True debug=False> def _check_closed(self): if self._closed: > raise RuntimeError('Event loop is closed') E RuntimeError: Event loop is closed /PATH/OF/PYTHON/lib/python3.11/asyncio/base_events.py:519: RuntimeError ===================================================================== short test summary info ====================================================================== FAILED app/tests/entities/collections/shop/test_shop_collection.py::test_shop_insert_one - RuntimeError: Event loop is closed =================================================================== 1 failed, 1 passed in 0.55s ====================================================================에러로그는 위와 같습니다. --async-mode 를 test로 변경해보면 저 단계까지 가기 전에 에러가 발생하고@pytest.mark.asyncio 어노테이션을 추가해줘도 결과는 같습니다.poetry 를 이용한 환경 구성이 처음이라 해당 지식이 많이 부족하여 이 문제를 어떻게 해결해야하는지 잘 모르겠습니다. 파이썬 버전은 3.11.3poetry 버전은 1.4.2mongodb 버전은 6.0.11 입니다. [tool.poetry.dependencies] fastapi = "^0.95.2" gunicorn = "^20.1.0" httpx = "^0.24.1" motor = "^3.1.2" orjson = "^3.8.14" python = "^3.11" uvicorn = "^0.22.0" [tool.poetry.group.dev.dependencies] black = {extras = ["d"], version = "^23.3.0"} coverage = "^7.2.3" isort = "^5.12.0" mypy = "^1.3.0" pytest = "^7.3.1" pytest-asyncio = "^0.21.0" toml-sort = "^0.23.0" 작성한 코드의 차이점은 db가 로컬에 있지 않고 외부에 있는 관계로def create_mongo_url(host: str = "localhost", port: int = 27017) -> str: return f"mongodb://{host}:{port}" DATABASE_NAME = os.environ.get("MONGO_DATABASE", "yorigin") HOST = os.environ.get("MONGO_HOST", "localhost") PORT = os.environ.get("MONGO_PORT", 27017) client = AsyncIOMotorClient(create_mongo_url(HOST, int(PORT)))이와 같은 코드를 추가하여 지정된 host의 mongodb와 통신할 수 있도록 한 것이 전부입니다. 확인 부탁드릴 수 있을까요?
-
해결됨탄탄한 백엔드 NestJS, 기초부터 심화까지
AlreadyHasActiveConnectionError 에러 발생
에러 해결하였습니다..app.module.ts > typeOrmModuleOptions에keepConnectionAlive: true 옵션이 빠져있어 발생한 에러였습니다. 검색해보니 '어플리케이션 종료 시 DB 연결 유지'에 대한 내용인데제가 다른 옵션과 착각하고 주석 처리했었습니다. 현재 옵션 활성화 하였고 e2e 테스트 정상적으로 진행되는거 확인했습니다.const typeOrmModuleOptions = { useFactory: async ( configService: ConfigService, ): Promise<TypeOrmModuleOptions> => ({ namingStrategy: new SnakeNamingStrategy(), // ... keepConnectionAlive: true, }), 검색해보니 beforeEach에 있는 app.init() 메소드에서 어플리케이션을 초기화하며 DB 연결도 초기화되는데,어플리케이션을 재초기화하는 것이지 종료한 적은 없었기에 여전히 'default'라는 이름으로 활성화된 DB 연결이 존재하였고,DB 연결 재초기화 중 'default라는 이름으로 새로운 DB 연결이 실패하였다' 에러가 발생한 것이며 keepConnectionAlive: true 옵션을 줌으로써DB 연결은 어플리케이션의 생명주기와는 별도로 존재하게 되고, 이미 활성화된 DB 연결이 존재하므로 새로운 DB 연결을 시도하지 않는다 라고 합니다..공부가 되었네요. app.e2e-spec.ts의 afterEach 메소드는 제거하였습니다. ============================================================= 안녕하세요 강사님강의따라 진행하다 에러가 발생하여 질문글 남깁니다. 에러 메세지는 아래와 같습니다.[Nest] 26544 - 2023. 11. 25. 오후 11:01:36 ERROR [TypeOrmModule] Unable to connect to the database. Retrying (1)... AlreadyHasActiveConnectionError: Cannot create a new connection named "default", because connection with such name already exist and it now has an active connection session. at AlreadyHasActiveConnectionError.TypeORMError [as constructor] (C:\Users\admin\OneDrive\바탕 화면\typeorm-in-the-nest\src\error\TypeORMError.ts:7:9) at new AlreadyHasActiveConnectionError (C:\Users\admin\OneDrive\바탕 화면\typeorm-in-the-nest\src\error\AlreadyHasActiveConnectionError.ts:8:9) at ConnectionManager.Object.<anonymous>.ConnectionManager.create (C:\Users\admin\OneDrive\바탕 화면\typeorm-in-the-nest\src\connection\ConnectionManager.ts:57:23) at C:\Users\admin\OneDrive\바탕 화면\typeorm-in-the-nest\src\globals.ts:77:35 at step (C:\Users\admin\OneDrive\바탕 화면\typeorm-in-the-nest\node_modules\tslib\tslib.js:143:27) at Object.next (C:\Users\admin\OneDrive\바탕 화면\typeorm-in-the-nest\node_modules\tslib\tslib.js:124:57) at C:\Users\admin\OneDrive\바탕 화면\typeorm-in-the-nest\node_modules\tslib\tslib.js:117:75 at new Promise (<anonymous>) at Object.__awaiter (C:\Users\admin\OneDrive\바탕 화면\typeorm-in-the-nest\node_modules\tslib\tslib.js:113:16) at createConnection (C:\Users\admin\OneDrive\바탕 화면\typeorm-in-the-nest\node_modules\typeorm\globals.js:55:20) [Nest] 26544 - 2023. 11. 25. 오후 11:01:39 ERROR [TypeOrmModule] Unable to connect to the database. Retrying (2)... AlreadyHasActiveConnectionError: Cannot create a new connection named "default", because connection with such name already exist and it now has an active connection session. at AlreadyHasActiveConnectionError.TypeORMError [as constructor] (C:\Users\admin\OneDrive\바탕 화면\typeorm-in-the-nest\src\error\TypeORMError.ts:7:9) at new AlreadyHasActiveConnectionError (C:\Users\admin\OneDrive\바탕 화면\typeorm-in-the-nest\src\error\AlreadyHasActiveConnectionError.ts:8:9) at ConnectionManager.Object.<anonymous>.ConnectionManager.create (C:\Users\admin\OneDrive\바탕 화면\typeorm-in-the-nest\src\connection\ConnectionManager.ts:57:23) at C:\Users\admin\OneDrive\바탕 화면\typeorm-in-the-nest\src\globals.ts:77:35 at step (C:\Users\admin\OneDrive\바탕 화면\typeorm-in-the-nest\node_modules\tslib\tslib.js:143:27) at Object.next (C:\Users\admin\OneDrive\바탕 화면\typeorm-in-the-nest\node_modules\tslib\tslib.js:124:57) at C:\Users\admin\OneDrive\바탕 화면\typeorm-in-the-nest\node_modules\tslib\tslib.js:117:75 at new Promise (<anonymous>) at Object.__awaiter (C:\Users\admin\OneDrive\바탕 화면\typeorm-in-the-nest\node_modules\tslib\tslib.js:113:16) at createConnection (C:\Users\admin\OneDrive\바탕 화면\typeorm-in-the-nest\node_modules\typeorm\globals.js:55:20) FAIL test/app.e2e-spec.ts (10.952 s) AppController (e2e) √ / (GET) (845 ms) hello jest × two plus two is four (5014 ms) ● AppController (e2e) › hello jest › two plus two is four thrown: "Exceeded timeout of 5000 ms for a hook. Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test." 7 | let app: INestApplication; 8 | > 9 | beforeEach(async () => { | ^ 10 | const moduleFixture: TestingModule = await Test.createTestingModule({ 11 | imports: [AppModule], 12 | }).compile(); at app.e2e-spec.ts:9:3 at Object.<anonymous> (app.e2e-spec.ts:6:1) Test Suites: 1 failed, 1 total Tests: 1 failed, 1 passed, 2 total Snapshots: 0 total Time: 11.106 s Ran all test suites. Jest did not exit one second after the test run has completed. This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with `--detectOpenHandles` to troubleshoot 읽어보니 이미 'default'라는 이름의 연결이 존재하고, 현재 활성화 중이므로 같은 이름의 연결을 또 생성할 수 없다는 것 같고,검색해보니 beforeEach 메소드 안에 Test.createTestingModule이 매 테스트마다 DB 연결을 시도하는 상황이라고 나왔습니다.. 하여 아래와 같이 afterEach 메소드를 사용하여 매 테스트마다 어플리케이션을 종료해주도록 코드를 수정하였습니다.describe('AppController (e2e)', () => { let app: INestApplication; beforeEach(async () => { const moduleFixture: TestingModule = await Test.createTestingModule({ imports: [AppModule], }).compile(); app = moduleFixture.createNestApplication(); await app.init(); }); // 테스트 2개 이상 사용할 경우 필요한 메소드 afterEach(async () => { await app.close(); }); it('/ (GET)', () => { return request(app.getHttpServer()) .get('/') .expect(200) .expect('typeorm in nest, just coding'); }); describe('hello jest', () => { it('two plus two is four', () => { expect(2 + 2).toBe(4); }); }); // 생략 수정 후 강의에서 진행했던 내용은 모두 완료가 되었는데..이제 궁금한 점은강사님과 코드 내용이 같고 도커나 DB 연결에 대하여 특별히 수정한 내용이 없는데왜 이런 상황이 발생하는 것인지. 버전이 달라 발생한 상황인 것인지.. 그리고 afterEach를 사용하였을때 당장 테스트 진행은 가능하지만 이대로 사용해도 괜찮을지 안좋은 것은 아닌지가 궁금합니다..
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 쇼핑몰 사이트 만들기[전체 리뉴얼]
multer를 이용해 상품 사진을 업로드할 때 서버 오류가 생깁니다.
FileUpload.jsx:18 POST http://localhost:4000/products/image 500 (Internal Server Error)이런식으로 에러가 생기는데 gpt에도 도움을 요청해봤지만 명확한 오류를 찾지 못했습니다. 도와주세요 ㅜㅜ
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 쇼핑몰 사이트 만들기[전체 리뉴얼]
SyntaxError: await is only valid in async functions and the top level bodies of module
안녕하세요! 현재 몽고DB로 백엔드 설정 중인데 강의를 따라가던중이런한 에러로 진행을 못하고 있습니다. 문제원인은 await가 async함수안에 들어가 한다고 하는데 강의에서는 async를 쓰는걸 본적이 없는데 문제를 어떻게 해결해야하나요?
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
람다 접근 에러
너무 자주 잘문드려 죄송합니다...2023-11-23T13:10:50.588Z 50b59392-754b-4b9c-90a1-ed48e95f40e1 ERROR AccessDenied: Access Denied at throwDefaultError (/var/task/node_modules/@smithy/smithy-client/dist-cjs/default-error-handler.js:8:22) at /var/task/node_modules/@smithy/smithy-client/dist-cjs/default-error-handler.js:18:39 at de_GetObjectCommandError (/var/task/node_modules/@aws-sdk/client-s3/dist-cjs/protocols/Aws_restXml.js:4330:20) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async /var/task/node_modules/@smithy/middleware-serde/dist-cjs/deserializerMiddleware.js:7:24 at async /var/task/node_modules/@aws-sdk/middleware-signing/dist-cjs/awsAuthMiddleware.js:14:20 at async /var/task/node_modules/@smithy/middleware-retry/dist-cjs/retryMiddleware.js:27:46 at async /var/task/node_modules/@aws-sdk/middleware-flexible-checksums/dist-cjs/flexibleChecksumsMiddleware.js:63:20 at async /var/task/node_modules/@aws-sdk/middleware-sdk-s3/dist-cjs/region-redirect-endpoint-middleware.js:14:24 at async /var/task/node_modules/@aws-sdk/middleware-sdk-s3/dist-cjs/region-redirect-middleware.js:9:20 { '$fault': 'client', '$metadata': { httpStatusCode: 403, requestId: 'S3JVT25F4WT5TH9H', extendedRequestId: 'i2FSNxeCIH5smb0tHWggtUQ7WWZIvDurOoQ4UGIZ1eVgwIPsJwrNC85V8Oh2XHVpCaFyITlXaaM=', cfId: undefined, attempts: 1, totalRetryDelay: 0 }, Code: 'AccessDenied', RequestId: 'S3JVT25F4WT5TH9H', HostId: 'i2FSNxeCIH5smb0tHWggtUQ7WWZIvDurOoQ4UGIZ1eVgwIPsJwrNC85V8Oh2XHVpCaFyITlXaaM='}이러한 에러가 발생했습니다. 찾아보니깐 s3 버컷 정책과 관련이 있는 것 같습니다.{ "Version": "2012-10-17", "Statement": [ { "Sid": "AddPerm", "Effect": "Allow", "Principal": "*", "Action": [ "s3:GetObject", "s3:PutObject" ], "Resource": "arn:aws:s3:::whatsup1/*" } ]}이게 저의 s3 버캣 정책입니다.그리고 아래는 aws-upload의 index.js입니다 //이미지 리사이징 라이브러리 const sharp = require("sharp"); const { S3Client, GetObjectCommand, PutObjectCommand, } = require("@aws-sdk/client-s3"); //함수가 aws 람다에서 돌아가기 때문에 스크릿키랑 아이디를 자동으로 넣어준다 = > 아무것도 넣어줄 필요 x const s3 = new S3Client(); //람다는 3개의 매개변수를 제공하고 이 함수를 호출해준다. exports.handler = async (event, context, callback) => { const Bucket = event.Records[0].s3.bucket.name; const Key = decodeURIComponent(event.Records[0].s3.object.key); //original/리버풀.png const filename = Key.split("/").at(-1); const ext = Key.split(".").at(-1).toLowerCase(); const requiredFormat = ext === "jpg" ? "jpeg" : ext; console.log("name", filename, "ext", ext); try { const getObject = await s3.send(new GetObjectCommand({ Bucket, Key })); const buffers = []; for await (const data of getObject.Body) { buffers.push(data); } const imageBuffer = Buffer.concat(buffers); console.log("original", getObject); const resizedImage = await sharp(imageBuffer) .resize(200, 200, { fit: "inside" }) .toFormat(requiredFormat) .toBuffer(); await s3.send( new PutObjectCommand({ Bucket, Key: `thumb/${filename}`, Body: resizedImage, }) ); console.log("put", resizedImage.length); return callback(null, `thumb/${filename}`); } catch (error) { console.error(error); return callback(error); } }; 구글링 해보니깐 s3정책들이 비슷하면서 약간씩 다르던데 뭐가 맞는건지 잘 모르겠습니다..
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
람다 에러
stack": [ "Error: ", "Something went wrong installing the \"sharp\" module", "", "Cannot find module '../build/Release/sharp-linux-arm64v8.node'"이렇게 에러가 발생했는데 람다에서 함수 생성시 선택사항에 보면아키텍쳐 선택할때 제로초님은 기본적으로 선택되어있는 x86을 선택하셨고 저는 맥북에어 m2를 사용해서 arm64를 선택했는데 이거 때문에 에러가 난걸까요? 그리고 제로초님이 강의 만드실때는 node 18버전이 최신버전이였는데 지금은 20까지 나와서 20으로 했는데 이것도 문제가 될까요?
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
Error: Data too long for column
req.file을 보면 아래와 같이 나옵니다.{ fieldname: 'img', originalname: 'á\x84\x89á\x85³á\x84\x8Fá\x85³á\x84\x85á\x85µá\x86«á\x84\x89á\x85£á\x86º 2023-11-22 á\x84\x8Bá\x85©á\x84\x92á\x85® 8.36.00.png', encoding: '7bit', mimetype: 'image/png', size: 156946, bucket: 'whatsup1', key: 'original/1700700649389_á\x84\x89á\x85³á\x84\x8Fá\x85³á\x84\x85á\x85µá\x86«á\x84\x89á\x85£á\x86º 2023-11-22 á\x84\x8Bá\x85©á\x84\x92á\x85® 8.36.00.png', acl: 'private', contentType: 'application/octet-stream', contentDisposition: null, contentEncoding: null, storageClass: 'STANDARD', serverSideEncryption: null, metadata: undefined, location: 'https://whatsup1.s3.ap-northeast-2.amazonaws.com/original/1700700649389_%C3%A1%C2%84%C2%89%C3%A1%C2%85%C2%B3%C3%A1%C2%84%C2%8F%C3%A1%C2%85%C2%B3%C3%A1%C2%84%C2%85%C3%A1%C2%85%C2%B5%C3%A1%C2%86%C2%AB%C3%A1%C2%84%C2%89%C3%A1%C2%85%C2%A3%C3%A1%C2%86%C2%BA%202023-11-22%20%C3%A1%C2%84%C2%8B%C3%A1%C2%85%C2%A9%C3%A1%C2%84%C2%92%C3%A1%C2%85%C2%AE%208.36.00.png', etag: '"9afb9409e1bcd41269629b6bb1100245"', versionId: undefined}제로초님은 사진 파일 확장자가 jpg로 뜨는데 저는 png로 뜹니다..s3에 저장되는 쪽이 아니라 사진을 파일로 만드는 부분에서 문제가 있는 것 같은데 어느부분에서 손을 봐야할지 잘 모르겠습니다..const { S3Client } = require("@aws-sdk/client-s3"); const multerS3 = require("multer-s3"); const s3 = new S3Client({ credentials: { accessKeyId: process.env.S3_ACCESS_KEY_ID, secretAccessKey: process.env.S3_SECRET_ACCESS_KEY, }, region: "ap-northeast-2", }); const upload = multer({ storage: multerS3({ s3, bucket: "whatsup1", key(req, file, cb) { cb(null, `original/${Date.now()}_${file.originalname}`); }, }), limits: { fileSize: 5 * 1024 * 1024 }, });그리고 추가적인 질문이 있는데 localhost로 서버를 작동시킬때 db는 잘 보이는데 lightsail로 작동시킨 db가 보이지 않습니다..mysql connection 추가 버튼 눌러서 hostname을 aws에서 제공해준 ip로 바꾸면 되는거 아닌가요?그런데 그렇게 하고 연결을 하니깐 버퍼링이 걸리면서 연결이 되지 않습니다..
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
카카오 로그인 질문드립니다!
안녕하세요!!제가 지금 Next.js와 Node.js를 활용해서 중고거래 사이트를 프론트와 백 둘다 구현을 하려고 하는데프론트(NextAuth)에서 API 를 받아와 카카오 로그인을 구현하면, 백에서는 카카오 로그인에대한 구현을 할 필요가 없는건가요?또, 프론트 나 백 둘중 어느곳에서 카카오 로그인을 구현해야 효율적인지 궁금합니다!
-
해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
11.3 통합테스트 중 TypeError: model.initiate is not a function
질문할까 고민하다가 용기내어 질문드려봅니다..!11장 통합테스트 중 나타난 에러입니다.npm test 를 입력하면 나오는 에러입니다.> nodebird@0.0.1 test > jest PASS models/user.test.js PASS services/user.test.js PASS middlewares/index.test.js FAIL routes/auth.test.js ● Test suite failed to run TypeError: model.initiate is not a function 22 | console.log(file, model.name); 23 | db[model.name] = model; > 24 | model.initiate(sequelize); | ^ 25 | }); 26 | 27 | Object.keys(db).forEach(modelName => { // associate 호출 at initiate (models/index.js:24:11) at Array.forEach (<anonymous>) at Object.forEach (models/index.js:20:4) at Object.require (routes/auth.test.js:2:23) Test Suites: 1 failed, 3 passed, 4 total Tests: 9 passed, 9 total Snapshots: 0 total Time: 0.725 s, estimated 1 s현재 에러는 model.initiate가 함수화가 되지 않았다고 나타는거 같습니다.model.initiate가 존재하는 index.js입니다.const Sequelize = require('sequelize'); const fs = require('fs'); const path = require('path'); const env = process.env.NODE_ENV || 'development'; const config = require('../config/config')[env]; const db = {}; const sequelize = new Sequelize( config.database, config.username, config.password, config, ); db.sequelize = sequelize; const basename = path.basename(__filename); fs .readdirSync(__dirname) .filter(file => { return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js'); }) .forEach(file => { const model = require(path.join(__dirname, file)); console.log(file, model.name); db[model.name] = model; model.initiate(sequelize); // 오류 발생시점 }); Object.keys(db).forEach(modelName => { if (db[modelName].associate) { db[modelName].associate(db); } }); module.exports = db;11.3 강의를 보는 중이며 auth.test.js 코드를 작성중입니다작성중인 auth.test.js는 아래와 같습니다.const app = require('../app'); const request = require('supertest'); const { sequelize } = require('../models'); beforeAll(async () => { await sequelize.sync() }) beforEach(() => { }); describe('POST /join', () => { test('로그인 안 했으면 가입', (done) => { request(app).post('/auth/join') .send({ email: 'choibo@naver.com', nick: 'bobobo', password: 'choibo11' }) .expect('Location', '/') .expect(302, done) }) }) describe('POST /login', () =>{ test('로그인 수행', (done) => { request(app).post('/auth/login') .send({ email: 'choibo@naver.com', password: 'choibo11' }) .expect('Location', '/') .expect(302, done) }) }); afterEach(() => {}); aftereAll(() => { }); 이부분에서 에러가 발생한다고 나타나있습니다.const { sequelize } = require('../models');
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
S3 버킷 만들 때 암호화 유형
버킷 만들때 강의 와 달리 처음부터 저렇게 선택되어있던데 그냥 원래 선택되었던거 유지하면서 만들면 되나요?
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
pm2 error
const express = require("express"); const cookieParser = require("cookie-parser"); const morgan = require("morgan"); const session = require("express-session"); const router = express.Router(); const path = require("path"); const dotenv = require("dotenv"); const passport = require("passport"); const app = express(); const passportConfig = require("./passport"); const redis = require("redis"); const RedisStore = require("connect-redis").default; dotenv.config(); const redisClient = redis.createClient({ url: `redis://${process.env.REDIS_HOST}:${process.env.REDIS_PORT}`, password: process.env.REDIS_PASSWORD, legacyMode: false, }); redisClient.connect().catch(console.error); const authRouter = require("./routes/auth"); const pageRouter = require("./routes/page"); const postRouter = require("./routes/post"); const userRouter = require("./routes/user"); const commentRouter = require("./routes/comment"); const updateRouter = require("./routes/update"); const deleteRouter = require("./routes/delete"); const helmet = require("helmet"); const hpp = require("hpp"); const { sequelize } = require("./models"); const logger = require("./logger"); passportConfig(); app.set("port", process.env.PORT || 8005); sequelize .sync({ force: false }) .then(() => { console.log("데이터베이스 연결 성공"); }) .catch((err) => { console.error(err); }); if (process.env.NODE_ENV === "production") { app.use( helmet({ contentSecurityPolicy: false, crossOriginEmbedderPolicy: false, crossOriginResourcePolicy: false, crossOriginOpenerPolicy: false, originAgentCluster: false, }) ); app.use(hpp()); app.use(morgan("combined")); } else { app.use(morgan("dev")); } app.use(express.json({ limit: "10mb" })); var cors = require("cors"); const { deepStrictEqual } = require("assert"); app.use(cors()); app.use("/img", express.static(path.join(__dirname, "uploads"))); app.use("/profileImg", express.static(path.join(__dirname, "profileImg"))); app.use(express.json()); app.use(express.urlencoded({ limit: "10mb", extended: false })); app.use(cookieParser(process.env.COOKIE_SECRET)); const sessionOption = { resave: false, saveUninitialized: false, secret: process.env.COOKIE_SECRET, cookie: { httpOnly: true, secure: false, }, store: new RedisStore({ client: redisClient }), }; if (process.env.NODE_ENV === "production") { sessionOption.proxy = true; } app.use(session(sessionOption)); app.use(passport.initialize()); app.use(passport.session()); app.use(express.static(path.join(__dirname, "prototype-client/build"))); app.get("/", (req, res) => { res.sendFile(path.join(__dirname, "prototype-client/build/index.html")); }); app.use("/page", pageRouter); app.use("/auth", authRouter); app.use("/post", postRouter); app.use("/user", userRouter); app.use("/comment", commentRouter); app.use("/update", updateRouter); app.use("/delete", deleteRouter); //react에서 react-router-dom으로 다룰 수 있게 app.get("*", function (req, res) { res.sendFile(path.join(__dirname, "/prototype-client/build/index.html")); }); //에러 처리 담당 app.use((req, res, next) => { const error = new Error(`${(req, method)} ${req.url} 라우터가 없습니다.`); error.status = 404; logger.info("hello"); logger.error(error.message); next(error); }); app.use((err, req, res, next) => { console.error(err); res.locals.message = err.message; res.locals.erorr = process.env.NODE_ENV !== "production" ? err : {}; res.status(err.status || 500); res.render("error"); }); module.exports = app;이렇게 코드를 실행하면 sudo pm2 monit의 server log에 2가지 에러가 나옵니다. server > [Error: ENOENT: no such file or directory, stat │ ││ server > errno: -2, │ ││ server > code: 'ENOENT', │ ││ server > syscall: 'stat', │ ││ server > path: '/home/bitnami/Whats-up/prototype-client/bu ││ ││ server > expose: false, │ ││ server > statusCode: 404, │ ││ server > status: 404 │ ││ server > } 에러 메시지를 봤을때 해당 경로에 대한 파일을 찾을 수 없다고 하는데 ls를 입력했을때 잘 있는걸 확인 할 수 있는데 왜 이런 에러가 발생하는지 모르겠습니다..2번쨰는 server > Error: No default engine was specified and no ││ server > at new View (/home/bitnami/Whats-up/node_module │ ││ server > at Function.render (/home/bitnami/Whats-up/node │││ server > at ServerResponse.render (/home/bitnami/Whats-u │ ││ server > at /home/bitnami/Whats-up/app.js:127:7 │ ││ server > at Layer.handle_error (/home/bitnami/Whats-up/n │ ││ server > at trim_prefix (/home/bitnami/Whats-up/node_mod │ ││ server > at /home/bitnami/Whats-up/node_modules/express/ ││ server > at Function.process_params (/home/bitnami/Whats 이런 에러가 발생합니다. 에러 메세지를 봤을떄는 view engine관련된 에러같은데 react랑 express연동할때는 따로 view engine 설정을 주지 않고 express.static으로 리액트 코드를 전달하면 되는거 아닌가요?
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
AWS 설정 후 실행했을때 사이트에 연결할 수 없음이 뜹니다
저는 지금 단순 html페이지 대신 react와 함께 nodebird 프로젝트를 하고 있는데요. 지금 aws설정도 다 마치고 pm2를 실행하고 sudo pm2 list를 해봐도 오류 없이 잘 실행됩니다.그래서 크롬 주소창에 ip를 입력하면 사이트에 연결할 수 없다고 합니다.. 직접적으로 에러가 뜨는 것도 아니여서 어디가 문제인지 잘 모르겠습니다..github:https://github.com/AUDWO/Whats-up/blob/main/app.js(prototype-client가 리액트로 만든 페이지 입니다)
-
미해결MERN 스택으로 만드는 지도서비스(+ TypeScript)
보일러 플레이트 다운 시 빈 폴더
소스 코드 다운받았을 때 깨지는 지 빈 폴더로 나옵니다!그리고 해당 프로젝트 깃 허브 부탁드려용