묻고 답해요
160만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
GqlExecutionContext가 없다고 나옵니다.
import { GqlExecutionContext } from '@nestjs/graphql';@nestjs/graphql 모둘에 내보낸 맴버 GqlExecutionContext가 없다고 에러가 뜹니다
-
해결됨탄탄한 백엔드 NestJS, 기초부터 심화까지
npm run start:dev 실행 시 에러..
안녕하세요 현재 수강중입니다..계속해서 에러가 발생하네요.. 지치네요.......ㅠㅠㅠ똑같이 한거같은데 다음과 같은 에러가 발생합니다..무엇이 문제일까요??
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
JWT 토큰이 어디 저장되어 있는 건가요?
인증을 하면 JWT 액세스 토큰을 전달 받고, fetchUser의 header에 전달 받은 토큰을 넘겨 인가를 받는다는 것을 알았습니다.이 때, JWT 토큰에 대해 서버가 알고 있어야 하는데 이것이 어디에 저장되어 있는 건가요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
강의별 전체 코드 git으로 받아볼 수 있을까요?
안녕하세요선생님께서 강의하시는 강의별 전체 코드를 받아볼 수 있는 git 주소가 있을까요?전체 정답 코드를 보지 못하고 따라하다보니 에러가 많이 나서 선생님 것으로 확인해보고자 합니다. 그럼 답변 기다리겠습니다. 감사합니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
products.service.ts 의 update 함수에 대한 질문입니다.
id 값은 myproduct 안에 이미 있는데newProduct 에 id: productId 이렇게 넣어주는 이유가 있나요?45번째 줄을 주석 처리해도 차이 없이 작동하더라구요.
-
미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
socket.io 채팅이 안써져요(안보내져요)
socket.io가 프론트하고 백엔드하고 연결이 되었는지 궁금합니다.각각의 서버 구동은프론트는 inflearn/project/sleact/front 에서 npm run dev 로 실행하고 있고, 백엔드는 개인적인 폴더를 하나 파서 아래와 같이 서버를 npm run start:dev 로구동하고 있습니다.프론트 서버 : 3090백엔드서버 : 3095socket.io를 이용해서 채팅을 구현해보려 하는 도중 테스트 해보는데 채팅이 안보내집니다.아래의 사진과 같이 '123' 이라는 채팅을 치고 엔터를 누르면 그대로 있습니다.개발자 도구를 키고 Network탭 부분에 나온 스샷개발자도구 console.log 창 스샷백엔드 websocket.io 설치버전 프론트 웹소켓 설치버전
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
강의에서 배운 상품 CRUD를 RESTAPI 로 바꾸기
강의에서 배운 상품 CRUD를 RESTAPI로 바꿔보고 싶은데, 이게 해볼만한 시도일까요? 참조할만한 자료가 있을까요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
N:M 등록 / 조회 API
query{ fetchProduct(productId:"7967c808-532f-48e8-87b7-4f4536ab1903"){ id name description price isSoldout productSaleslocation{ id address addressDetail lat lng meetingTime } productCategory{ id name } productTags{ id name } } } { "errors": [ { "message": "Cannot return null for non-nullable field Query.fetchProduct.", "locations": [ { "line": 2, "column": 3 } ], "path": [ "fetchProduct" ], "extensions": { "code": "INTERNAL_SERVER_ERROR", "exception": { "stacktrace": [ "Error: Cannot return null for non-nullable field Query.fetchProduct.", " at completeValue (C:\\Users\\enter\\OneDrive\\바탕 화면\\agarang-camp\\19-01-typeorm-crud-many-to-many\\node_modules\\graphql\\execution\\execute.js:594:13)", " at C:\\Users\\enter\\OneDrive\\바탕 화면\\agarang-camp\\19-01-typeorm-crud-many-to-many\\node_modules\\graphql\\execution\\execute.js:486:9", " at processTicksAndRejections (node:internal/process/task_queues:96:5)", " at async Promise.all (index 0)", " at execute (C:\\Users\\enter\\OneDrive\\바탕 화면\\agarang-camp\\19-01-typeorm-crud-many-to-many\\node_modules\\apollo-server-core\\src\\requestPipeline.ts:501:14)", " at processGraphQLRequest (C:\\Users\\enter\\OneDrive\\바탕 화면\\agarang-camp\\19-01-typeorm-crud-many-to-many\\node_modules\\apollo-server-core\\src\\requestPipeline.ts:407:22)", " at processHTTPRequest (C:\\Users\\enter\\OneDrive\\바탕 화면\\agarang-camp\\19-01-typeorm-crud-many-to-many\\node_modules\\apollo-server-core\\src\\runHttpQuery.ts:436:24)" ] } } } ], "data": null } 똑같이 따라헀는데, fetchproduct 부분에서 왜 이런 오류가 발생하는 것일까요? product.entity.ts 를 아래와 같이 nullable: true로 수정했는데도 플레이 그라운드에서 똑같은 에러가 나옵니다. ======================== import { Field, Int, ObjectType } from '@nestjs/graphql'; /* eslint-disable prettier/prettier */ // product.entity.ts import { ProductCategory } from 'src/apis/productCategory/entities/productCategory.entity'; import { ProductSaleslocation } from 'src/apis/productsSaleslocation/entities/productSaleslocation.entity'; import { ProductTag } from 'src/apis/productTags/entities/productTag.entity'; import { User } from 'src/apis/users/entities/user.entity'; import { Column, DeleteDateColumn, Entity, JoinColumn, JoinTable, ManyToMany, ManyToOne, OneToOne, PrimaryGeneratedColumn, } from 'typeorm'; @Entity() @ObjectType() export class Product { @PrimaryGeneratedColumn('uuid') @Field(() => String) id: string; @Column() @Field(() => String) name: string; @Column() @Field(() => String) description: string; @Column() @Field(() => Int) price: number; @Column({ default: false }) //시작시 디폴트값 @Field(() => Boolean) isSoldout: boolean; // soldedAt: Date // @Column({ default: false }) //시작시 디폴트값 // @Field(() => Boolean) // isDeleted: boolean; // @Column({ default: null }) //시작시 디폴트값 // @Field(() => Date) // DeletedAt: Date; @DeleteDateColumn() @Field({ nullable: true }) deletedAt: Date; @JoinColumn() @OneToOne(() => ProductSaleslocation) @Field(() => ProductSaleslocation) productSaleslocation: ProductSaleslocation; @ManyToOne(() => ProductCategory) @Field(() => ProductCategory) productCategory: ProductCategory; @ManyToOne(() => User) @Field(() => User, { nullable: true }) user: User; @JoinTable() @ManyToMany(() => ProductTag, (productTags) => productTags.products) @Field(() => [ProductTag]) productTags: ProductTag[]; } /*tag가 배열이다 그래프QL에서 배열은 양쪽으로 감싸는 게 배열이다. */ 위 product.enttity.ts를 수정한 이유는 DB에 deletedAt 컬럼이 null, userId 컬럼이 null로 되어 있어서 아래와 같이 추가해주었습니다. 그래도 똑같은 에러가 발생하네요. @Field({ nullable: true }) deletedAt: Date; @ManyToOne(() => User) @Field(() => User, { nullable: true }) user: User;
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
1:1 관계 등록 API 질문입니다.
//18-03의 방법 2. 상품과 상품 거래위치를 같이 등록하는 경우 async create({ createProductInput }) { const { productSaleslocation, ...product } = createProductInput; console.log( '어떻게 받아오는지 createProductInput:::::::::찍어보자 ', createProductInput, ); console.log( '서비스단에서 productSaleslocation::::::::', productSaleslocation, ); // console.log('서비스단에서...product:::::::::::::::', ...product); const result = await this.productSaleslocationRepository.save({ ...productSaleslocation, // }); console.log('서비스단에서 result:::::', result); const result2 = await this.productRepository.save({ ...product, productSaleslocationId: result.id, }); console.log('서비스단에서 result2:::::', result2); return result2; } 위를 grpahql 에서 데이터를 전송해보면, 터미널창에서아래와 같이 나옵니다. 어떻게 받아오는지 createProductInput:::::::::찍어보자 [Object: null prototype] { name: '마우스', description: '참좋은마우스', price: 2000, productSaleslocation: [Object: null prototype] { address: '구로', addressDetail: '구로역', lat: 1, lng: 1, meetingTime: 2022-10-30T00:00:00.000Z } } 서비스단에서 productSaleslocation:::::::: [Object: null prototype] { address: '구로', addressDetail: '구로역', lat: 1, lng: 1, meetingTime: 2022-10-30T00:00:00.000Z } query: START TRANSACTION query: INSERT INTO `product_saleslocation`(`id`, `address`, `addressDetail`, `lat`, `lng`, `meetingTime`) VALUES (?, ?, ?, ?, ?, ?) -- PARAMETERS: ["f6bc848d-42ff-42c5-a454-39e8a9106dac","구로","구로역",1,1,"2022-10-30T00:00:00.000Z"] query: COMMIT 서비스단에서 result::::: { address: '구로', addressDetail: '구로역', lat: 1, lng: 1, meetingTime: 2022-10-30T00:00:00.000Z, id: 'f6bc848d-42ff-42c5-a454-39e8a9106dac' } query: START TRANSACTION query: INSERT INTO `product`(`id`, `name`, `description`, `price`, `isSoldout`, `deletedAt`, `productSaleslocationId`, `productCategoryId`, `userId`) VALUES (?, ?, ?, ?, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) -- PARAMETERS: ["a09e9c56-4b45-420d-98ec-c075da6014e0","마우스","참좋은마우스",2000] query: SELECT `Product`.`id` AS `Product_id`, `Product`.`isSoldout` AS `Product_isSoldout`, `Product`.`deletedAt` AS `Product_deletedAt` FROM `product` `Product` WHERE ( `Product`.`id` = ? ) AND ( `Product`.`deletedAt` IS NULL ) -- PARAMETERS: ["a09e9c56-4b45-420d-98ec-c075da6014e0"] query: COMMIT 서비스단에서 result2::::: { name: '마우스', description: '참좋은마우스', price: 2000, productSaleslocationId: 'f6bc848d-42ff-42c5-a454-39e8a9106dac', deletedAt: null, id: 'a09e9c56-4b45-420d-98ec-c075da6014e0', isSoldout: false } 어떻게 받아오는지 createProductInput:::::::::찍어보자 [Object: null prototype] { name: '마우스', description: '참좋은마우스1', price: 2000, productSaleslocation: [Object: null prototype] { address: '구로', addressDetail: '구로역', lat: 1, lng: 1, meetingTime: 2022-10-30T00:00:00.000Z } } 서비스단에서 productSaleslocation:::::::: [Object: null prototype] { address: '구로', addressDetail: '구로역', lat: 1, lng: 1, meetingTime: 2022-10-30T00:00:00.000Z } query: START TRANSACTION query: INSERT INTO `product_saleslocation`(`id`, `address`, `addressDetail`, `lat`, `lng`, `meetingTime`) VALUES (?, ?, ?, ?, ?, ?) -- PARAMETERS: ["33a4c94a-886d-4f76-9226-a363afc4b7e4","구로","구로역",1,1,"2022-10-30T00:00:00.000Z"] query: COMMIT 서비스단에서 result::::: { address: '구로', addressDetail: '구로역', lat: 1, lng: 1, meetingTime: 2022-10-30T00:00:00.000Z, id: '33a4c94a-886d-4f76-9226-a363afc4b7e4' } query: START TRANSACTION query: INSERT INTO `product`(`id`, `name`, `description`, `price`, `isSoldout`, `deletedAt`, `productSaleslocationId`, `productCategoryId`, `userId`) VALUES (?, ?, ?, ?, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) -- PARAMETERS: ["a97bb588-3074-4f1b-abaf-a9d244616dd3","마우스","참좋은마우스1",2000] query: SELECT `Product`.`id` AS `Product_id`, `Product`.`isSoldout` AS `Product_isSoldout`, `Product`.`deletedAt` AS `Product_deletedAt` FROM `product` `Product` WHERE ( `Product`.`id` = ? ) AND ( `Product`.`deletedAt` IS NULL ) -- PARAMETERS: ["a97bb588-3074-4f1b-abaf-a9d244616dd3"] query: COMMIT 서비스단에서 result2::::: { name: '마우스', description: '참좋은마우스1', price: 2000, productSaleslocationId: '33a4c94a-886d-4f76-9226-a363afc4b7e4', deletedAt: null, id: 'a97bb588-3074-4f1b-abaf-a9d244616dd3', isSoldout: false } 강의에서 설명해주신 코드는 const result2 = await this.productRepository.save({ ...product, productSaleslocation: result, }); console.log('서비스단에서 result2:::::', result2); return result2; }...product를 하면 product 테이블에 product와 관련된 데이터(name, description, price) 가 DB 테이블에 들어가는 것은 이해가 되었는데, productSaleslocation: result 라고 하면, DB에lnt, lng, meetingtime, address, adressDetail까지 전부 들어가는 게 아닌가요? 왜 DB를 확인해보면, productSaleslocation의 id 값만 productSaleslocationId 컬럼에 들어가게 되는 것인가요? 그래서 product 테이블에 productSalesloactionId 라는 컬럼이 있어서 아래와 같이 result2 코드를 작성해보았습니다. const result2 = await this.productRepository.save({ ...product, productSaleslocationId: result.id, }); 이렇게 코드를 작성하면, 상품테이블에 productSaleslocationId 컬럼이 있으니, productSaleslocationId : result.id 를 해줘서 DB에 productSaleslocationId 값을 넣을 수 있는게 왜 아닌지 이해가 가지 않습니다.왜 productSaleslocationId : result.id 라고 하면 터미널창에는 찍히지만,DB에 아무것도 들어가지 않는 것일까요?오히려 productSaleslocation: result 라고 하면, productSaleslocation의 lnt, lng, meetingtime, address, adressDetail 은 하나도 들어가지 않고, 어떠한 에러가 발생하지 않고, productSaleslocation의 id값만 외래키로 DB에 잘 들어가게 되는것일까요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
PartialType과 OmitType 동시 적용
포트폴리오 과정의 'N:M 등록 및 조회/회원가입'을 처리하는 중 질문할 것이 나와 질문을 드립니다.User의 생성부분을 구현하기 위해 CreateUserInput 타입을 만들었고 해당 부분에서 유저 아이디, 패스워드, 이메일 등을 기입하도록 하였습니다.@InputType() export class CreateUserInput { @Field(() => String) loginId: string; @Field(() => String) @MinLength(8) password: string; @Field(() => String) name: string; @Field(() => String) address: string; @Field(() => String) @IsPhoneNumber('KR') phone: string; @Field(() => String) @IsEmail() @Transform(({ value }) => value.toLowerCase()) email: string; } 그리고 User의 수정 부분을 구현하기 위해 UpdateUserInput 타입을 만들었습니다. 단순히 OmitType으로 CreateUserInput 부분을 넘겨 만들었습니다만, API 동작에서 패스워드 부분을 넘기지 않으면 필수 항목을 입력하지 않았다고 수정이 되지 않았습니다. @InputType() export class UpdateUserInput extends OmitType(CreateUserInput, ['loginId', 'email'], InputType) { } 그래서 그냥 PartialType까지 상속하고 싶었습니다만 타입스크립트도 다중 상속을 지원하지 않는지 OmitType과 PartialType을 함께 쓸 수 없었습니다. 이러면 그냥 CreateUserInput처럼 전부 구현할 수 밖에 없나요? API 부분에서 넘기지 않은 부분은 그냥 그대로 냅두는 것을 목적으로 합니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
테이블 생성 관련 질문
1. 강의를 따라 하다 보면 중간 테이블의 이름이product_product_tags_product_tag라고 만들어지는데중간 테이블의 이름은 어떤 걸 기준으로, 어떤 규칙으로 만들어지는 건가요?2. 자동으로 생성된 중간 테이블의 이름을 임의로 변경해도 되나요?3. 지금 만들어진 테이블들은 저희가 만들어 놓은 entity 파일을 기준으로서버를 실행하면 TypeOrm 이 만들어 주는 게 맞는 거죠?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
나만의 검색 API : 캐싱의 유효시간 관련, 폴링 시 일부 컬럼만을 ELK에 넣었을 때
안녕하세요. ELK와 Redis를 이용하여 검색 API 숙제를 하는 중 질문이 있습니다.캐시를 이용하여 검색 결과를 반환할 때, 폴링 등을 통해서 새로운 데이터가 들어온다면 기존의 캐시를 이용하지 못할 것 같은데요, 제 생각으로는 강의중 말씀해주신 정확도를 포기하는 대신 성능을 얻기 위해서 캐시를 일단 TTL 만료 이전까지 사용해야 할 것 같습니다만, 좋은 방법이 무엇일까요? 강의 내에서는 폴링을 통해 테이블 컬럼의 전체가 아닌 일부 컬럼만을 Elasticsearch에 넣으셨었는데 전체를 넣지않는 이유가 있을까요? (데이터가 커져서? Join 데이터를 포함하면 많아질 것 같기는 합니다.) 일부만 넣는 이유가 있다면 게시판 검색을 만든다고 생각하면 제가 생각한 아래의 방식으로도 사용되는 편일까요?1) ID를 포함하여 검색 결과 목록에 노출될 제목 등을 얻어오는 데에 ELK와 캐시를 이용2) 상세보기를 클릭했을 때는 DB 인덱스로 사용되는 ID를 이용하여 디비에서 필요한 모든 컬럼을 얻어오기 강의 막바지를 향해 달려가고 있습니다. 좋은 강의 제공해주셔서 감사드립니다.
-
해결됨탄탄한 백엔드 NestJS, 기초부터 심화까지
UseFilter 데코레이터에 인스턴스? 클래스?
공식문서 힌트에서,Prefer applying filters by using classes instead of instances when possible. It reduces memory usage since Nest can easily reuse instances of the same class across your entire module. 와 같이, 인스턴스 대신에 클래스를 사용하라고 나와있는데요,클래스를 사용하는 것이UseFIlter(HttpExceptionFilter) 가 아니라,UseFIlter(new HttpExceptionFilter()) 이렇게 사용하는 건가요..? 공식문서에서 클래스를 사용하는 것이 권장된다고 나와 있고 클래스로 사용하는 것이 1번인줄 이해했는데, 그 문장 이후에도 2번 과 같이 쓰여서 헷갈려서 질문 올립니다!
-
미해결따라하며 배우는 NestJS
async await 관련 질문입니다.
좋은 강의 영상 감사합니다. controller에서 service함수를 이용할때에는 async await 를 안써줘도 괜찮나요? 괜찮은것 같은데 혹시 그 이유는 무엇일까요..?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
맥사용자가 아닌경우 리눅스 설치를 위해 별도 컴퓨터가 있어야 할까요?
Docker - MongoDB 연결 수업전 까지 들었습니다.현재까지는 리눅스 설치 없이 문제없이 진행중 입니다. 질문1.맥북이 아닌경우컴퓨터 두대(리눅스, 인강용) 로 진행하는 건가요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
Docker 2 - API 패키징 "/" 슬러시 생략가능 여부 질문
질문1.아래 코드중에서 마지막 슬러시 " / " 는 생략 가능 가능하지요?Dockerfile WORKDIR /myfolder/COPY ./package.json /myfolder/COPY ./yarn.lock /myfolder/
-
미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
유닛테스트 도중 'findByEmail' 의 함수를 못찾고 있습니다.
문제점: 제목 그대로 유닛테스트 도중 'findByEmail' 의 함수를 못찾고 있습니다.<에러발생 사진><제 코드>users.service.spec.tsusers.service.ts추가질문 : 추가 질문으로 위로 올려 보시면 users.Service.spec.ts에서 두번째 사진중 빨간네모박스 체크를 했는데 기존 UsersServie 코드로 하면 모듈에서 인식을 못하는지 아래와 같은 에러가 떴습니다. 이거 다른해결 방법이 있나요?< 모듈 사진추가>users.module.tsapp.module.ts
-
미해결Node.js의 모든 것
create( ) - User 를 만들기 수업 관련
강의 잘듣고 있는데 제가 아직 초보라서 강의를 듣고 게시판이나 로그인 같은것들을 잘 구현할수 있을지 nest js 와 잘 연동할수 있을지 감이 안잡혀서요 혹시 prisma 강의에서 로그인, 로그아웃 게시판 만들기 이미지 업로드 구현 같은 구체적인 기능 구현 강의는 추가 안되나요?
-
미해결Node.js의 모든 것
prisma 설정하고 미들웨어 사용해보기 강의 관련 질문들
질문1prisma 설정하고 미들웨어 사용해보기까지의 schema.prisma 코드가 있으신가요? 질문2그리고 prisma.push 하면 schema.prisma 에 모델로 설정되어 있는 것들만 스키마의 테이블로 등록 되는건가요? 혹시 없는 테이블들이 pgadmin 에서 미리 만들어져 있을 경우 어떻게 되나요? prisma.push 만 사용하면 장고처럼 migrations migrate 따로 관리 안해도 되나요? 질문3프리즈마 서비스 생성자 함수에 다음과 같이 설정하면 프리즈마 쿼리와 에러 정보를 확인 할수 있다 그렇게 생각하면 되나요? 그리고 그게 미들웨어 방식으로 설정하는 거죠?질문4아래 코드에서 params 는 백엔드에서 orm 으로 넘기는 파라미터 정보 next 는 디비로부터 오는 정보가 맞나요? 그리고 이 미들웨어는 자동으로 실행되는건가요? return 값은 어디로 가나요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
소셜로그인 43:30
제 본인 프로젝트에 해당되는 내용입니다.구글인증까지는 무난하게 되는데요.1. 파란색이 Entity() 에서 뽑아온 Column명에 해당하는 변수로 알고 있습니다. 2. 구글인증을 통과한 후에 name, email, password를 req.user로 넣어서 보내주는 걸로 알고 있습니다. <질문의도>name, email, password를 req.user객체에 넣어서 받았으니, req.user.name,req.user.email,req.user.password,데이터를 꺼내서 개별적으로컬럼에 저장되는 변수에userName = req.user.nameuserEmail = req.user.emailuserPassword = req.user.password위와 같이 저장되어야 하지 않아 생각해 봅니다. 그런데 아래 오류메시지의 경우<property 'email' does not exist on type 'User & Pick<User, userEmail, userName, userPassword>↑왜(why) req.user에서 userEmail, userName,userPassword를 찾고 있는지 이해가 가지 않습니다.----------------------------------------------------------제가 지금 머릿속에서 뭔가 꼬인 것 같습니다.답변 부탁드릴께요.진도를 못나가고 있어요ㅠ