묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결탄탄한 백엔드 NestJS, 기초부터 심화까지
안녕하세요 강사님 실행할때 오류가 발생해서 질문드립니다.
Error: Cannot find module 'app.model' Require stack: - D:\Study\Inflearn\NestJS\Express\letsStart\dist\app.js at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15) at Function.Module._load (node:internal/modules/cjs/loader:778:27) at Module.require (node:internal/modules/cjs/loader:1005:19) at require (node:internal/modules/cjs/helpers:102:18) at Object.<anonymous> (D:\Study\Inflearn\NestJS\Express\letsStart\dist\app.js:4:19) at Module._compile (node:internal/modules/cjs/loader:1101:14) at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10) at Module.load (node:internal/modules/cjs/loader:981:32) at Function.Module._load (node:internal/modules/cjs/loader:822:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12) { code: 'MODULE_NOT_FOUND', requireStack: [ 'D:\\Study\\Inflearn\\NestJS\\Express\\letsStart\\dist\\app.js' ] } npm run start:dev 했을때 이와같은 오류가 발생하고 postman도 마찬가지로 localhost:8000으로 get 검색시 찾지 못하는데 어느 부분에서 잘못됬는지를 모르겠습니다. 코드는 오타 없이 강사님이 작성한것과 동일합니다.
-
미해결스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
SSR관해서
HTML을 WAS에서 생성할때와 서버에서 생성할때의 차이가 무엇입니까?
-
미해결Nuxt.js 시작하기
서버사이드 렌더링에서 서버란 무엇인가요?!
안녕하세요!! 강의 정말 유용하고 잘봤습니다! 근데 SSR과 CSR의 개념적인 부분에서 CSR은 쉽게 얘기해서 제가사이트를 들어갔을때 최초로 서버에서 빈 HTML과 모든 JS, CSS파일등을 받아서 제 브라우저(?)에서 페이지를 그리는걸 의미한다라고 이해했고 SSR같은 경우는 최초 사이트 진입시 해당 페이지의 완성된 페이지를 서버에서 받아오고 다른페이지 시동시마다도 완성된페이지를 서버에서 받아온다라고 이해했습니다 근데 궁금한점이 SSR에서 서버란게 어떤서버를 의미하는건지 잘모르겠습니다. 웹서버나 WAS같은 서버를 의미하는걸까요?
-
해결됨탄탄한 백엔드 NestJS, 기초부터 심화까지
TypeORM 트랜잭션 질문드립니다.
안녕하세요 윤상석 강사님. TypeORM의 트랜잭션 관련으로 질문이 있습니다.TypeORM에서 트랜잭션을 다루는 방법은 이전 질문글에 답변해주셨듯이 크게 3가지인 것으로 알고 있습니다.1. QueryRunner2. getConnection, getManager3. @Transactional개인적으로는 @Transactional() 데코레이터를 사용하는것이 편리하여 사용하고 있었는데요.NestJS 공식문서에서 데코레이터를 이용하는 것을 권장하지 않고 있고,구글링을 해보아도 유닛 테스트에 어려움이 있어 권장하지 않는 분들이 많은 것을 알게되었습니다.여기서 첫 번째 질문이 있습니다.Q1. "유닛 테스트에 어려움이 있다"는 이야기가 구체적으로 무슨 의미인지 궁금합니다. 모킹이 어렵다. 내 마음대로 제어가 불가능하다 등의 이야기가 이해는 가는데 와닿지는 않아서 질문드립니다.----QueryRunner 방식을 이용하게 되면 try-catch-finally 코드가 강제가 되는 것 같아보입니다.여기서 두 번째 질문이 있습니다.Q2. 모든 에러를 감지하는 Filter를 적용해두었다면 QueryRunner를 사용하는 try-catch-finally 구문에서 에러 처리를 해버려 필터가 작동하지 않을 것 같은데 맞을까요?맞다면, 만약 Filter에서 요청이 실패하였을 때의 로깅기능이 있다고 가정한다면 로깅기능이 작동하지 않을 것 같습니다.그렇다면 catch 문에서 따로 Filter에서 구현한 로깅을 다시 구현해주어야 할까요?----트랜잭션 처리를 도와주는 typeorm-transactional-cls-hooked 패키지를 발견하였습니다.여기서 마지막 세 번째 질문이 있습니다.Q3. 해당 패키지는 유닛 테스를 할 때 트랜잭션 기능이 작동하지 않도록 모킹기능도 제공해주는 것 같습니다. QuerryRunner 보다 안 좋은점이 있다면 어떤 점이 있을까요?----질문이 너무 많은 것 같아 죄송합니다.좋은 강의와 답변해주셔서 항상 감사합니다.
-
미해결탄탄한 백엔드 NestJS, 기초부터 심화까지
useFactory 사용시 resource 파일 분리 후 di 방법
먼저 너무 좋은 ADMIN 대시보드 라이브러리를 알려주셔서 감사합니다. 해당 라이브러리로 몇가지 테스트해보는 중인데 adminJsOptions가 너무 길어져 resources를 별도의 파일로 분리하려 하고 있습니다. 하다보니 이미 factory로 blogModel을 inject하고 있는데 resources를 별도의 파일로 분리하려고 보니 blogModel을 분리한 파일에서 어떻게 가져와야할지 막막하더라구요. adminjs뿐아니라 다른 모듈을 사용할때도 useFactory를 통해 di를 해주는경우가 많은데 이럴때는 분리된 파일에는 어떻게 의존성을 주입해줘야 할까요??? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 import * as AdminJSMongoose from '@adminjs/mongoose'; import { AdminModule as AdminBroModule } from '@adminjs/nestjs'; import { Module } from '@nestjs/common'; import { getModelToken } from '@nestjs/mongoose'; import AdminJS from 'adminjs'; import { Model } from 'mongoose'; import { UsersModule } from 'src/users/users.module'; import { User } from 'src/users/users.schema'; import { after, before } from './hooks/users.hooks'; AdminJS.registerAdapter(AdminJSMongoose); @Module({ imports: [ AdminBroModule.createAdminAsync({ imports: [UsersModule], inject: [getModelToken(User.name)], useFactory: (usersModel: Model<User>) => ({ adminJsOptions: { rootPath: '/admin', resources: [ { resource: usersModel, options: { navigation: { name: null, icon: '', }, properties: { email: { isTitle: false, position: 1, }, name: { isTitle: true, }, _id: { isVisible: { list: false }, }, password: { isVisible: false, }, }, actions: { edit: { isAccessible: isAdmin }, delete: { isAccessible: isAdmin }, new: { isAccessible: isAdmin }, show: { isAccessible: isAdmin, }, list: { isAccessible: isAdmin }, custom_delete: { actionType: 'record', icon: 'TrashCan', guard: 'doYouReallyWantToDoThis', variant: 'danger', before: before, after: after, handler: async (request, response, context) => { const user = context.record; await usersModel.findOne({_id: request.params.id}); console.log('custom handler!!!'); return { record: user.toJSON(context.currentAdmin), }; } }, }, }, }, ], }, auth: { authenticate: async (email, password) => { const user = await usersModel.findOne({ email: email }); if (user) { const matched = user.password === password; if (matched && user.role === 'ADMIN') { return user.readOnlyData; } } return null; }, cookieName: 'cookie-test', cookiePassword: 'test', }, }), }), ], }) export class AdminModule {} const isAdmin = ({ currentAdmin }) => currentAdmin && currentAdmin.role === 'ADMIN'; resource 코드 분리 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import * as AdminJSMongoose from '@adminjs/mongoose'; import { AdminModule as AdminBroModule } from '@adminjs/nestjs'; import { Module } from '@nestjs/common'; import { getModelToken } from '@nestjs/mongoose'; import AdminJS from 'adminjs'; import { Model } from 'mongoose'; import { UsersModule } from 'src/users/users.module'; import { User } from 'src/users/users.schema'; import { after, before } from './hooks/users.hooks'; import { userResource } from './resources/users.resource'; AdminJS.registerAdapter(AdminJSMongoose); @Module({ imports: [ AdminBroModule.createAdminAsync({ imports: [UsersModule], inject: [getModelToken(User.name)], useFactory: (usersModel: Model<User>) => ({ adminJsOptions: { rootPath: '/admin', resources: [ userResource ], }, auth: { authenticate: async (email, password) => { const user = await usersModel.findOne({ email: email }); if (user) { const matched = user.password === password; if (matched && user.role === 'ADMIN') { return user.readOnlyData; } } return null; }, cookieName: 'cookie-test', cookiePassword: 'test', }, }), }), ], }) export class AdminModule {} const isAdmin = ({ currentAdmin }) => currentAdmin && currentAdmin.role === 'ADMIN'; 함수로 만들어 파라미터로 넘겨주는 방법밖에 없을까요???
-
해결됨[리뉴얼] 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: {}}; });
-
미해결탄탄한 백엔드 NestJS, 기초부터 심화까지
next()가 없는 (불필요한) 경우에도, middleware 함수라고 볼 수 있나요??
안녕하세요~ 좋은 강의 넘 잘 듣고 있습니다~ 감사합니다 :) 이 에러 핸들링을 하는 함수를 middleware라고 언급해주셨는데, 저는 조금 헷갈려서 질문 드립니다! app.use((req: express.Request, res: express.Response, next: express.NextFunction) => { console.log('this is error middleware'); res.send({ error: '404 not found error' }); }); 미들웨어는 하려는 일의 중간에서, 개발자가 원하는 무언가를 할 수 있도록 하는 것을 말하는거니까 express 에서는 next() 가 있는 경우를 middleware 로 본다 는 것으로 이해했습니다. 그런데 위 코드는 다음으로 넘기는 것 없이 바로 404를 반환해서, next가 꼭 필요하지 않은 것 같은데... 이 경우에도 이 함수를 middleware 함수라고 볼 수 있나요~?
-
미해결탄탄한 백엔드 NestJS, 기초부터 심화까지
http-exception.filter.ts 파일 내용 중 질문이 있습니다.
const error = exception.getResponse() as | string | { error: string; statusCode: number; message: string | string[] }; 강의 중에 http-exception.filter.ts 파일에서 error 변수를 위와 같이 할당을 하는데 as | string 뒤에 있는 타입을 { error: string, statusCode: number; message: string | string[] };로 받는데 객체의 속성들을 특별하게 넣어준 이유가 있나요? 단순히 { error: string }로만 처리해도 다른 속성 값들이 자동으로 들어오기 때문에 출력할 때는 문제가 없는 것 같은데 정확한 타입을 제공하기 위해서 라던가 등 특별한 이유가 있는지 궁금합니다.
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
42초에서 말씀하신 서버사이드 렌더링에 대해 질문
0:38 초가량 부근에서 서버사이드렌더링은 defaultandserver?에서 html을 데이터와 합쳐서 그려준다고 그랬죠? 라고 하신 부분이 이해가 잘되지 않아서요 styledcomponent는 style을 컴포넌트로 꾸며주는 라이브러리고 렌더링할떄 작동하므로 서버에서 렌더링 하고 내려오는 SSR의 동작원리상 서버쪽에서 적용이 안됐다고 보면 되는거 같은데요 (맞나요?) 렌더링이라는거 자체가 브라우저에서 렌더링 엔진이 코드를 읽고 DOM, CSSOM하고 렌더트리로 합친다음에 리플로우 리페인트하는 과정이라고 알고 있습니다. 그럼 무조건 호스트쪽 컴퓨터의 브라우저에서 렌더링하는게 아닌가 싶은데 서버쪽에서 '렌더링'을 미리 해준다는 것이 무슨 말인지 이해가 잘되지 않습니다. 말씀하시는 '렌더링'은 화면을 구성할 코드를 만들어줬다는 말인가요?
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
getServersideProps session 질문
안녕하세요! 강좌를 바탕으로 블로그를 제작하는 중에, 방문자 수를 counting 하는 기능을 구현하는데 막혀 질문드립니다. front server에서 getServerSideProps에 있는 export const getServerSideProps = wrapper.getServerSideProps(async (context) => { const cookie = context.req ? context.req.headers.cookie : ''; axios.defaults.headers.Cookie = ''; if (context.req && cookie) { axios.defaults.headers.Cookie = cookie; } context.store.dispatch({ type: LOAD_MY_INFO_REQUEST, }) context.store.dispatch({ type: LOAD_POSTS_REQUEST, }); context.store.dispatch(END); await context.store.sagaTask.toPromise(); }); LOAD_MY_INFO_REQUEST와 LOAD_POSTS_REQUEST를 이용해 back server에 요청을 날리면 back server에서는 app.js의 최상단에 존재하는 let count = 0; app.use((req,res,next) => { var date = new Date(); var today=date.getYear()+" "+date.getMonth()+" "+date.getDate(); console.log("lastvisit : " + req.session.lastVisit); if(req.session.lastVisit != today){ req.session.lastVisit = today; count++; } next(); }); 다음 함수를 이용해 방문자 수를 count할려고합니다! 문제는 front에서 먼저, LOAD_MY_INFO_REQUEST로 요청을 보내, session과 함께 응답을 받고 다시 LOAD_POSTS_REQUEST요청을 하면, 요청에는 첫번째 요청의 응답으로 넣어주었던 session이 존재하지 않는다는 점입니다. 몇일동안 잡고 있어도 도저히 해결책을 모르겠어 질문드립니다.
-
미해결탄탄한 백엔드 NestJS, 기초부터 심화까지
소켓 연결관련 질문입니다.
강의에서 socket.id는 계속 유지되다가 연결이 끊기거나 새로고침되면 바뀐다고 나오는데요 즉, 새로고침하면 소켓연결이 끊긴다는 뜻인데 이걸 막을 방법이 있나요? 예를 들어서 제가 웹 상에서 멀티플레이가 가능한 카드게임을 구현한다고 하면 게임 플레이 도중 사용자가 실수로 새로고침을 누르면 끊겨버릴텐데 이런 상황에서는 어떤식으로 처리를 하나요? 또 질문이 하나 있는데 강의와는 조금 벗어난 질문이긴한데.. 소켓연결에 더해서 redis까지 이용해서 만들어보려고 하는데 구글에 nestjs redis 이렇게 검색하면 나오는 공식문서가 Microservice 어쩌고 하면서 redis랑 같이 나오더라구요. 제가 구현하고 싶은 기능은 웹상에서 방을 만들고, 사용자들이 해당 방에 들어가면 사용자들의 정보를 redis에 담고 redis pub/sub과 소켓을 이용하여 같은 방안에 사용자들끼리 통신하는 그런걸 만들어보고 싶은데 이 경우에 공식문서에 나와있는 Microservice.. 를 쓰면 되는게 맞는건지 잘 모르겠어서 질문드립니다.
-
미해결Nuxt.js 시작하기
nuxt.js 초기 세팅시 폴더 구조가 강의와 다르게 구성됩니다
프로젝트 생성시의 설정값을 강의에서와 동일하게 했는데, 말씀하신 것과 폴더구조가 다르게 설정되고 있습니다. (프로젝트 이름을 동일하게 설정하고 설치해도 저렇게 폴더구조가 잡힙니다) npm run dev를 실행하면 첫 화면도 강의와 다르게 나오고 layouts, middleware, plugins와 같은 폴더가 빠졌는데 create-nuxt-app 버전이 강의에서는 v3.6.0이고 지금 설치하면 v3.7.1으로 나오는데 버전이 달라지면서 생기는 차이인걸까요?
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
emotion SSR 적용 질문있습니다!
안녕하세요 현영님! styled-components 대신에 emotion 사용해서 실습하고 있는데, emotion 공식문서에서 10버전 이상부터는 next에서 SSR 적용이 된다고 나와있는데요. (현재 11버전 사용중입니다.) 그렇다면, pages/_document.js의 코드에서 import React from "react"; import Document, { Html, Head, Main, NextScript } from "next/document"; // import {ServerStyleSheet} from "styled-components" export default class MyDocument extends Document { static async getInitialProps(ctx) { // const sheet = new ServerStyleSheet(); const originalRenderPage = ctx.renderPage; try { // ctx.renderPage = () => // originalRenderPage({ // enhanceApp: App => props => sheet.collectStyles(<App {...props} />) // }); const initialProps = await Document.getInitialProps(ctx); return { ...initialProps, styles: ( <> {initialProps.styles} {/* {sheet.getStyleElement()} */} </> ) }; } catch (err) { console.error(err); } finally { // sheet.seal(); } } render() { return ( <Html> <Head /> <body> <script src="https://polyfill.io/v3/polyfill.min.js?features=default%2Ces2015%2Ces2016%2Ces2017%2Ces2018%2Ces2019" /> <Main /> <NextScript /> </body> </Html> ); } } styled-components 관련 부분만 제외하고 입력하면 될까요?
-
해결됨탄탄한 백엔드 NestJS, 기초부터 심화까지
프론트 코드는 어디서 받나요?
https://github.com/amamov/teaching-nestjs-a-to-z 에 있는 frontend 디렉토리가 프론트코드인가요?
-
미해결탄탄한 백엔드 NestJS, 기초부터 심화까지
Filter도 결국 middleware에서 처리할 수 있을거 같은데 나누는 이유가 있을까요?
Filter도 결국 middleware에서 처리할 수 있을거 같은데 나누는 이유가 있을까요?
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
CSR에서 로그인 정보 불러오기
안녕하세요 제로초님 강의 정말 잘 듣고 있습니다. [내 로그인 정보 매번 불러오기] 강의 파트에서 애초부터 서버에서 데이터를 받아올 때 로그인이 되어 있게 하려면 서버 사이드 렌더링(SSR)을 해주어야 한다고 말씀해주셨는데 그렇다면 CSR로 react-nodejs에서는 아예 불가능한 부분인가요?
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
초기 로딩할 때 SSR 방식이라면
초기 로딩할 때 SSR 방식으로 불러오면 UX 관점에서 어떤 이유로든 혹시나 로딩이 오래걸릴 경우 로딩 화면조차 안나오면 사용자들의 이탈률이 CSR보다 높지 않나요?
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
제로초님 질문하나만 하겠습니당 ssr 관련
A 페이지 SSR 하는 페이지 B 페이지 그냥 페이지(SSR안하는 페이지) A에서 B로 이동 후 B에서 뒤로가기 하면 A로 이동 이 때 뒤로가기 시 A로 이동되면서 ssr 이 되면서 페이지가 아예 리렌더링 되더라고요.. 그냥 일반적인 웹사이트에서는 캐싱되는데 ssr 페이지에서 뒤로가기시 화면전환없이 캐싱되는 방법이 있을까요?
-
미해결
Next getServerSideProps context.params에 favicon이 왜.. 때문일까요..?
브라우저 창 주소 - localhost:3000/nickname 컴포넌트 내부 import { useRouter } from 'next/router'; const MyPost = () => { const router = useRouter(); const { pagename } = router.query; console.log(pagename); // 결과 - nickname 정확히 출력 }; getServerSideProps 내부 export const getServerSideProps = wrapper.getServerSideProps(async (context) => { console.log(context.params); // 결과 - { pagename : 'favicon.ico' } ?? }); useRouter의 query와 context의 params가 같은 역할을 하는걸로 배웠는데... getServerSideProps에서 왠 'favicon.ico'가 ?? 출력이 되는걸까요...? 당황쓰...
-
해결됨Vue로 Nodebird SNS 만들기
[해결] v.trim()을 사용하면 해당 property를 읽을 수 없다고 하는데요~
아래 질문과 동일한 질문인데.. 이렇게 뜨는데... 혹시 다른 걸로 대체할 수 있는 방법이 있을까요? 음 해결했습니다.. 좀 이상하긴 한데 변수값?이 v가 아니기만 하면 되는 거 같아요.. v 를 text로 바꾸니까 에러 없이 잘 동작합니다. (참고로 기존 에러에서는 서버는 동작하는데 해당 에러가 title에 뜨고, 박스에 입력 자체가 불가능했습니다. 검색해봤는데 이유는 모르겠네요... )