월 17,600원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
해시태그가 불러와지지 않습니다....ㅠ
영상을 보고 따라하고 있는데 user/1은 잘 되지만 /hashtag/해시태그는 불러와지지가 않습니다... 원인을 알려주시면 진심으로 감사드립니다....
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
http://localhost:3060/post/1에서 에러가 발생했습니다..ㅠ
바쁘실텐데 질문드려서 죄송합니다. 영상을 보고 따라하며 공부하고 있는데 localhost:3060/post/1에서 에러가 발생했습니다. 그전까지 잘 따라했다고 생각했는데 이유를 잘 모르겠네요.... 원인을 알려주시면 진심으로 감사드립니다.....ㅠ
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
jwt방식을 이용하려고 하는데 사가에서 이런식의 코드를 이용해도 문제 없는건가요?
안녕하세요 제로초님 jwt방식의 로그인을 이런식으로 해결해도 되는 지 여쭙고 싶습니다. 그리고 서버사이드props를 사용할 때 어떤식으로 토큰확인을 해야하는 지도 여쭙고 싶습니다 감사합니다
- 해결됨[리뉴얼] React로 NodeBird SNS 만들기
모바일버전 대응
일반 데스크탑화면일때 뷰량 모바일일때 뷰량 헤더부분(네비게이션) 을 다르게 구성해서 모바일로 가면 화면을 다른걸로 보여줘야되는데 어떻게 해야되나요?
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
index 페이지 속도가 왜이리 느릴까요?
아래에도 어떤 분이 같은 주제로 올리신 질문입니다. index 페이지 속도 관련인데요, 배포 환경 기준 index 페이지 로드에 약 5~6초 가량 걸립니다. 다른 페이지 ssr 1~2초 걸리는건 귀여운 수준이네요.. 로초님이 Link들에 prefetch={false} 거실때 전 패스했는데 그게 느려지는 원인이 될 수 있을까요? 개선해야 한다면 어떤 방향으로 개선하는게 좋을까요? https://nodebird.com/ 은 속도 기가막힌걸 보면 제 쪽 문제일텐데 코드는 대부분 그대로 따라쳤는데 이렇게까지 차이가 날 수 있나 싶구요.. 배포사이트 - https://bearsns.com/ index 소스코드 - https://github.com/bear-bear-bear/sns-clone/blob/master/front/pages/index.js
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
useSWR에 대해서
안녕하세요. 제로초님 최근에 제로초님을 통해 useSWR에 대해서 알게되었고 이에 대한 내용을 찾아보다가 궁금점이 생겨 질문남깁니다. 많은 글에서 useSWR을 활용하여 상태관리를 할 수 있다고 하여서 여러 자료를 뒤져봤는데요. userSWR은 비동기 데이터만을 위한 상태관리로 사용하고 비동기 데이터 외에 다른 전역으로 상태관리가 필요한 예를 들어 토스트 메시지라던가 하는 데이터들은 contextAPI나 Redux를 이용해서 관리해주어야하나요? useSWR을 이용해서 비동기 데이터 외에도 전역상태 관리가 필요한 다른 데이터도 활용가능한지 useSWR이 Redux와 ContextAPI를 대체할수 있는건지 궁금합니다.
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
where는
이렇게 where 조건 2가지면 2가지 조건을 다만족해야하나요? where: { id: req.params.postId, UserId: req.user.id, },
- 해결됨[리뉴얼] React로 NodeBird SNS 만들기
_app.js 특정페이지에 적용하고싶지 않을때
_app.js 를 적용하면 모든페이지에 적용된다 했는데 특정페이지만 _app.js 를 적용하고싶지 않으면 어떻게 해야되나요?
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
새로고침후 content
안녕하세요, 제로초님 영상강의 잘 따라가면서 문제없이 진행하다가 서버 재시작하거나 새로고침하면 2번째 사진처럼 돌아가는데 routes/post.js에서 게시글 로드할때 데이터를 다시 가공해야하는 건가요?..
- 해결됨[리뉴얼] React로 NodeBird SNS 만들기
eslint 적용 후 에러...
이게 대체 무슨 에러인지 모르겠습니다... 검색도해보고에러메시지에서시킨대로도해봤는데 아무리해도없어지지가않아요ㅠㅜ 도와주십숑..
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
https 적용후 nginx 502 bad gateway 오류
안녕하세요, 제로초님. 배포 후 nginx가 502 bad gateway 오류가 발생했는데, 어제는 잘 되다가 오늘 갑자기 안되서 질문드립니다... 서버를 AWS lightsail을 이용하였고, nginx/letsencrypt를 사용하여 https를 적용하였습니다. nginx 부분은 블로그에 작성하신 내용을 참고하였고, default와 .conf 파일 은 다음과 같습니다. //etc/nginx/nginx.conf user www-data; worker_processes auto; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; events { worker_connections 768; # multi_accept on; } http { sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; gzip on; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; } /etc/nginx/sites-enabled/default server { listen 443 ssl; server_name apis.hometownalba.com; ssl_certificate /etc/letsencrypt/live/apis.hometownalba.com/fullchain.pem; # managed b y Certbot ssl_certificate_key /etc/letsencrypt/live/apis.hometownalba.com/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; location / { proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; user www-data; user www-data; } server { listen 443 ssl; server_name apis.hometownalba.com; ssl_certificate /etc/letsencrypt/live/apis.hometownalba.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/apis.hometownalba.com/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; location / { proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Real-IP $remote_addr; proxy_pass http://127.0.0.1:3065; proxy_redirect off; proxy_connect_timeout 300; proxy_send_timeout 300; proxy_read_timeout 300; } } 그리고 error log를 찍어보았는데, 다음과 같았습니다. 2021/11/10 05:36:35 [error] 1603#1603: *5 upstream prematurely closed connection while reading response header from upstream, client: 1.238.158.106, server: apis.hometownalba.com, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:3065/", host: "apis.hometownalba.com" 2021/11/10 05:39:37 [error] 1684#1684: *5 upstream prematurely closed connection while reading response header from upstream, client: 1.238.158.106, server: apis.hometownalba.com, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:3065/", host: "apis.hometownalba.com" 매번 답변 감사드립니다 ㅠㅠ
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
디버깅
[제로초 강좌 질문 필독 사항입니다]질문에는 여러분에게 도움이 되는 질문과 도움이 되지 않는 질문이 있습니다.도움이 되는 질문을 하는 방법을 알려드립니다.https://www.youtube.com/watch?v=PUKOWrOuC0c0. 숫자 0부터 시작한 이유는 1보다 더 중요한 것이기 때문입니다. 에러가 났을 때 해결을 하는 게 중요한 게 아닙니다. 왜 여러분은 해결을 못 하고 저는 해결을 하는지, 어디서 힌트를 얻은 것이고 어떻게 해결한 건지 그걸 알아가셔야 합니다. 그렇지 못한 질문은 무의미한 질문입니다.1. 에러 메시지를 올리기 전에 반드시 스스로 번역을 해야 합니다. 번역기 요즘 잘 되어 있습니다. 에러 메시지가 에러 해결 단서의 90%를 차지합니다. 한글로 번역만 해도 대부분 풀립니다. 그냥 에러메시지를 올리고(심지어 안 올리는 분도 있습니다. 저는 독심술사가 아닙니다) 해결해달라고 하시면 아무런 도움이 안 됩니다.2. 에러 메시지를 잘라서 올리지 않아야 합니다. 입문자일수록 에러메시지에서 어떤 부분이 가장 중요한 부분인지 모르실 겁니다. 그러니 통째로 올리셔야 합니다.3. 코드도 같이 올려주세요. 다만 코드 전체를 다 올리거나, 깃헙 주소만 띡 던지지는 마세요. 여러분이 "가장" 의심스럽다고 생각하는 코드를 올려주세요.4. 이 강좌를 바탕으로 여러분이 응용을 해보다가 막히는 부분, 여러 개의 선택지 중에서 조언이 필요한 부분, 제 경험이 궁금한 부분에 대한 질문은 대환영입니다. 다만 여러분의 회사 일은 질문하지 마세요.5. 강좌 하나 끝날 때마다 남의 질문들을 읽어보세요. 여러분이 곧 만나게 될 에러들입니다.6. 위에 적은 내용을 명심하지 않으시면 백날 강좌를 봐도(제 강좌가 아니더라도) 실력이 늘지 않고 그냥 코딩쇼 관람 및 한컴타자연습을 한 셈이 될 겁니다. 디버깅하는데 자꾸 오류가 나서 찾아봤는데 해결방법을 모르겠어요..
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
갑자기 궁금한게 생겻는데용
실무에서는 dispatch를 두가지 방법중 어떤방법으로 사용하는게 맞나요 ?
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
로그인 성공 시 페이지
로그인 성공 시 replace를 하는데 이때 로그인 페이지가 따로 있을 경우에 로그인 페이지로 접근하기 직전 페이지로 replace를 하고 싶은데 이전 페이지 url 을 얻는 방법을 아무리 서핑해봐도 모르겠네요. 어떻게 해야 얻을 수 있나요??
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
제로초님 죄송하지만 하나만 더 여쭤볼게요 ㅠ
프론트앤드에서 작업중에 nprogress 없애려고 _app.js에서 관련 코드를 삭제하고 반영이 잘 안되는것 같아서 .next 폴더를 지운후에 빌드했습니다. 그리고는 다시금 git을 통해 pull 했더니 우분투에서 에러가 납니다 해결을 위해 다시금 코드 살려보기도 하고 우분투 서버내에서 node_modules폴더 삭제하고 package-lock.json파일 삭제후에 다시금 npm install 통해 설치해보기도 했는데도 계속 에러나네요 ㅠ 혹시 해결방법을 아시는지요? 부탁드립니다 ㅠ
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
로그인이안되네요.
로그인하면 석세스안되고 대기중입니다.. 사가쪽에 입력한 이메일 받앗나확인하고 이부분하다가 passport local이랑 index다확인하고 비밀번호제거한값으로 user보내고 했는데 왜안되는지모르겟어요... 로그인 리퀘스트의 state를 확인하니 me부분이 null이라 이거때문인거같긴한데 그래서 사가부분에서 데이터 받앗나 확인한거였거든요 원인을 잘모르겟습니다. 노드 워닝 같이올릴게요.. [nodemon] 2.0.14 [nodemon] to restart at any time, enter `rs` [nodemon] watching path(s): *.* [nodemon] watching extensions: js,mjs,json [nodemon] starting `node app.js` 서버 실행중 Executing (default): CREATE TABLE IF NOT EXISTS `Users` (`id` INTEGER NOT NULL auto_increment , `email` VARCHAR(30) NOT NULL UNIQUE, `nickname` VARCHAR(30) NOT NULL, `password` VARCHAR(100) NOT NULL, `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci; Executing (default): SHOW INDEX FROM `Users` FROM `react-nodebird` Executing (default): CREATE TABLE IF NOT EXISTS `Posts` (`id` INTEGER NOT NULL auto_increment , `content` TEXT NOT NULL, `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, `UserId` INTEGER, `RetweetId` INTEGER, PRIMARY KEY (`id`), FOREIGN KEY (`UserId`) REFERENCES `Users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, FOREIGN KEY (`RetweetId`) REFERENCES `Posts` (`id`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci; Executing (default): SHOW INDEX FROM `Posts` FROM `react-nodebird` Executing (default): CREATE TABLE IF NOT EXISTS `Images` (`id` INTEGER NOT NULL auto_increment , `src` VARCHAR(200) NOT NULL, `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, `PostId` INTEGER, PRIMARY KEY (`id`), FOREIGN KEY (`PostId`) REFERENCES `Posts` (`id`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci; Executing (default): SHOW INDEX FROM `Images` FROM `react-nodebird` Executing (default): CREATE TABLE IF NOT EXISTS `Hashtags` (`id` INTEGER NOT NULL auto_increment , `name` VARCHAR(20) NOT NULL, `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci; Executing (default): SHOW INDEX FROM `Hashtags` FROM `react-nodebird` Executing (default): CREATE TABLE IF NOT EXISTS `Comments` (`id` INTEGER NOT NULL auto_increment , `content` TEXT NOT NULL, `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, `UserId` INTEGER, `PostId` INTEGER, PRIMARY KEY (`id`), FOREIGN KEY (`UserId`) REFERENCES `Users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, FOREIGN KEY (`PostId`) REFERENCES `Posts` (`id`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; Executing (default): SHOW INDEX FROM `Comments` FROM `react-nodebird` Executing (default): CREATE TABLE IF NOT EXISTS `Like` (`createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, `UserId` INTEGER , `PostId` INTEGER , PRIMARY KEY (`UserId`, `PostId`), FOREIGN KEY (`UserId`) REFERENCES `Users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN KEY (`PostId`) REFERENCES `Posts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci; Executing (default): SHOW INDEX FROM `Like` FROM `react-nodebird` Executing (default): CREATE TABLE IF NOT EXISTS `Follow` (`createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, `FollowingId` INTEGER , `FollowerId` INTEGER , PRIMARY KEY (`FollowingId`, `FollowerId`), FOREIGN KEY (`FollowingId`) REFERENCES `Users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN KEY (`FollowerId`) REFERENCES `Users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci; Executing (default): SHOW INDEX FROM `Follow` FROM `react-nodebird` Executing (default): CREATE TABLE IF NOT EXISTS `PostHashtag` (`createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, `PostId` INTEGER , `HashtagId` INTEGER , PRIMARY KEY (`PostId`, `HashtagId`), FOREIGN KEY (`PostId`) REFERENCES `Posts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN KEY (`HashtagId`) REFERENCES `Hashtags` (`id`) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci; Executing (default): SHOW INDEX FROM `PostHashtag` FROM `react-nodebird` db연결 성공 Executing (default): SELECT `id`, `email`, `nickname`, `password`, `createdAt`, `updatedAt` FROM `Users` AS `User` WHERE `User`.`email` = 'wjdgksak@naver.com';Executing (default): SELECT `User`.`id`, `User`.`email`, `User`.`nickname`, `User`.`createdAt`, `User`.`updatedAt`, `Posts`.`id` AS `Posts.id`, `Followings`.`id` AS `Followings.id`, `Followings->Follow`.`createdAt` AS `Followings.Follow.createdAt`, `Followings->Follow`.`updatedAt` AS `Followings.Follow.updatedAt`, `Followings->Follow`.`FollowingId` AS `Followings.Follow.FollowingId`, `Followings->Follow`.`FollowerId` AS `Followings.Follow.FollowerId`, `Followers`.`id` AS `Followers.id`, `Followers->Follow`.`createdAt` AS `Followers.Follow.createdAt`, `Followers->Follow`.`updatedAt` AS `Followers.Follow.updatedAt`, `Followers->Follow`.`FollowingId` AS `Followers.Follow.FollowingId`, `Followers->Follow`.`FollowerId` AS `Followers.Follow.FollowerId` FROM `Users` AS `User` LEFT OUTER JOIN `Posts` AS `Posts` ON `User`.`id` = `Posts`.`UserId` LEFT OUTER JOIN ( `Follow` AS `Followings->Follow` INNER JOIN `Users` AS `Followings` ON `Followings`.`id` = `Followings->Follow`.`FollowingId`) ON `User`.`id` = `Followings->Follow`.`FollowerId` LEFT OUTER JOIN ( `Follow` AS `Followers->Follow` INNER JOIN `Users` AS `Followers` ON `Followers`.`id` = `Followers->Follow`.`FollowerId`) ON `User`.`id` = `Followers->Follow`.`FollowingId` WHERE `User`.`id` = 1; (node:3728) UnhandledPromiseRejectionWarning: SequelizeDatabaseError: Unknown column 'Posts.UserId' in 'on clause' at Query.formatError (C:\index\nodeNest\back\node_modules\sequelize\lib\dialects\mysql\query.js:265:16) at Query.run (C:\index\nodeNest\back\node_modules\sequelize\lib\dialects\mysql\query.js:77:18) at processTicksAndRejections (internal/process/task_queues.js:97:5) (node:3728) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1) (node:3728) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. Executing (default): SELECT `id`, `email`, `nickname`, `password`, `createdAt`, `updatedAt` FROM `Users` AS `User` WHERE `User`.`email` = 'wjdgksak@naver.com';Executing (default): SELECT `User`.`id`, `User`.`email`, `User`.`nickname`, `User`.`createdAt`, `User`.`updatedAt`, `Posts`.`id` AS `Posts.id`, `Followings`.`id` AS `Followings.id`, `Followings->Follow`.`createdAt` AS `Followings.Follow.createdAt`, `Followings->Follow`.`updatedAt` AS `Followings.Follow.updatedAt`, `Followings->Follow`.`FollowingId` AS `Followings.Follow.FollowingId`, `Followings->Follow`.`FollowerId` AS `Followings.Follow.FollowerId`, `Followers`.`id` AS `Followers.id`, `Followers->Follow`.`createdAt` AS `Followers.Follow.createdAt`, `Followers->Follow`.`updatedAt` AS `Followers.Follow.updatedAt`, `Followers->Follow`.`FollowingId` AS `Followers.Follow.FollowingId`, `Followers->Follow`.`FollowerId` AS `Followers.Follow.FollowerId` FROM `Users` AS `User` LEFT OUTER JOIN `Posts` AS `Posts` ON `User`.`id` = `Posts`.`UserId` LEFT OUTER JOIN ( `Follow` AS `Followings->Follow` INNER JOIN `Users` AS `Followings` ON `Followings`.`id` = `Followings->Follow`.`FollowingId`) ON `User`.`id` = `Followings->Follow`.`FollowerId` LEFT OUTER JOIN ( `Follow` AS `Followers->Follow` INNER JOIN `Users` AS `Followers` ON `Followers`.`id` = `Followers->Follow`.`FollowerId`) ON `User`.`id` = `Followers->Follow`.`FollowingId` WHERE `User`.`id` = 1; (node:3728) UnhandledPromiseRejectionWarning: SequelizeDatabaseError: Unknown column 'Posts.UserId' in 'on clause' at Query.formatError (C:\index\nodeNest\back\node_modules\sequelize\lib\dialects\mysql\query.js:265:16) at Query.run (C:\index\nodeNest\back\node_modules\sequelize\lib\dialects\mysql\query.js:77:18) at processTicksAndRejections (internal/process/task_queues.js:97:5) (node:3728) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2) Executing (default): SELECT `id`, `email`, `nickname`, `password`, `createdAt`, `updatedAt` FROM `Users` AS `User` WHERE `User`.`email` = 'wjdgksak@naver.com';Executing (default): SELECT `User`.`id`, `User`.`email`, `User`.`nickname`, `User`.`createdAt`, `User`.`updatedAt`, `Posts`.`id` AS `Posts.id`, `Followings`.`id` AS `Followings.id`, `Followings->Follow`.`createdAt` AS `Followings.Follow.createdAt`, `Followings->Follow`.`updatedAt` AS `Followings.Follow.updatedAt`, `Followings->Follow`.`FollowingId` AS `Followings.Follow.FollowingId`, `Followings->Follow`.`FollowerId` AS `Followings.Follow.FollowerId`, `Followers`.`id` AS `Followers.id`, `Followers->Follow`.`createdAt` AS `Followers.Follow.createdAt`, `Followers->Follow`.`updatedAt` AS `Followers.Follow.updatedAt`, `Followers->Follow`.`FollowingId` AS `Followers.Follow.FollowingId`, `Followers->Follow`.`FollowerId` AS `Followers.Follow.FollowerId` FROM `Users` AS `User` LEFT OUTER JOIN `Posts` AS `Posts` ON `User`.`id` = `Posts`.`UserId` LEFT OUTER JOIN ( `Follow` AS `Followings->Follow` INNER JOIN `Users` AS `Followings` ON `Followings`.`id` = `Followings->Follow`.`FollowingId`) ON `User`.`id` = `Followings->Follow`.`FollowerId` LEFT OUTER JOIN ( `Follow` AS `Followers->Follow` INNER JOIN `Users` AS `Followers` ON `Followers`.`id` = `Followers->Follow`.`FollowerId`) ON `User`.`id` = `Followers->Follow`.`FollowingId` WHERE `User`.`id` = 1; (node:3728) UnhandledPromiseRejectionWarning: SequelizeDatabaseError: Unknown column 'Posts.UserId' in 'on clause' at Query.formatError (C:\index\nodeNest\back\node_modules\sequelize\lib\dialects\mysql\query.js:265:16) at Query.run (C:\index\nodeNest\back\node_modules\sequelize\lib\dialects\mysql\query.js:77:18) at processTicksAndRejections (internal/process/task_queues.js:97:5) (node:3728) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 3) 이건 git주소입니다. https://github.com/MaJunghan/Next.js-and-node 확인하시면 다시 private으로 변경하겠습니다.
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
안녕하세요 제로초님 배포후 에러가 발생해서 문의드립니다 ㅠ
이전과 다른 프로젝트를 만들었는데 또 같은 에러가 ㅠㅠ 처음 에러나는 부분이고 회원가입이나 다른 버튼 클릭시에는 cors, mixed contents 둘다 에러가 나네요 ㅠ app.js 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 userRouter = require('./routes/user'); const usersRouter = require('./routes/users'); const jobRouter = require('./routes/job'); const careerRouter = require('./routes/career'); const educationRouter = require('./routes/education'); const activityRouter = require('./routes/activity'); const awardRouter = require('./routes/award'); const certificationRouter = require('./routes/certification'); const certificationsRouter = require('./routes/certifications'); const languageRouter = require('./routes/language'); const projectRouter = require('./routes/project'); const socialRouter = require('./routes/social'); const comtestRouter = require('./routes/comtest'); const comtestsRouter = require('./routes/comtests'); const teamreviewRouter = require('./routes/teamreview'); const teamreviewsRouter = require('./routes/teamreviews'); const teamsearchRouter = require('./routes/teamsearch'); const skillRouter = require('./routes/skill'); const skillsRouter = require('./routes/skills'); const userskillRouter = require('./routes/userskill'); const jobsRouter = require('./routes/jobs'); const db = require('./models'); const passportConfig = require('./passport'); dotenv.config(); const app = express(); // db.sequelize.sync({ force: true }) db.sequelize.sync() .then(() => { console.log('db 연결 성공'); }) .catch(console.error); passportConfig(); //배포를 위한 setting if (process.env.NODE_ENV === "production") { app.use(morgan('combined')) app.use(hpp()); app.use(helmet()); app.use(cors({ origin: 'https://choono.co.kr', credentials: true, // 다른 주소간 cookie 전달 })); } else { // front --> backend 요청시 터미널에 송신상태 표현됨 app.use(morgan('dev')); app.use(cors({ origin: true, credentials: true, // 다른 주소간 cookie 전달 })); } // 업로드한 이미지 보이기 위한 작업 - 경로 맞추기 / static: 정적파일 제공 / join: 현 폴더명+uploads라는 이름을 합쳐 // '/': localhost:3065"/images"" --> Postform의 경로 참조 app.use('/', express.static(path.join(__dirname, 'uploads'))); // 자리위치 고정, front(saga)에서 받은 data를 req.body로 넘겨줌 / axios형태 // 즉, front(saga)에서 받은 data를 해석하여 req.body.email 등으로 변경하도록 도움 app.use(express.json()); // 일반 form형태 data 처리 app.use(express.urlencoded({ extended: true })); // 로그인시 front와 back이 같은 data를 갖고있어야 함 // 로그인시 db의 user정보를 다시 브라우저에 보내줄 때 비번: 보안위험요소 존재(암호화해서 cookie형태로 보냄) app.use(cookieParser(process.env.COOKIE_SECRET)); app.use(session({ saveUninitialized: false, resave: false, // proxy: true, // 배포시 secret: process.env.COOKIE_SECRET, // 암호화 cookie: { httpOnly: true, // secure: false, secure: true, // 배포시 domain: process.env.NODE_ENV === 'production' && '.choono.co.kr' } })); // passport 로그인시 활용 app.use(passport.initialize()); app.use(passport.session()); app.get('/', (req, res) => { res.send('hello express'); }) app.use('/user', userRouter); app.use('/users', usersRouter); app.use('/job', jobRouter); app.use('/career', careerRouter); app.use('/activity', activityRouter); app.use('/award', awardRouter); app.use('/certification', certificationRouter); app.use('/certifications', certificationsRouter); app.use('/language', languageRouter); app.use('/project', projectRouter); app.use('/social', socialRouter); app.use('/education', educationRouter); app.use('/comtest', comtestRouter); app.use('/comtests', comtestsRouter); app.use('/teamreview', teamreviewRouter); app.use('/teamreviews', teamreviewsRouter); app.use('/teamsearch', teamsearchRouter); app.use('/skill', skillRouter); app.use('/skills', skillsRouter); app.use('/userskill', userskillRouter); app.use('/jobs', jobsRouter); app.listen(3065, () => { console.log("서버 실행중!") }); config/config.js (프론트) export const backUrl = 'https://api.choono.co.kr'; // export const backUrl = "http://3.34.2.218"; // Ubuntu 빌드시 검토 // exports.backUrl = 'http://localhost:3065'; 코드작성에는 이상없다고 생각했는데 문제를 찾아봐도 해결방법이 나오질 않네요 ㅠㅠ api.도메인.co.kr로 들어가면 잘 작동하는 것 같습니다. 부탁드립니다 ㅠ pm2 모니터시에 처음엔 db연결 완료라고 나오는데 실행중에 아무것도 뜨지 않는 부분에서 문제가 있으려나 모르겠네요 ㅠ 이건 pm2 에러 확인입니다 프론트앤드 package.json { "name": "choono-front", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "next -p 3060", "build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 NODE_ENV=production ANALYZE=true next build", "start": "cross-env NODE_OPTIONS=--max-old-space-size=8192 NODE_ENV=production next start -p 3060" }, "author": "SehwanJun", "license": "ISC", "dependencies": { "@ant-design/icons": "^4.6.4", "@next/bundle-analyzer": "^11.1.2", "antd": "^4.3.0", "axios": "^0.21.4", "babel-plugin-styled-components": "^1.13.2", "cross-env": "^7.0.3", "immer": "^9.0.6", "moment": "^2.29.1", "nanoid": "^3.1.25", "next": "^9.5.5", "next-redux-wrapper": "^6.0.2", "nprogress": "^0.2.0", "pm2": "^5.1.2", "prop-types": "^15.7.2", "react": "^17.0.2", "react-dom": "^17.0.2", "react-quill": "^1.3.5", "react-redux": "^7.2.5", "react-tooltip": "^4.2.21", "redux": "^4.1.1", "redux-devtools-extension": "^2.13.9", "redux-saga": "^1.1.3", "styled-components": "^5.3.1" }, "devDependencies": { "babel-eslint": "^10.1.0", "eslint": "^7.32.0", "eslint-config-airbnb": "^18.2.1", "eslint-plugin-import": "^2.24.2", "eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-react": "^7.25.2", "eslint-plugin-react-hooks": "^4.2.0" } } 백앤드 package.json { "name": "choono-back", "version": "1.0.0", "description": "", "main": "app.js", "scripts": { "dev": "nodemon app", "start": "cross-env NODE_ENV=production pm2 start app.js" }, "author": "SehwanJun", "license": "ISC", "dependencies": { "aws-sdk": "^2.1022.0", "axios": "^0.24.0", "bcrypt": "^5.0.1", "cookie-parser": "^1.4.5", "cors": "^2.8.5", "cross-env": "^7.0.3", "dotenv": "^10.0.0", "express": "^4.17.1", "express-session": "^1.17.2", "helmet": "^4.6.0", "hpp": "^0.2.3", "morgan": "^1.10.0", "multer": "^1.4.3", "multer-s3": "^2.10.0", "mysql2": "^2.3.0", "passport": "^0.4.1", "passport-kakao": "^1.0.1", "passport-local": "^1.0.0", "passport-naver": "^1.0.6", "pm2": "^5.1.2", "sequelize": "^6.6.5", "sequelize-cli": "^6.2.0" }, "devDependencies": { "nodemon": "^2.0.12" } }
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
input 파일 업로드시 다른정보는 넘어가는데 file정보가 넘어가지 않는 현상
안녕하세요 개인작업중에 질문이있습니다. 서버와 통신중 백엔드 서버에 게시글 올리는 기능을 만드는데 다른 정보들은 넘어가는데 이미지 파일만 넘어가지 않는 현상이 있어서 질문드립니다. 통신 방법과 이미지 데이터 바꾸기 등을 하여도 넘어가지 않습니다. 코드입니다 import React, { useCallback, useEffect, useRef, useState } from 'react'; import Router from 'next/router'; import MainLayout from '../components/MainLayout'; import style from '../styles/css/upload.module.css'; import useInput from '../hooks/useInput'; import { useDispatch, useSelector } from 'react-redux'; import { ADD_POST_REQUEST, LOAD_POSTS_REQUEST, UPLOAD_IMAGES_REQUEST, } from '../reducers/post'; import { POST_CARD } from '../reducers/menu'; import axios from 'axios'; const Home = () => { const dispatch = useDispatch(); const { me } = useSelector((state) => state.user); const { mainPosts, addPostDone, imagePaths } = useSelector( (state) => state.post, ); const [photoToAddList, setPhotoToAddList] = useState([]); const [content, onChangeContent, setContetn] = useInput(); const [notice, onChangeNotice, setNotice] = useInput(false); const ref = useRef(); const handleResizeHeight = useCallback(() => { if (ref === null || ref.current === null) { return; } ref.current.style.height = '20px'; ref.current.style.height = ref.current.scrollHeight + 'px'; }, []); //댓글창 크기 자동조절 useEffect(() => { if (!me) { Router.push('/'); } }, [me]); const checkboxClick = useCallback(() => { setNotice((prev) => !prev); }, [notice]); const imageInput = useRef(); const onClickImageUpload = useCallback(() => { imageInput.current.click(); }, [imageInput.current]); // 이미지 파일 변수에 저장 const handleImage = useCallback( (e) => { const temp = []; const photoToAdd = e.target.files; for (let i = 0; i < photoToAdd.length; i++) { console.log(photoToAdd); temp.push({ id: photoToAdd[i].name, file: photoToAdd[i], url: URL.createObjectURL(photoToAdd[i]), }); } if (temp.length > 10) { return alert('최대개수 10개가 넘어갔습니다'); } if (temp.length + photoToAddList.length > 10) { return alert('최대개수 10개가 넘어갔습니다'); } if (photoToAddList.length > 10) { return alert('최대개수 10개가 넘어갔습니다'); } setPhotoToAddList(temp.concat(photoToAddList)); // setPhoto(temp.push(temp.forEach((v) => v))); }, [photoToAddList], ); const onRemove = useCallback( (deleteUrl) => { setPhotoToAddList(photoToAddList.filter((v) => v.url !== deleteUrl)); }, [photoToAddList], ); const upLoadFormClick = useCallback( (e) => { e.preventDefault(); if (!photoToAddList.length > 0) { alert('이미지를 등록해주세요'); return; } if (!content) { alert('내용을 등록해주세요'); return; } dispatch({ type: ADD_POST_REQUEST, data: { bo_writer: me.id, bo_content: content, bo_image: photoToAddList, }, }); dispatch({ type: LOAD_POSTS_REQUEST, data: { mem_id: me?.id, }, }); setTimeout(() => { if (addPostDone) { Router.push('/'); dispatch({ type: POST_CARD, }); } }, 1000); }, [photoToAddList, content, addPostDone], ); return ( <> <MainLayout> <div style={{ paddingTop: '24px' }}></div> <section className={style.a}> <article className={style.maxWidth}> <form encType="multipart/form-data" onSubmit={upLoadFormClick} className={style.upLoadForm} > {me?.grade === 'admin' && ( <div> <span>공지</span> <input name="mem_flag" type="checkbox" value={notice} onClick={checkboxClick} // required /> </div> )} <div className={style.imageBox}> {/* /분리 */} <ul> {photoToAddList ? photoToAddList.map((v) => { return ( <li key={v.url}> <div className={style.remove} onClick={() => onRemove(v.url)} > x </div> <img src={v.url} style={{ backgroundImage: `url(${v.url})`, }} /> </li> ); }) : null} <li onClick={onClickImageUpload}> <div className={style.imageInput}> <img src="/icon/addphoto.svg" className={style.addImg} /> </div> </li> </ul> </div> <input name="bo_image" type="file" accept="image/jpg, image/jpeg, image/png" ref={imageInput} onChange={handleImage} hidden multiple required /> <div className={style.textInput}> <textarea name="bo_content" type="text" placeholder="문구를 입력해주세요" ref={ref} onInput={handleResizeHeight} onChange={onChangeContent} maxLength={140} required /> <button>게시</button> </div> </form> </article> </section> <div style={{ paddingBottom: '44px' }}></div> </MainLayout> </> ); }; Home.propTypes = {}; export default Home; // 게시물 등록하기 function addPostAPI(data) { console.log(data, 'data'); return axios.post( `/board/insert.do?bo_writer=${data.bo_writer}&bo_content=${data.bo_content}&bo_image=${data.bo_image}`, data, ); } function* addPost(action) { try { const result = yield call(addPostAPI, action.data); console.log(result); yield put({ type: ADD_POST_SUCCESS, data: result.data, }); } catch (error) { console.error(error); yield put({ type: ADD_POST_FAILURE, data: error.response.data, }); } }
- 해결됨[리뉴얼] React로 NodeBird SNS 만들기
질문드립니다 getServerSideProps or getInitialProps
만약 모든 페이지에서 사용자 정보가 SSR되어야한다면 getServerSideProps보다 getInitalProps로 _app에다가 설정하는게 나을꺼 같은데 혹시 이 방법 말고 더 좋은 방법이 있을까 여쭤봅니다. getInitalProps는 레거시 코드니까 사용하지 않는 게 좋다는데 이거 말고 대안을 못 찾겠네요.ㅠㅠ 1. _app -> getInitalProps MyApp.getInitialProps = wrapper.getInitialAppProps( (store) => async ({ Component, ctx }) => { store.dispatch( setCredentials({ user: await axios .get("http://localhost:4000/users/me", { withCredentials: true, headers: { cookie: ctx.req?.headers.cookie || "", }, }) .then((response) => response.data) .catch(() => null), }) ); return { pageProps: { ...(Component.getInitialProps ? await Component.getInitialProps({ ...ctx, store }) : {}), pathname: ctx.pathname, }, }; } ); 2. pages -> getServerSideProps wrapper.getServerSideProps((store) => async (context) => { store.dispatch( setCredentials({ user: await axios .get("http://localhost:4000/users/me", { withCredentials: true, headers: { cookie: context.req.headers.cookie || "", }, }) .then((response) => response.data) .catch(() => null), }) ); return {props: {}}; });
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
제가 백엔드 sql port 번호설정을 잘못한거 같습니다..
영상을 보면 브라우저 3060 프론트 서버(Next) (3060) 백엔드 서버(express) (3065) MySQL(3306)라고 되어있는데 저는 제꺼는 프론트 서버는 3060이고 백엔드 서버는3000이고 MySQL 3306으로 들어가면 아래오류가 뜨고 3000번으로 들어가면 로그인이 됩니다. 어디서부터 잘못된 느낌이 들어서 질문올립니다.... 프론트 서버이고 백엔드 서버입니다. 그리고 백엔드 서버에서 port를 3000으로 맞춰줘야 db연결 성공이 떠서 3000으로 맞췄습니다..