묻고 답해요
161만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
섹션 22부터 새로 개정된 강의라고 하는데, 어떻게 들어야 할까요?
안녕하세요, 금일 (10월 28일) 강의를 시작한 학생입니다.어떻게 강의를 들어야 하는지 헷갈려서 문의드려요.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
섹션 31 댓글 기능 구현 과제 관련 질문
안녕하세요 섹션 31 댓글 기능 구현 과제 중 궁금한 점이 있어 질문 남깁니다 댓글 리스트의 수정 아이콘 클릭 시 사진과 같은 화면이 나오도록 했고, 댓글 등록하기 presenter component를 재사용 했습니다댓글 리스트 presenter 파일입니다export default function CommentListUI(props) { return ( <S.Wrapper> {props.data?.fetchBoardComments.map((item) => ( <S.CommentListWrapper key={item._id}> {props.isEdit && props.commentId === item._id ? ( <CommentWriteUI></CommentWriteUI> ) : ( <S.Comment_Container> <S.profile_icon src="/02/profile_icon.png"></S.profile_icon> <S.Content_container> <S.Name_Star_container> <S.Text style={{ fontWeight: "600" }}>{item.writer}</S.Text> <S.ReviewStar_container style={{ marginLeft: "16px" }}> <S.StarDiv></S.StarDiv> <S.StarDiv></S.StarDiv> <S.StarDiv></S.StarDiv> <S.StarDiv></S.StarDiv> <S.StarDiv></S.StarDiv> </S.ReviewStar_container> </S.Name_Star_container> <S.Text style={{ marginTop: "-15px", fontWeight: "500" }}> {item.contents} </S.Text> <S.Text style={{ fontSize: "12px", fontWeight: "400", color: "#BDBDBD", }} > {getDate(item.createdAt)} </S.Text> </S.Content_container> <S.Icon_container> <S.Icon style={{ backgroundImage: `url("/createComment.png")` }} onClick={() => props.onClickTEST(item._id)} ></S.Icon> <S.Icon style={{ backgroundImage: `url("/clear.png")` }} onClick={() => props.onClickDelete(item._id)} ></S.Icon> </S.Icon_container> </S.Comment_Container> )} </S.CommentListWrapper> ))} </S.Wrapper> ); } 삼항연산자를 사용해 나오는 화면을 다르게 했습니다isEdit 변수는 수정하기 아이콘 클릭 시 true로 바뀌고, 삼항연산자 조건에 isEdit 변수만 사용하니 수정 아이콘을 클릭하지 않은 다른 댓글 리스트가 사라지면서 재사용한 댓글 등록 presenter 파일만 화면에 나와서 조건은 위와 같이 작성했습니다 여기서 문제는 수정 아이콘을 클릭해 나오는 댓글 등록 창은 container 파일에 작성한 함수가 작동하지 않는 것입니다 댓글 리스트 container 파일입니다export default function CommentList() { const { data } = useQuery(FETCH_COMMENTS); const [deleteBoardComment] = useMutation(DELETE_COMMENTS); const onClickDelete = async (item) => { const pw = prompt("비밀번호를 입력해주세요."); try { await deleteBoardComment({ variables: { pw: pw, boardCommentId: item, }, refetchQueries: [{ query: FETCH_COMMENTS }], }); alert("삭제되었습니다."); } catch (error) { alert(error.message); } }; // 수정하기 아이콘 클릭 시 화면 변화 const [isEdit, setIsEdit] = useState(false); const [commentId, setCommentId] = useState(); const onClickTEST = (item) => { setIsEdit(true); setCommentId(item); }; // console.log(commentId); return ( <CommentListUI data={data} onClickDelete={onClickDelete} onClickTEST={onClickTEST} isEdit={isEdit} commentId={commentId} ></CommentListUI> ); } 댓글 등록 container 파일입니다 const [updateBoardComment] = useMutation(UPDATE_BOARD_COMMENT); const onClickUpdate = () => { // updateBoardComment({ // variables: { // updateBoardCommentInput: { // contents: contents, // rating: 0 // }, // password: pw, // boardCommentId: // } // }) console.log("Test"); }; return ( <> <CommentWriteUI onChangeWriter={onChangeWriter} onChangePw={onChangePw} onChangeContents={onChangeContents} onClickUpdate={onClickUpdate} ></CommentWriteUI> </> ); } onClickUpdate 함수는 댓글 작성 presenter 파일의 등록하기 버튼에 연결되어 있습니다상세 페이지 로딩 시 나오는 댓글 등록창은 버튼 클릭 시 콘솔이 제대로 나오는데댓글 리스트 수정 아이콘을 눌러 나오는 댓글 등록창에서는 버튼을 눌러도 콘솔 자체가 나오지 않습니다 댓글 과제 가이드를 확인해서 어떻게 수정하면 좋을지는 알았지만, 궁금한 점이 해소되지 않네요궁금한 점은삼항연산자, map 등 기능의 속성을 제대로 알지 못한 채 사용한 문제인지코드 자체를 잘못 작성한 것인지 추가로 rating(별점) 데이터 활용법에 대한 힌트를 얻고 싶습니다rating 값 1 = 별 1개 인가요? rating 숫자 데이터가 별과 어떻게 연결되는지 잘 모르겠습니다 부족한 점이 많아 질문이 너무 길어졌네요 항상 감사합니다
-
미해결코로나맵 개발자가 알려주는 React + Express로 지도서비스 만들기 (Typescript)
지도가 두개가 열리는 것 같습니다
보시면 하나의 지도 div에 두개가 열리는 것 같습니다.실제로 지도가 두개가 열려 서로 level이 달라 겹치는 모습입니다. 뒷장의 지도에는 마커가 표기되지 않습니다.아래는 맵과 관련된 코드들입니다.mern_client/src/components/common/Map/index.tsximport React, { useEffect } from 'react'; interface MapProps { width: string; height: string; initMap?: (map: naver.maps.Map) => void; } function Map({width, height, initMap}: MapProps) { useEffect(() => { const mapOptions = { center: new naver.maps.LatLng(37.3595704, 127.105399), zoom: 10 }; const map = new naver.maps.Map('map', mapOptions); if (initMap){ initMap(map); } }, []); return <div id="map" style={{width, height}}></div>; } export default Map; mern_client/src/components/MapContainer.tsximport { useSetAtom } from "jotai"; import React from 'react'; import Map from './common/Map'; import { mapAtom } from "../atoms/map"; function MapContainer() { const setMap = useSetAtom(mapAtom); const initMap = (map: naver.maps.Map) => { setMap(map); naver.maps.Event.addListener(map, 'click', () => { console.log("맵 클릭"); }); }; return <Map width="100%" height='100%' initMap={initMap}/> }; export default MapContainer; mern_client/src/atoms/map.tsimport { atom } from 'jotai'; export const mapAtom = atom<naver.maps.Map | null>(null);
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
AWS 배포 서버 관련 문의드립니다....
혹시 서버가 2개가 생성된 이유가 뭘까요..?
-
해결됨mongoDB 기초부터 실무까지(feat. Node.js)
updateMany에서 user._id를 못찾는 상황
강좌대로 Blog.updateMany({ "user._id": userId }, { "user.name": name })로 하니 블로그 데이터 유저 정보가 변경이 계속 안되고 있습니다 ㅠㅠ 유저 데이터는 정상적으로 변경이 되었는데요 문제점을 모르겠습니다.해당 코드 깃허브 : https://github.com/alinfanclub/KimDevlogServer/blob/updateMany/src/routes/userRouter.js userRouter.put("/:userId", async (req, res) => { try { const { userId } = req.params; if (!mongoose.isValidObjectId(userId)) return res.status(400).send({ err: "invalid userId" }); const { age, name } = req.body; if (!age && !name) return res.status(400).send({ err: "age or name is required" }); if (age && typeof age !== "number") return res.status(400).send({ err: "age must be a number" }); if (name && typeof name.first !== "string" && typeof name.last !== "string") return res.status(400).send({ err: "first and last name are strings" }); // let updateBody = {}; // if(age) updateBody.age = age; // if(name) updateBody.name = name; // const user = await User.findByIdAndUpdate(userId, updateBody, { new: true }); let user = await User.findById(userId); if (age) user.age = age; if (name) { user.name = name; await Blog.updateMany({ "user._id": userId }, { "user.name": name }); } await user.save(); return res.send({ user }); } catch (err) { console.log(err); return res.status(500).send({ err: err.message }); } });
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
SSH 콘솔 sql 설치 오류문의합니다.
sudo dpkg -i mysql-apt-config_0.8.23-1>_all.deb를 입력하면 error가 발생하는데.. 어떻게 해결할 수 있을까요..?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
안녕하세요 08-02-nestjs-with-graphql 폴더실행시에러
안녕하세요 해당영역 학습중인데 서버실행시 자꾸 Error: Cannot find module '@apollo/server' 이런에러가 발생됩니다 그래서 node_modules 디렉토리 삭제후 다시 설치해보고 yarn add apollo-server 명령어를 사용해서 설치도해보았는데도 동일한 증상입니다..ㅠ 그래서 앞부분 학습을 못하고잇어요 ㅠ 현재 버전은 이러합니다 !
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
포스트 트윗 시 게시글이 추가되지 않고, 요청 무한로딩에 걸립니다. TypeError: Cannot read properties of undefined (reading 'data')
안녕하세요 제로초님현재 섹션3 redux-saga 연동하기 - 게시글, 댓글 saga 작성하기 영상의 Warning: Encountered two children with the same key, 2. 에러 해결까지 수강한 학생입니다!로그인 후 포스트 폼에 글을 입력 후 트윗하기 버튼을 누르는 순간 콘솔 창에 에러가 발생했습니다.redux-devtools로 포스트 추가 액션의 변화를 살펴보니ADD_POST_SUCCESS 포스트 추가 성공 액션이 실행되고 있지 않았습니다! 콘솔에 있는 에러 메시지 번역은 다음과 같았습니다.번역을 읽고 data가 undefined이며, addPost에 이상이 있음을 확인했고,컴포넌트 폴더의 PostForm.js와 reducers/post.js, sagas/post.js를 코드를 확인했습니다.https://github.com/ZeroCho/react-nodebird/blob/master/ch4/front/components/PostForm.js제로초님의 깃허브 챕터4와 구글 검색을 참고 후 가장 의심되는 코드 부분을 올립니다!※ 관련 없는 코드는 . . . 으로 요약 표시하였습니다. components/PostForm.js가독성을 위해 setText는 setPostText로, text는 postText로 바꾸어 코딩했습니다.// reducer 포스트 추가 요청 액션 불러오기 import { addPost } from '../reducers/post'; // 포스트 폼 컴포넌트(사용자 정의 태그) const PostForm = () => { const dispatch = useDispatch(); const [postText, onChangePostText, setPostText] = useInput(''); const { imagePaths, addPostLoading, addPostDone } = useSelector((state) => state.post); /* ----- 포스트 추가 완료 시 포스트 폼 글자 지우기 ----- */ useEffect(() => { if (addPostDone) { setPostText(''); } }, [addPostDone]); /* ----- 포스트 폼 제출 시 포스트 카드 추가 ----- */ const onSubmitForm = useCallback(() => { dispatch(addPost(postText)); }, [postText]); // const onSubmitForm = useCallback(() => { // dispatch({ // type: ADD_POST_REQUEST, // data: addPost, // }); // }, [postText]); return ( <Form . . . /> <Input.TextArea id="post-form" value={postText} onChange={onChangePostText} maxLength={140} placeholder="어떤 신기한 일이 있었나요?" /> . . . {/* ---------- 포스트 작성 버튼 ---------- */} <Button type="primary" style={{ float: 'right' }} htmlType="submit" loading={addPostLoading} > 트윗하기 </Button> </div> </Form> ); }; reducers/post.js// ShortId 라이브러리 불러오기 import shortId from 'shortid'; // 중앙 데이터 저장소(기본 state) export const initialState = { /* ---------- 메인 포스트 더미 데이터 ---------- */ mainPosts: [{ . . . }], /* ---------- 이미지 업로드 시 경로 저장 ---------- */ imagePaths: [], /* ---------- 포스트 추가 시도 중, 완료, 에러 ---------- */ addPostLoading: false, addPostDone: false, addPostError: null, } // 포스트 추가 액션 : 요청, 성공, 실패 export const ADD_POST_REQUEST = 'ADD_POST_REQUEST'; export const ADD_POST_SUCCESS = 'ADD_POST_SUCCESS'; export const ADD_POST_FAILURE = 'ADD_POST_FAILURE'; // 포스트 추가 요청 액션 생성함수(action creator) export const addPost = (data) => ({ type: ADD_POST_REQUEST, data, }); // 포스트 더미 데이터 const dummyPost = (data) => ({ id: shortId.generate(), content: data, User: { id: 1, nickname: '다랑', }, Images: [], Comments: [], }); // 리듀서(reducer) : (이전 상태, 액션) => 다음 상태 const reducer = (state = initialState, action) => { switch (action.type) { /* ----- 포스트 추가 요청 리듀서 ----- */ case ADD_POST_REQUEST: return { addPostLoading: true, addPostDone: false, addPostError: null, }; /* ----- 포스트 추가 성공 리듀서 ----- */ case ADD_POST_SUCCESS: return { ...state, mainPosts: [dummyPost(action.data), ...state.mainPosts], addPostLoading: false, addPostDone: true, // 사용자 더미 데이터 me: dummyUser(action.data), }; /* ----- 포스트 추가 실패 리듀서 ----- */ case ADD_POST_FAILURE: return { addPostLoading: false, addPostError: action.error, }; default: return state; } }; sagas/post.js// Saga 이펙트 불러오기 import { all, fork, call, takeLatest, put, delay } from 'redux-saga/effects'; // Axios 라이브러리 불러오기 import axios from 'axios'; // reducer 포스트 추가, 답글 추가 액션 불러오기 import { ADD_POST_REQUEST, ADD_POST_SUCCESS, ADD_POST_FAILURE, } from '../reducers/post'; // addPost 실행 시 서버에 addPostAPI 요청 function addPostAPI(data) { return axios.post('/api/post', data) } // ADD_POST_REQUEST 액션이 실행되면 addPost 함수 실행 function* addPost(action) { try { // const result = yield call(addPostAPI, action.data); /* ----- 요청 성공 시 ADD_POST_SUCCESS 액션 디스패치 ----- */ yield delay(1000); yield put({ type: ADD_POST_SUCCESS, data: action.data, // 성공 결과 }); } catch (err) { /* ----- 요청 실패 시 ADD_POST_FAILURE 액션 디스패치 ----- */ yield put({ type: ADD_POST_FAILURE, error: err.response.data, // 실패 결과 }); } } 강의 잘 보고 있습니다!항상 정성스러운 답변 남겨주셔서 감사합니다 제로초님!
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
식별 관계랑 비식별 관계
안녕하세요 강의 끝까지 잘봤습니다!!!강의 시청 후 포트폴리오용 프로젝트 설계 중에 식별 관계에 대해 의문이 생겨서 질문합니다! 우선 식별 관계로 구성 시 자식 테이블에 데이터를 넣기 전에 부모 테이블에 데이터가 필수적으로 존재해야 한다고 알고 있습니다.이는 개발자가 실수로 데이터를 입력하는 것을 막아줌으로써 데이터 정합성을 DB에서도 체크할 수 있지만, 만약 요구사항이 변경된다면 테이블의 데이터와 구조를 모두 변경해야하는 불상사가 발생할 수 있다고 알고 있습니다. 그렇다면 굳이 식별 관계로 설정할 필요가 있나요?? 그냥 전부 비식별 관계로 설정하면 안될까요? 포트폴리오에 올릴 프로젝트를 만드는 중이라 정석대로 식별 관계로 설정해야 하나 싶은데, 아직 뭐가 뭔지 잘 모르는 상태에서 괜히 복잡하게 식별 관계로 설정하는게 맞는건가 잘 모르겠어서요ㅜㅜ
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 레딧 사이트 만들기(NextJS)(Pages Router)
잘 되다가 cors 에러가 계속 뜨는데
몇 번이고 완성코드랑도 비교해보고 영상도 계속 돌려보고다 확인해봐도 코드의 문제는 전혀 없는데도대체 왜 갑자기 cors 에러가 뜨는지 모르겠네요...
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
gcp gke configmap관련 질문드립니다
gcp gke configmap관련 질문드립니다지워도 보고 docker-compose file에서 envfile 주석처리되어있는데도 막상 디플로이하면 항상 env에 localhost로 나와버리네요configmap에선 정상적으로 제가 입력한값으로 뜨는데 적용이 안됩니다로컬에서 도커이미지 전부다 지워봤는데도 계속 그럽니다, 어떻게 해야할까요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
MyIcon 에러
다음과 같이 에러가 나는데 이유가 뭔가요 'rev' 속성이 '{}' 형식에 없지만 'Pick<AntdIconProps, "cite" | "data" | "form" | "label" | "slot" | "span" | "style" | "summary" | "title" | "pattern" | "start" | "hidden" | "color" 에서 필수입니다 라고 나옵니다
-
미해결[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
Cannot find module 'msw/node' from 'src/commons/mocks/index.js'
안녕하세요. test를 하던 중 오류가 발생하여 문의드립니다.지금 현재 코드를import { setupServer } from "msw/node"; import { apis } from "./apis"; export const server = setupServer(...apis); 위에처럼 입력해 놓은 상태입니다. 하지만 테스트 실행 시아래와 같이 발생합니다. Cannot find module 'msw/node' from 'src/commons/mocks/index.js' Require stack: src/commons/mocks/index.js jest.setup.js > 1 | import { setupServer } from "msw/node"; | ^ 2 | import { apis } from "./apis";추가적으로 지금 jest관련 페이지에서Parsing error: ESLint was configured to run on `<tsconfigRootDir>/src\commons\mocks\index.js` using `parserOptions.project`: <tsconfigRootDir>/tsconfig.json However, that TSConfig does not include this file. Either: - Change ESLint's list of included files to not include this file - Change that TSConfig to include this file - Create a new TSConfig that includes this file and include it in your parserOptions.project See the typescript-eslint docs for more info: https://typescript-eslint.io/linting/troubleshooting#i-get-errors-telling-me-eslint-was-configured-to-run--위와 같은 오류가 발생합니다. 해결 부탁드립니다!
-
미해결[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
eslint 설치시 노드 버전 오류때문에 설치가 안되는거 같습니다.
노드 버전때문에 eslint가 설치되다가 중간에 오류가 났습니다. 그래서 오류 내용이 노드 16버전이나 18버전 이상을 써라고 하는거 같더라고 지금 17.3.1버전이고요, 그래서 nvm use 명령을 사용해서 18.15버전을 사용해서 설치 했더니 그때부터 parser 오류가 계속 나더라고요..ㅠㅠ parser 오류를 없애려고 하니, eslint가 작동을 안하는거 같고 도와주세요 아래에 tsconfig.json, eslintrc.js, package.json, 그리고 경로 사진을 첨부하여 드립니다. 어떻게든 구글 검색으로 할려고 했으나... 도대체 어느버전이 호환이 안되는건지 모르겠네요 ㅠㅠeslint 설치시 오류난 상황 캡처 사진입니다.파일 경로 캡처입니다.tsconfig 캡처입니다.package.json 캡처입니다.eslintrc.js 캡처입니다.
-
미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
서버에 여러명이 동시 접속 시 잘못된 개인정보 전송 오류
안녕하세요 제로초님~ 금일 질문드리고자 하는 내용은 제 ec2 에 띄워둔 nest.js 서버에 여러명이 동시에 접속 시, 서버의 오작동에 관한 내용입니다.nest.js 로 개발을 하면서 여러 사람이 서버에 동시에 로그인을 하면, 로그인한 당사자가 아닌 다른 사람의 회원정보가 나타나는 버그를 발견했습니다. 그래서 인터셉터를 사용하여 사용자에게 응답을 보내기 전 한번 더 검증을 진행하는 방식으로 해결을 했지만, 여러 의문점들을 해결하지 못하여 질문드립니다.1. 인터셉터를 사용하여 위 문제를 해결한 것이 올바른 접근 방식일까요? 팀원들에게 물어보니 인터셉터를 적용한 후에 위 같은 현상이 사라졌다고는 합니다.2. 이러한 문제가 나타나는 이유가 무엇일까요? 제 예상으로는 Node.js 가 싱글스레드라서 여러 요청이 한번에 몰려오면 비동기 부분이 꼬여서 나타나는 문제일까 생각했습니다. 그런데 챗지피티에게 물어보니 오히려 싱글스레드, 싱글톤이면 꼬일 일이 없다고 해서 더 혼란스럽네요. ============================================깃허브 저장소 컨트롤러 부분 : https://github.com/fog-of-war/dev-be/blob/dev/src/users/users.controller.ts#L63서비스 부분 : https://github.com/fog-of-war/dev-be/blob/dev/src/users/users.service.ts#L72가드 부분 : https://github.com/fog-of-war/dev-be/blob/dev/src/auth/guard/at.guard.ts#L13전략 부분 : https://github.com/fog-of-war/dev-be/blob/fff2d70af55ba51d1b3649006774b4d2aec7d566/src/auth/strategy/at.strategy.ts#L12인터셉터 부분 : https://github.com/fog-of-war/dev-be/blob/dev/src/common/interceptor/user-sub-check.interceptor.tsGetCurrentUser 데코레이터 부분 : https://github.com/fog-of-war/dev-be/blob/dev/src/auth/decorator/get-current-user-id.decorator.ts#L4============================================아래의 글은 제가 해결해보면서 적은 블로그 글입니다. ### 1. 로그로 찍어보기일단 로그로 어떻게 된 일인지 확인해봤다.```ts@UseGuards(ATGuard) @Controller("users") export class UsersController { constructor( private userService: UsersService, private logger: LoggerService ) {} /** 나의 정보 가져오기/ 마이페이지, 메인페이지 사용 */ @Get("me") async getMe(@GetCurrentUserInfo() user) { // 1. 여기선 user_id : 3 으로 출력되나 this.logger.log("1️⃣ 1. 자신의 회원정보 호출한 사람 ", user["sub"]); const result = await this.userService.findUserById(user["sub"]); // 2. 여기선 user_id : 2 의 정보를 출력 후 user_id : 3 에게 응답 this.logger.log("2️⃣2. 자신의 회원정보 호출 결과", result); return result; } }user_id : 3 이 'users/me' 요청을 했을때 1️⃣ 로그에서는 정상적으로 요청한 사람의 정보를 출력했다.그러나 서비스 계층 비즈니스 로직을 지난 뒤인 2️⃣ 로그에서는 user_id : 2 의 정보를 출력했다.엑세스토큰 소유자의 것이 아닌 동시에 접속한 다른 사람의 정보를 전달한 것이다.혼자 로컬에서 여러 계정으로 로그인해가며 작업을 할 땐 이런 현상이 없었기에, Node.js 의 싱글스레드 방식 때문이 아닐까 예상했다.### 2. 비슷한 사례 찾아보기"로그인하면 다른 사람 정보가"···리디, 개인정보 유출 사고[https://v.daum.net/v/20230329083313717](https://v.daum.net/v/20230329083313717)올리브영 개인정보 노출 사건, 무슨 일이 일어났을까?[https://www.boannews.com/media/view.asp?idx=114594](https://www.boannews.com/media/view.asp?idx=114594)리디북스의 경우 CDN 서버 캐시 설정 오류, 올리브영의 경우 CDN 오류 였다고 한다. 현재 내 서버는 CDN 방식을 사용하지 않고 있다.올리브영, 아직 조사 중이라 상세 내용 공개 어려워그러면서 “CDN(콘텐츠 배포 네트워크)에서 일시적인 오류가 발생해 일부 고객들의 정보가 노출된 것”이라고 설명했다. CDN이 엉키면 사용자가 특정 콘텐츠를 요청했을 때, 엉뚱한 결과가 출력되는데, 바로 그런 일이 일어났다는 것이다.Open AI 의 경우 Redis 라이브러리 버그[https://www.clien.net/service/board/news/17984872](https://www.clien.net/service/board/news/17984872)클리앙의 경우 Redis 라이브러리 버그[https://www.clien.net/service/board/annonce/17922106](https://www.clien.net/service/board/annonce/17922106) Open AI 와 클리앙의 경우 레디스 라이브러리 버그로 발생했다고 한다. 하지만 내 서버에 레디스를 설치하기 전에도 해당 버그는 발생했었다. 정확한 원인이 파악되었습니다.저희가 서버에서 세션을 저장하고 있는 redis(일종의 메모리db)가 한계수치 이상의 부하를 받으면 인덱스가 깨지는 현상이 발생한다고 합니다.국내 대형 쇼핑몰 두곳에서 최근 유사한 증상이 있어 관련자들에게 문의해본 바 저희와 같은 증상이었습니다. 이번의 여러 조치 중 redis 통신 최적화 작업도 진행하였기에 다시 재발되지 않을 것입니다.더 줄일 수 있는 요소가 있으므로 추가적인 작업을 진행할 예정입니다.### 3. 해결 방안클라이언트에게 데이터를 돌려보내기 전에 한 번 더 검증을 진행하기로 했다.들어오는 모든 요청을 인터셉터가 먼저 확인하고, 해당 엔드포인트가 Access Token 을 사용하는 메서드라면 user_id 를 originalUserSub 라는 변수에 기록해둔다.그리고 응답을 반환하기 전, 반환 값에 들어있는 user_id 와 originalUserSub 의 동일 여부를 검증한다.만약 검증을 통과하지 못한다면 해당 요청을 무효화하고 다시 실행하게끔 로직을 구성했다.import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common'; import { Observable } from 'rxjs'; import { switchMap } from 'rxjs/operators'; import { LoggerService } from '../../logger/logger.service'; @Injectable() export class UserSubCheckInterceptor implements NestInterceptor { constructor(private readonly logger: LoggerService) {} intercept(context: ExecutionContext, next: CallHandler): Observable<any> { const request = context.switchToHttp().getRequest(); const user = request.user; const originalUserSub = request.user.sub; return next.handle().pipe( switchMap(async (data) => { if (user['sub'] && data.user_id) { if (data.user_id && originalUserSub !== undefined && data.user_id !== originalUserSub) { // user["sub"] 값이 변경되었으므로 해당 메서드를 다시 호출합니다. this.logger.log("UserSubCheckInterceptor : user['sub'] 가 동일하지 않습니다 " + originalUserSub + "!==" + data.user.user_id) return await next.handle().toPromise(); } } return data; }), ); } }https://github.com/fog-of-war/dev-be/blob/dev/src/common/interceptor/user-sub-check.interceptor.ts
-
미해결[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
린터 Parsing error
안녕하세요.린터와 포멧터 강의 따라하면서 모든 설치와 적용을 끝냈는데요. 하던 중에 .eslintrc.js에서 다음과 같은 에러가 뜨기 시작하더라구요.해결방법 서치하다가 아래 코드를 추가했더니 위 에러는 사라지긴 했는데 맞는 해결방법인지 모르겠네요.ignorePatterns: [".eslintrc.js"]그리고 이 코드를 넣든 안 넣든 class 내에 있는 모든 js 파일들에서 import 부분에 Parsing error가 나네요...(ts, tsx 파일들은 제대로 lint가 작동하는 것 같아 전부 고칠 수 있었습니다)이런 오류가 아마 모든 js 파일에서 뜨네요yarn lint하면 이렇게 도배가 되구요... 어떻게 해결해야 하나요?참고로 .eslintrc.jsmodule.exports = { env: { browser: true, es2021: true, }, extends: ["standard-with-typescript", "plugin:react/recommended", "prettier"], overrides: [ { env: { node: true, }, files: [".eslintrc.{js,cjs}"], parserOptions: { sourceType: "script", }, }, ], parserOptions: { project: "**/tsconfig.json", ecmaVersion: "latest", sourceType: "module", }, plugins: ["react"], rules: { "react/react-in-jsx-scope": "off", "@typescript-eslint/no-misused-promises": "off", "@typescript-eslint/no-unused-vars": "off", }, ignorePatterns: [".eslintrc.js"], }; tsconfig.json{ "compilerOptions": { "target": "es5", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, "forceConsistentCasingInFileNames": true, "noEmit": true, "incremental": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve" }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "exclude": ["node_modules"] } 폴더 구조입니다!
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
yarn run start가 안돼요
package.jsonnode_modules, yarn.lock 지우고 다시 깔아보고 라이브러리 버전 맞춘거 같은데 yarn run start가 안돼요 tsconfig.jsoneslintrc.jstsconfig.json, eslintrc.js 느낌상 이쪽 문제 같은데 어딘지 모르겠습니다여기 폴더 인터넷 찾아보고 조금 수정했는데 모르겠어요어느순간부터 오류 놓쳤는데 어딘지 모르겠어요
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
정말 렌덤하게 403(Forbiden Error) 가 뜹니다.
안녕하세요! 람다하고 nginx 까지 적용했는데, 정말 렌덤하게 403 error 가 뜹니다.몇몇 이미지는 처음 업로드 할때 403 error 가 나지만 새로고침을 하면 업로드가 되어 있었습니다.1MB에 png 이미지는 resizing 이 되지 안고 새로고침을 해도 403에러가 납니다.람다 모니터링 메세지를 봤는데 이렇게 나옵니다.혹시 제가 resize 폴더에 너무 많은 이미지를 저장해서 나는 오류일까요? 감사합니다.
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 쇼핑몰 사이트 만들기[전체 리뉴얼]
[plugin:vite-plugin-eslint] error 'React' is defined but never used no-unused-vars
eslint 와 관련된 에러 인 것 같은데요.물론 강의 중에 말씀하신 eslint 설정도 완료 하였습니다. React를 사용하지 않는데 React를 import 해서 그런것 같습니다. 강사님 강의 중에는 이런 현상이 없는데 이런 현상이 나와서 구글링을 해보아도 뾰족한 답을 못찾았습니다.확인 부탁드립니다~!!
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
이 호출과 일치하는 오버로드가 없습니다. 오류
무한스크롤 Section16-02-infinite-scroller 강의를 듣고 있을 때 발생한 오류입니다.실행은 정상적으로 되는데 해결방법 알 수 있을까요?