묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
JPA Delete 동작이 궁금합니다.
안녕하세요. 좋은 강의를 제공해주신 덕분에 JPA를 열심히 공부하고 있습니다. JPA 사용 중에 궁금한 점이 있는데요 delete동작 방식을 보니, em.find로 entity를 조회 후에 em.remove순으로 query가 동작하고 있습니다. Mysql에서 null인 값을 조건절로 삭제해봐도 에러는 발생하지 않는데, JPA만의 특별한 이유가 있을까요? 두 번째로 궁금한 점도 있습니다ㅎㅎ JPA에서는 foreign key 제약조건을 위반하지 않기 위해서 모든 sql이 아래의 순서로 동작한다고 합니다. 1. Insert, in the order they were performed 2. Updates 3. Deletion of collection elements 4. Insertion of collection elements 5. Deletes, in the order they were performed 위의 조건으로 인해 하나의 transaction안에서 unique key걸린 값을 remove후 save하면 duplicate error가 발생하는데요. 혹시 이것도 JPA만의 특별한 이유가 있는지 너무너무 궁금합니다!
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
회원 가입 할때 에러나는 부분들이 있어서여
안녕하세여 john ahn 님 저 ㅈㅅ한데 처음부터 강의를 다시 듣는중인데 이부분에서 다시 에러가 나서여 저번에 알려주셨던것도 같은데 좀 되서 잊어버렸어요 ㅈㅅ 회원 가입한뒤에 몽고 디비에서 다음과 같이 확인이 되고 회원가입 두번째 시도에 에러가 발생해서여 왜 그런지 알려주시면 대단히 감사여postman의 메세지는 result: { "success": false, "err": { "driver": true, "name": "MongoError", "index": 0, "code": 11000, "keyPattern": { "email": 1 }, "keyValue": { "email": null } } } 몽고 디비의 저장 형식도 좀 이상하고 두번째 회원 가입이 실패하는것도 이해가 안가여 아이디를 바꿔서 회원 가입 해도 두번째부터 에러가 발생해여
-
미해결프로그래밍 시작하기 : 파이썬 입문 (Inflearn Original)
설치오류
파이썬이랑 아톰 설치는 되는데 아톰에서 autocomplete-python, script가 다운이 안되고 deprecated라고 뜨네요..
-
미해결웹 게임을 만들며 배우는 자바스크립트
children이 호출이 안되요ㅠㅠ
안녕하세요 선생님 강의랑 조금 다른 방식으로 btn.addEventListener("click", makeArray); 에서 table안에 tr, td 만드는 makeArray함수호출하고 (참고로 tbody같은 html요소들은 makeArray밖의 맨위에 이미 특정해놨어요) 이 함수안에서 randomNumberForDigging(horiz, verti, numMine);로 폭탄위치정할 랜덤 Array 만드는 함수 호출을 하는데 이상한것이 makeArray함수에서는 tbody.children[특정n]하면 호출되는데 randomNumberForDigging이 함수에서는 호출이 안되요. 근데 randomNumberForDigging여기서 console.log(tbody.children[특정n])은 undefined인데 console.log(tbody.children) 은 htmlcollection이라며 호출이 되요..이틀동안 원인을 찾고있는데 모르겠어요ㅠㅠ
-
데브옵스(DevOps)를 위한 쿠버네티스 마스터
GCP, 쿠버네티스 질문입니다!!
삭제된 글입니다
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
로그인 시도중 backend 에서 에러가 발생하면서 로그인이 되지 않습니다. 작성한 코드는 강사님이 작성하신 코드와 차이가 없는것 같습니다.
login(option) login(Post) 아래는 backend - log 입니다. Executing (default): SELECT `id`, `email`, `nickname`, `password`, `createdAt`, `updatedAt` FROM `Users` AS `User` WHERE `User`.`email` = 'test@test.com'; Executing (default): INSERT INTO `Users` (`id`,`email`,`nickname`,`password`,`createdAt`,`updatedAt`) VALUES (DEFAULT,?,?,?,?,?); Executing (default): SELECT `id`, `email`, `nickname`, `password`, `createdAt`, `updatedAt` FROM `Users` AS `User` WHERE `User`.`email` = 'test@test.com'; (node:11018) UnhandledPromiseRejectionWarning: Error: Include unexpected. Element has to be either a Model, an Association or an object. at Function._conformInclude (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:383:11) at /Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:319:59 at Array.map (<anonymous>) at Function._conformIncludes (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:319:39) at Function._baseMerge (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:786:10) at Function._defaultsOptions (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:823:17) at Function._injectScope (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:3224:10) at Function.findAll (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:1694:10) at Function.findOne (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:1905:23) at /Users/imac/Desktop/nodebird study/back/routes/user.js:25:56 (node:11018) 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(). (rejection id: 2) (node:11018) [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. 에러 메세지를 읽은 결과... 원인이 두가지로 생각되는데요 1. routes/user.js 에 route /login 부분의 요소가 연관 모델이 아니다. 2. routes/user.js 에 route /login 함수를 try catch 로 묶어 줘라. 제가 이해한것이 맞는지 모르겠네요.. routes/user.js const express = require('express'); const bcrypt = require('bcrypt'); const passport = require('passport'); const { User, Post } = require('../models'); const router = express.Router(); // 로그인 login // 미들웨어 확장 router.post('/login', (req, res, next) => { passport.authenticate('local', (err, user, info) => { // 서버 에러, 성공, 클라이언트 에러 if (err) { console.error(err); return next(err); } if (info) { return res.status(401).send(info.reasone); // 401: 허가되지 않음 , 403: 금지 } return req.login(user, async (loginErr) => { // passport login error 시 if (loginErr) { console.error(loginErr); return next(loginErr); } const fullUserWithoutPassword = await User.findOne({ where: { id: user.id }, // attributes: ['id', 'nickname','email'], attributes: { exclude: ['password'] }, include: [{ model: Post, attributes: ['id'], }, { medel: User, as: 'Followings', attributes: ['id'], }, { model: User, as: 'Followers', attributes: ['id'], }] }) // res.setHeader('Cookie', 'cxlhy') return res.status(200).json(fullUserWithoutPassword); }); })(req, res, next); }); // 로그아웃 logout router.post('/logout', (req, res) => { req.logout(); req.session.destroy(); // session 에 저장된 쿠키와 id 를 지운다. res.send('ok'); // 로그아웃 성공 }); // 회원가입 signup router.post('/', async (req,res, next) => { // POST /user try { const exUser = await User.findOne({ where: { email: req.body.email, } }); if (exUser) { return res.status(403).send('이미 사용 중인 아이디입니다.'); // 응답 } const hashedPassword = await bcrypt.hash(req.body.password, 12); // 10 ~ 13 - 해쉬화 한다. await User.create({ email: req.body.email, nickname: req.body.nickname, password: hashedPassword, }); // res.json(); // res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000'); // res.setHeader('Access-Control-Allow-Origin', '*'); res.status(200).send('ok'); // res.status(200).send('ok'); 응답 } catch(error) { console.error(error); next(error); // status 500 } }); // router.delete('/', (req,res) => { // DELETE /user // res.json({id: 1 }); // }); module.exports = router; 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 postAPIRouter = require('./routes/post'); const userAPIRouter = require('./routes/user'); const db = require('./models'); const passportConfig = require('./passport'); dotenv.config(); const app = express(); db.sequelize.sync() .then(() => { console.log('db 연결 성공'); }) .catch(console.error); passportConfig(); app.use(cors({ // origin: 'https://nodebird.com', // https://nodebird.com 에서 온 요청만 허용하겠다. origin: '*', // 모든 요청 허용 // credentials: false, // })); app.use(express.json()); // front server 에서 json 형식으로 데이터를 보냈을때 req.body 안에 data를 넣어준다. app.use(express.urlencoded({ extended: true})); // from submit 했을때 urlencoded 방식으로 변환해준다. 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', postAPIRouter); app.use('/user', userAPIRouter); app.listen(3065, () => { console.log('서버 실행 중') }); models/user.js module.exports = (sequelize, DataTypes) => { const User = sequelize.define('User', { // Mysql에는 users 테이블 생성 // id가 기본적으로 들어있다. email: { type: DataTypes.STRING(30), // INTEGER: 정수, FLOAT: 소수(실수) BOOLEAN, FLOAT allowNull: false, // 필수 unique: true, // 고유한 값 }, nickname: { type: DataTypes.STRING(30), allowNull: false, // 필수 }, password: { type: DataTypes.STRING(100), allowNull: false, // 필수 }, }, { charset: 'utf8', collate: 'utf8_general_ci' // 한글 저장 }); User.associate = (db) => { db.User.hasMany(db.Post); db.User.hasMany(db.Comment); // Liked user 가 좋아요를 누른 post 를 가져온다.. db.User.belongsToMany(db.Post, { through: 'Like', as: 'Liked' }); db.User.belongsToMany(db.User, { through: 'Follow', as: 'Followers', foreignKey: 'FollowingId'}); db.User.belongsToMany(db.User, { through: 'Follow', as: 'Followings', foreignKey: 'FollowerId'}); }; return User; models/post.js module.exports = (sequelize, DataTypes) => { const Post = sequelize.define('Post', { // Mysql에는 posts 테이블 생성 // id가 기본적으로 들어있다. content: { type: DataTypes.TEXT, allowNull: false, }, // RetweetId }, { charset: 'utf8mb4', collate: 'utf8mb4_general_ci' // 이모티콘 저장 }); Post.associate = (db) => { db.Post.belongsTo(db.User); db.Post.belongsToMany(db.Hashtag, { through: 'PostHashtag'} ); db.Post.hasMany(db.Comment); db.Post.hasMany(db.Image); // user post 테이블간에 like 테이블이 생기고.. as 에 따라서 post.getLikers 처럼 게시글 좋아요.. 누른 user 를 가져온다. // Likers 좋아요를 누른 user 를 가져온다. db.Post.belongsToMany(db.User, { through: 'Like', as: 'Likers' }); db.Post.belongsTo(db.Post, { as: 'Retweet' }) }; return Post; } models/comment.js module.exports = (sequelize, DataTypes) => { const Comment = sequelize.define('Comment', { // Mysql에는 comments 테이블 생성 // id가 기본적으로 들어있다. content: { type: DataTypes.TEXT, allowNull: false, }, // UserId: 1 // PostId: 1 }, { charset: 'utf8mb4', collate: 'utf8mb4_general_ci' // 한글 저장 }); Comment.associate = (db) => { db.Comment.belongsTo(db.User); db.Comment.belongsTo(db.Post); }; return Comment; } sagas/user.js import { all, put, fork, takeLatest, delay, call } from 'redux-saga/effects'; import axios from 'axios'; import { LOG_IN_REQUEST, LOG_IN_SUCCESS, LOG_IN_FAILURE, LOG_OUT_REQUEST, LOG_OUT_SUCCESS, LOG_OUT_FAILURE, SIGN_UP_REQUEST, SIGN_UP_SUCCESS, SIGN_UP_FAILURE, FOLLOW_REQUEST, FOLLOW_SUCCESS, FOLLOW_FAILURE, UNFOLLOW_REQUEST, UNFOLLOW_SUCCESS, UNFOLLOW_FAILURE, } from '../reducers/user'; function followAPI(data) { return axios.post('/api/follow', data); } function* follow(action) { try { // yield put({ // type: 'FOLLOW_REQUEST', // }); // const result = yield call(followAPI, action.data); // ex> const result = yield call(logInAPI, action.data, a, b, c); a, b, c 인자를 추가시 yield delay(1000); // throw new Error('') // 아래 catch 로 넘어간다. yield put({ type: FOLLOW_SUCCESS, data: action.data, }); } catch (err) { yield put({ // put => dispatch 다. type: FOLLOW_FAILURE, data: err.response.data, }); } } function unfollowAPI(data) { return axios.post('/api/unfollow', data); } function* unfollow(action) { try { // yield put({ // type: 'UNFOLLOW_REQUEST', // }); // const result = yield call(unfollowAPI, action.data); // ex> const result = yield call(logInAPI, action.data, a, b, c); a, b, c 인자를 추가시 yield delay(1000); // throw new Error('') // 아래 catch 로 넘어간다. yield put({ type: UNFOLLOW_SUCCESS, data: action.data, }); } catch (err) { yield put({ // put => dispatch 다. type: UNFOLLOW_FAILURE, data: err.response.data, }); } } function signUpAPI(data) { return axios.post( '/user', data); // localhostUrl ( http://localhost:3065 ) + /user } function* signUp(action) { try { // yield put({ // type: 'LOG_IN_REQUEST', // }); const result = yield call(signUpAPI, action.data); // ex> const result = yield call(logInAPI, action.data, a, b, c); a, b, c 인자를 추가시 // yield delay(1000); // throw new Error('') // 아래 catch 로 넘어간다. console.log(result); yield put({ type: SIGN_UP_SUCCESS, // data: result.data, }); } catch (err) { console.error(err); yield put({ // put => dispatch 다. type: SIGN_UP_FAILURE, data: err.response.data, }); } } function logOutAPI() { return axios.post('/api/logout'); } function* logOut() { try { // yield put({ // type: 'LOG_OUT_REQUEST', // }); // const result = yield call(logOutAPI); yield delay(1000); yield put({ type: LOG_OUT_SUCCESS, }); } catch (err) { yield put({ // put => dispatch 다. type: LOG_OUT_FAILURE, error: err.response.data, }); } } function logInAPI(data) { return axios.post('/user/login', data); } function* logIn(action) { try { console.log('saga logIn'); // yield put({ // type: 'LOG_IN_REQUEST', // }); const result = yield call(logInAPI, action.data); console.log(result); // ex> const result = yield call(logInAPI, action.data, a, b, c); a, b, c 인자를 추가시 // yield delay(1000); yield put({ type: LOG_IN_SUCCESS, data: result.data, }); } catch (err) { console.error(err); yield put({ // put => dispatch 다. type: LOG_IN_FAILURE, error: err.response.data, }); } } function* watchFollow() { yield takeLatest(FOLLOW_REQUEST, follow); // take =>logIn 액션이 실행될때까지 기다리겠다. } function* watchUnFollow() { yield takeLatest(UNFOLLOW_REQUEST, unfollow); // take =>logIn 액션이 실행될때까지 기다리겠다. } function* watchLogIn() { yield takeLatest(LOG_IN_REQUEST, logIn); // take =>logIn 액션이 실행될때까지 기다리겠다. } function* watchLogOut() { yield takeLatest(LOG_OUT_REQUEST, logOut); } function* watchSignUp() { yield takeLatest(SIGN_UP_REQUEST, signUp); // take =>logIn 액션이 실행될때까지 기다리겠다. } export default function* userSaga() { yield all([ fork(watchFollow), fork(watchUnFollow), fork(watchLogIn), fork(watchLogOut), fork(watchSignUp), ]); } sagas/index.js // all fork call put delay debounce throttle takeLatest tabkeEvery takeLeding taekMaybe import { all, fork } from 'redux-saga/effects'; import axios from 'axios'; import postSaga from './post'; import userSaga from './user'; import { localhostUrl } from '../config/config'; axios.defaults.baseURL = localhostUrl; export default function* rootSaga() { yield all([ // all 은 배열을 받아서 배열안에 있는 명령들을 한번에 실행 시켜준다. fork(postSaga), fork(userSaga), ]); }; front/config/config.js export const domainUrl = 'http://api.nodebird.com'; export const localhostUrl = 'http://localhost:3065';
-
미해결Vue.js 끝장내기 - 실무에 필요한 모든 것
안녕하세요. 질문이 있습니다.
태그 작성하고 저장하면 자동적으로 포멧팅 하는데 br, img, input 들이 뒤에 /가 붙어서 나오더라구요.. <br/> <img/> <input/> 이렇게요~ 해당 기능을 끌 수 있을까요?? 확인 부탁 드립니다. 감사합니다.
-
미해결홍정모의 따라하며 배우는 C++
random shuffle이 안되는데 이유를 모르겠습니다.
#include <iostream> #include <vector> #include <algorithm> using namespace std; class Cents { private: int m_cents; public: Cents(int cents = 0) { m_cents = cents; } int getCents() const { return m_cents; } int& getCents() { return m_cents; } friend std::ostream& operator << (std::ostream& out, const Cents& cents) { out << cents.m_cents; return out; } }; int main() { vector<Cents> arr(20); for (unsigned i = 0; i < 20; ++i) { arr[i].getCents() = i; } std::random_shuffle(begin(arr), end(arr)); for (auto& e : arr) { cout << e << " "; } cout << endl; return 0; } 강의 내용 그대로 친 것 같은데 random 셔플부분만 std에 존재하지 않는다고 계속 에러나네요.
-
해결됨스프링과 JPA 기반 웹 애플리케이션 개발
엔티티에 저장이 안되는 문제에 대한 문의
안녕하세요. 강의 잘 보았습니다. 강의 도움 받아서 테스트 진행해보고 있는데요. 저장이 안되는 부분에 대해 문의 드려봅니다. Car, Camp 엔티티가 있고 Car 전체 데이터 읽어서 특정 필드의 값을 Camp 에서 찾아서 업데이트하는 로직입니다. if (carRepository.count() > 0) { carRepository.findAll().stream().forEach(s -> { String campName = s.getCampEngName(); Optional<Car> car = carRepository.findById(s.getId()); Camp camp = campRepository.findByEngName(campName); if (camp != null) { car.ifPresent(m -> m.setNote(camp.getKorName())); } });} 해당 부분 코드는 이렇게 했는데, 수행 후에 실제 Car 엔티티의 note 값이 변경이 안되어있습니다. 로그 찍어보면 campName 값은 일일이 잘 가져오고 있는데 setNote로 저장이 안됩니다. 트랜젝션 문제일까요? 강의를 제대로 소화를 못했는지 원인을 못찾겠네요. ㅠㅠ 도움 부탁드립니다. 아.. 저게 수행되는 곳이, 일반 컨트롤러 통해서 들어오는게 아니라 최초 실행시점입니다.(혹시 이게 문제일까요?) @PostConstruct public void initCarData() throws IOException { ... if (carRepository.count() > 0) { } ... } 이 부분입니다.
-
미해결홍정모의 따라하며 배우는 C언어
디버깅에 대하여
강의를 따라 해보는데 강의처럼 구현이 되지 않습니다. 어떻게 해야 될까요.
-
미해결쉽고 자연스럽게 배워보는 Javascript 입문 - 코드스쿼드 마스터즈 코스 레벨1
질문은 아니구 5:40 쯤 수정하실때
(에디터마다 상이하겠지만 서브라임 텍스트 기준) - , * , / 두개씩 수정하시는 부분 1. 첫번째 '-' 옆에 커서 넣고 2. ctrl 키 3. 두번째 '-' 옆에 커서 넣고 수정하시면 한번에 수정가능해요! 업무나 기타 프로그램 이용에 참고하세요~~~ -지나가던 웹디 + 초보 퍼블리셔-
-
미해결홍정모의 따라하며 배우는 C언어
소수끼리의 몫과 나머지
예를들어 5.4 나누기 1.05의 몫과 나머지를 구하는 연산자는 뒤에 나오나요? (while 문으로 계속해서 빼는 방식으로 프로그램을 만들 수는 있어보이네요)
-
미해결현존 최강 크롤링 기술: Scrapy와 Selenium 정복
scrapy shell
scrapy shell로 해서 하나하나 response 결과를 확인할때는 잘 파싱되서 결과값이 나오는데, 전체 scrapy를 생성해서 crawl 돌리면 400 HTTP status code is not handled or not allowed 이 나는건 왜 때문인가요...?
-
윤재성의 만들면서 배우는 Spring MVC 5
이미지의 경로
삭제된 글입니다
-
미해결파이썬 알고리즘 문제풀이 입문(코딩테스트 대비)
sum1과 sum2 초기화 과정에 대한 문의
안녕하세요 선생님 명쾌한 강의를 해주셔서 항상 감사합니다. 다름이 아니오라 sum1과 sum2 초기화 과정에 대한 과정에 대해 질문드릴 사항이 한가지 있습니다. 사진에서 표기한 2)인 대각선을 위한 sum1과 sum2의 초기화 과정이 1)의 과정과 달리 for반복문 밖에 작성하는지궁금합니다. 실제로 대각선을 구하는 for안에 넣어보니 -1이 된 154가 출력되는 것을 확인할 수 있었습니다. 어떠한 이유때문에 155가 아닌 154출력 되었으며 어째서 for문 안이 아닌 밖에서 초기화 과정이 이루어지는지 궁금합니다.
-
미해결현존 최강 크롤링 기술: Scrapy와 Selenium 정복
scrapt shell re() 정규표현 적용시 에러
강사님이 알려주신데로 re를 쓰게되면 이런 에러가 나는데 방법이 있을까요...?
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
선생님의 github 예시로 가입/로그인을 해도 에러가 납니다.
안녕하세요. 제가 작업한 작업물에서 오류를 해결하지 못해서 선생님의 작업물을 받아서 돌려보았는데요, 추가한 건 dev.js(제가 쓰던 파일을 그대로 복사해서 사용했습니다.) root와 cilent애 전부 npm install 해주었고, 추가로 bcrypt 오류가 떠서 npm install bcrypt --save 해주었는데, 콘솔창에서 에러가 뜨지는 않지만, 알림창으로 Failed to sign up이라고 뜨는 것으로 보아 dispatch(registerUser(body)) .then(response => { if (response.payload.success) { props.history.push("/login") } else { alert("Failed to sign up") } }) 이 부분에서 계속 돌고 있는 것 같습니다. 다른 분들은 질문을 하시지 않은 것으로 봐서 제 로컬 문제 같은데요... 리덕스 구축할 때 혹시 로컬에서 확인해야 할 부분이 있으면 다시 짚어주시면 감사하겠습니다.
-
미해결프로그래밍 시작하기 : 파이썬 입문 (Inflearn Original)
튜플 리스트로 형 변환 활용
튜플을 리스트로형 변환 해서 튜플 값을 수정하거나 삭제하는 코드를 간단하게 보여주실 수 있을까요? 지금 막 해보는데 잘 안되네요..ㅠㅠ
-
미해결인터랙티브 웹 개발 제대로 시작하기
키다운-업 연속 시 캐릭터에 .running class
안녕하세요 강사님. 26강까지 다 듣고, 강사님이 주신 원본이랑 비교까지 다 했는데도 궁금한 점이 있어서요! 다름이아니라, 제 파일에서 키다운 이벤트 시, 키코드 37번과 39번은 문제없이 작동하는데, 위 아래 키보드를 클릭하면 running클래스가 랜덤하게 작동합니다. 1. forward 시에 running클래스 정상작동, 얼마 안가서 backward시 running이 붙지 않고, 돌아옵니다. 2. forward로 끝까지 갔다가 backward시에는 running이 붙었다가 중간에 또 forward와 backward를 반복하면 running이 붙지 않은채 움직입니다. 원본 파일에서 개발자 코드를 켜놓고 character 클래스를 볼 때도, forward에는 running이 붙다가 backward에는 running이 붙지 않고 돌아오는데, 이 부분 해결방법 여쭤봅니다. 저는 크롬이랑, 웨일에서 개발자도구를 실행시켰습니다. 감사합니다!
-
미해결페이스북 클론 - full stack 웹 개발
댓글 순서
안녕하세요 강사님! 강의 잘 듣고 있습니다. 질문은 아니고 그냥 제가 생각했던 문제가 해결되어서 남겨봅니다. 동영상 끝부분에 댓글을 달아서 보여주시는 부분을 하다가, 새로운 댓글들이 위쪽으로 달리는 것을 보고 이상하게 느꼈습니다. 대부분이 새로운 댓글들이 아래로 달리지 않나 합니다. 그래서 찾아본 결과 post_list.html 파일에 for문, 즉 {% for comment in post.comment_set.all %} 이 부분에서 끝에 reversed 를 달아 {% for comment in post.comment_set.all reversed %} 이런식으로 바꾸면 for문이 반대로 돌아 댓글들 순서가 반대로 되어 순차적으로 댓글들이 달리게 됩니다. 그리고 insertAdjacentHTML에서 'afterend'를 쓰니 제 마음에 딱 드는 방식으로 바뀌게 되었습니다. 더 좋은 방법이 있다면 알려주세요! 혹시나 저처럼 이상하게 생각하신 분들이 있을까봐 질문 남겨요 :)