묻고 답해요
161만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결탄탄한 백엔드 NestJS, 기초부터 심화까지
src 디렉토리 내의 폴더는 뭐라고 칭해야 하나요?
nest.js로 개인 프로젝트 진행 중에 갑자기 문뜩 든 생각인데요.빨간 색으로 동그라미 친 디렉토리는 뭐라고 불러야 하는 지 궁금합니다.해당 디렉토리에는 API가 구현되어있는데, 도메인이라고 불러야 하는지모듈이라고 불러야 하는지, 아니면 그냥 디렉토리인지 답변 해주실 수 있을까욥?
-
해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
데이터베이스 연결 싪패
DB연결 문제라고 해서, 처음부터 새로 생성해서 시도해보았으나, 에러 코드가 동일하게 출력됩니다ㅠㅠ ==============================시도해본 것들mysql 비밀번호 초기화, 재설정mysql db 다시 세팅dotenv 코드말고 직접 데이터베이스 정보 입력후 실행 터미널 메세지base) C:\Users\user\Downloads\master\a-nest> npm run db:create > a-nest@0.0.1 db:create > ts-node ./node_modules/typeorm-extension/dist/cli/index.js db:create -d ./dataSource.ts C:\Users\user\Downloads\master\a-nest\node_modules\mysql2\lib\packets\packet.js:728 const err = new Error(message); ^ Error: Access denied for user ''@'localhost' (using password: YES) at Packet.asError (C:\Users\user\Downloads\master\a-nest\node_modules\mysql2\lib\packets\packet.js:728:17) at ClientHandshake.execute (C:\Users\user\Downloads\master\a-nest\node_modules\mysql2\lib\commands\command.js:29:26) at Connection.handlePacket (C:\Users\user\Downloads\master\a-nest\node_modules\mysql2\lib\connection.js:489:32) at PacketParser.onPacket (C:\Users\user\Downloads\master\a-nest\node_modules\mysql2\lib\connection.js:94:12) at PacketParser.executeStart (C:\Users\user\Downloads\master\a-nest\node_modules\mysql2\lib\packet_parser.js:75:16) at Socket.<anonymous> (C:\Users\user\Downloads\master\a-nest\node_modules\mysql2\lib\connection.js:101:25) at Socket.emit (node:events:513:28) at Socket.emit (node:domain:489:12) at addChunk (node:internal/streams/readable:324:12) at readableAddChunk (node:internal/streams/readable:297:9) { code: 'ER_ACCESS_DENIED_ERROR', errno: 1045, sqlState: '28000', sqlMessage: "Access denied for user ''@'localhost' (using password: YES)", sql: undefined. } app.module.ts@Module({ imports: [ ConfigModule.forRoot({ isGlobal: true }), TypeOrmModule.forRoot({ type: 'mysql', host: 'localhost', port: 3307, autoLoadEntities: true, entities: [ ChannelChats, ChannelMembers, Channels, DMs, Mentions, Users, WorkspaceMembers, Workspaces, ], keepConnectionAlive: true, migrations: [__dirname + '/migrations/*.ts'], charset: 'utf8mb4_general_ci', synchronize: false, logging: true, }), TypeOrmModule.forFeature([Users]), UsersModule, WorkspacesModule, ChannelsModule, ], controllers: [AppController], providers: [AppService], }) export class AppModule implements NestModule { configure(consumer: MiddlewareConsumer): void { consumer.apply(LoggerMiddleware).forRoutes('*'); // consumer.apply(FrontendMiddleware).forRoutes({ // path: '/**', // method: RequestMethod.ALL, // }); } }
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
[ODM-MongoDB접속] post요청 후 몽고DB에서 조회가 안됩니다.
postman에서 post요청 후 get으로 확인했을 때 잘 받아와집니다. MongoDB Compass에 localhost:27017로 연결해서 refresh해도 mydocker DB가 조회가 안됩니다. docker - mongodb가 연결이 잘 안된건지 어렵습니다.. 어떻게 확인할 수 있을까요?import express from 'express' import { checkValidationPhone, getToken, sendTokenToSMS } from './phone.js'; import swaggerUi from 'swagger-ui-express' import swaggerJSDoc from 'swagger-jsdoc' import { options } from './swagger/config.js' import cors from 'cors' import { checkValidationEmail, getWelcomeTemplate, sendWelcomeTemplateToEmail } from './email.js'; import mongoose from 'mongoose' import { Board } from './models/board.model.js' const app = express() app.use(cors()) app.use(express.json()); app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerJSDoc(options))); app.get('/boards', async (req, res) => { // const result = [ // { // number: 1, // writer: '철수', // title: '제목입니다~~~', // contents: '내용이에요@@@', // }, // { // number: 2, // writer: '영희', // title: '영희 제목입니다~~~', // contents: '영희 내용이에요@@@', // }, // { // number: 3, // writer: '훈이', // title: '훈이 제목입니다~~~', // contents: '훈이 내용이에요@@@' // }, // ]; const result = await Board.find() //DB접속해서 가져오는 내용 위랑동일 res.send(result) }) app.post('/boards', async (req, res) => { console.log(req.body); // 1. 데이터를 등록하는 로직 => DB에 접속해서 데이터 저장하기 const board = new Board({ writer: req.body.writer, title: req.body.title, contents: req.body.contents, }); await board.save(); //원래는 SQL문법을 써야하지만 mongoose가 자동으로 변환해줌.(ORM, ODM) // 2. 저장 결과 응답 주기 res.send("게시물 등록에 성공하였습니다."); }); app.post('/tokens/phone', (req, res) => { const myphone = req.body.myphone; const isValid = checkValidationPhone(myphone); if (isValid) { const mytoken = getToken(); sendTokenToSMS(myphone, mytoken); res.send('인증완료!!!'); } }); app.post("/users", (req, res) => { const user = req.body.myuser const isValid = checkValidationEmail(user.email) if(isValid){ const mytemplate = getWelcomeTemplate(user) sendWelcomeTemplateToEmail(user.email, mytemplate) res.send("가입완료!") } }) //몽고DB 접속 mongoose.connect("mongodb://my-database:27017/mydocker") // localhost로 접속하게되면 express 도커안에서의 localhost이기때문에 dockercompose로 묶인 my-database-1 컴퓨터로 들어가야함. // 단, dockercompose로 묶어뒀기 때문에 이름만 입력해서 진입가능(네임리졸루션). // Backend API 서버 오픈 app.listen(3000, () => console.log(`exemple app listening on port ${3000}`))
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
노션 자료에 링크가
노션 자료 중결제 - FrontEnd 적용페이지 안에 있는 링크가Page not found 로 나옵니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
몽고디비 접속 문제
노션에 써있는걸로 sudo systemctl start mongod 실행하면 실행이 안되서공식문서에서 찾아보니 sudo service mongod start를 입력하면 starting database mongod 라고 뜬 후 fail이 뜹니다.... localhost:27017로 접속을 하면 잘 뜨긴 하는데 해결 방법이 없을까요 ??
-
해결됨탄탄한 백엔드 NestJS, 기초부터 심화까지
tsc-watch
이거는 nodemon이랑 비슷한 개념인가요?..
-
해결됨탄탄한 백엔드 NestJS, 기초부터 심화까지
Mongoose API document
imports: [MongooseModule.forFeature([{ name: Cat.name, schema: CatSchema }])],에서 왜 name, schema 를 가지는 객체가 필요한지 궁금해서 타고 들어가봤더니, ModelDefinition타입이더라구요. 패키지에 도큐먼트 작성된 것이 없어서npm mongoose , nestjs/mongoose둘 다 찾아봤는데 mongoose 도큐먼트에는 따로 없었고,nestjs/mongoose 는 도큐먼트가 아예 안보이더라구요.. API 가 궁금할 때에는 어떤 방법으로 찾아 볼 수 있을까요..?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
도커내부 접속 안됨
docker run 이미지ID 하고 새로운 터미널 열어서 docker ps 로 containerID 확인 후docker exec -it 명령어 사용해서 도커 내부로 들어가려고 하면 OCI runtime exec failed: exec failed: unable to start container process: exec: "C:/Program Files/Git/usr/bin/bash": stat C:/Program Files/Git/usr/bin/bash: no such file or directory: unknown이런식으로 오류가 뜹니다 왜 그런건가요??해결 방법 알려주세요!
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
N:M tag 부분 구현 중 findOne 조회 부분 에러
products.service.ts에서 create 부근에 tag를 저장 하기 전 tag를 미리 조회하는 부분을 구현 중인데 findOne에서 {name: tagname} 을 구현하려고 할 때 다음과 같은 에러가 발생합니다. save에서는 에러가 발생하지 않는데 findOne 조회 부분만 에러가 발생하네요관련된 코드 같이 보내드립니다.createProduct.input.tsimport { InputType, Field, Int } from '@nestjs/graphql'; import { Min } from 'class-validator'; import { ProductSaleslocationInput } from 'src/apis/productsSaleslocation/entities/dto/productSaleslocation.input'; @InputType() export class CreateProductInput { @Field(() => String) name: string; @Field(() => String) description: string; @Min(0) @Field(() => Int) price: number; @Field(() => ProductSaleslocationInput) productSaleslocation: ProductSaleslocationInput; @Field(() => String) productCategotyId: string; @Field(() => [String]) productTags: string[]; } products.entity.tsimport { Field, Int, ObjectType } from '@nestjs/graphql'; import { ProductCategory } from 'src/apis/productsCategory/entities/productsCategory.entity'; import { ProductTag } from 'src/apis/productsTags/productTags.entity'; import { User } from 'src/apis/users/users.entity'; import { Column, DeleteDateColumn, Entity, JoinColumn, JoinTable, ManyToMany, ManyToOne, OneToOne, PrimaryGeneratedColumn, } from 'typeorm'; import { ProductSaleslocation } from '../../productsSaleslocation/entities/productsSaleslocation.entity'; @Entity() @ObjectType() export class Product { @PrimaryGeneratedColumn('uuid') @Field(() => String) id: string; @Field(() => String) @Column() name: string; @Field(() => String) @Column() description: string; @Field(() => Int) @Column() price: number; @Field(() => Boolean) @Column({ default: false }) isSoldout: boolean; @DeleteDateColumn() deletedAt: Date; @Field(() => ProductSaleslocation) @JoinColumn() @OneToOne(() => ProductSaleslocation) productSaleslocation: ProductSaleslocation; @Field(() => ProductCategory) @ManyToOne(() => ProductCategory) productCategory: ProductCategory; @Field(() => User) @ManyToOne(() => User) user: User; @JoinTable() @ManyToMany(() => ProductTag, (productTags) => productTags.products) @Field(() => [ProductTag]) productTags: ProductTag[]; } productTags.entity.tsimport { Field, ObjectType } from '@nestjs/graphql'; import { Column, Entity, ManyToMany, PrimaryGeneratedColumn } from 'typeorm'; import { Product } from '../products/entities/products.entity'; @Entity() @ObjectType() export class ProductTag { @Field(() => String) @PrimaryGeneratedColumn('uuid') id: string; @Column() @Field(() => String) name: string; @Field(() => [Product]) @ManyToMany(() => Product, (products) => products.productTags) products: Product[]; } products.service.tsimport { Product } from './entities/products.entity'; import { Injectable, UnprocessableEntityException } from '@nestjs/common'; import { Repository } from 'typeorm'; import { InjectRepository } from '@nestjs/typeorm'; import { ProductSaleslocation } from '../productsSaleslocation/entities/productsSaleslocation.entity'; import { ProductTag } from '../productsTags/productTags.entity'; @Injectable() export class ProductService { constructor( @InjectRepository(Product) private readonly productRepository: Repository<Product>, @InjectRepository(ProductSaleslocation) private readonly productSaleslocationRepository: Repository<ProductSaleslocation>, @InjectRepository(ProductTag) private readonly productTagRepository: Repository<ProductTag>, ) {} async findAll() { return await this.productRepository.find({ relations: ['productSaleslocation', 'productCategory', 'productTags'], }); } async findOne({ productId }) { return await this.productRepository.findOne({ where: { id: productId }, relations: ['productSaleslocation', 'productCategory', 'productTags'], }); } async create({ createProductInput }) { // 1. 상품만 등록하는 경우 // const result = await this.productRepository.save({ // ...createProductInput, // // 하나 하나 직접 나열하는 방식 // // name: createProductInput.name, // // description: createProductInput.description, // // price: createProductInput.price, // }); // 2. 상품과 상품거래 위치 같이 등록 const { productSaleslocation, productCategotyId, productTag, ...product } = createProductInput; const result = await this.productSaleslocationRepository.save({ ...productSaleslocation, }); // productTag // ["#electronics, #computer"] const result2 = []; // [{name: ..., id: ...}] for (let i = 0; i < productTags.length; i++) { const tagName = productTags[i].replace('#', ''); // check the tags that has already registered const checkTag = await this.productTagRepository.findOne({ name: tagName, }); // if the tags has been existed if (checkTag) { result2.push(checkTag); // if the tags hasn't been existed } else { const newTag = await this.productTagRepository.save({ name: tagName }); result2.push(newTag); } } const result3 = await this.productRepository.save({ ...product, productSaleslocation: result, // result 통째로 넣기 vs id만 넣기 productCategory: { id: productCategotyId }, productTags: result2, }); return result3; } async update({ productId, updateProductInput }) { const myProduct = await this.productRepository.findOne({ where: { id: productId }, }); const newProduct = { ...myProduct, id: productId, ...updateProductInput, }; return await this.productRepository.save(newProduct); } async checkSoldOut({ productId }) { const product = await this.productRepository.findOne({ where: { id: productId }, }); if (product.isSoldout) { throw new UnprocessableEntityException('Sold out'); } // if(product.isSoldout) { // throw new HttpException('이미 판매 완료 된 상품입니다.', HttpStatus.UNPROCESSABLE_ENTITY) // } } async delete({ productId }) { // 1. 실제 삭제 // const result = await this.productRepository.delete({ id: productId }); // return result.affected ? true : false // 2. 소프트 삭제(직접 구현) - isDeleted // this.productRepository.update({ id: productId }, { isDeleted: true }); // 3. 소프트 삭제(직접 구현) - deletedAt // this.productRepository.update({ id: productId }, { deletedAt: new Date() }); // 4. 소프트 삭제(TypeORM 제공) - softRemove - id로만 삭제 가능 // this.productRepository.softRemove({ id: productId }); // 4 . 소프트 삭제(TypeORM 제공) - softDelete const result = await this.productRepository.softDelete({ id: productId }); return result.affected ? true : false; } } 내용 확인 부탁드립니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
안녕하세요 질문있습니다!
@ObjectType이랑 @EntryType이랑 같이 사용을 할수는 없는건가요??dto와 entry가 다른부분이 없어서 같이 쓰는게 낫겠다싶어서 시도하려니 안되네요확실히 역할을 나눠야하는건가요??
-
해결됨탄탄한 백엔드 NestJS, 기초부터 심화까지
[2023.03.04 기준] 프론트앤드 빌드 방법 정리
해당 강의 프론트앤드 빌드 방법 정리합니다.강의 그대로 따라할 시에 제가 구성한 환경에서는 에러가 지속적으로 발생했습니다.에러 정보: Error: error:0308010C:digital envelope routines::unsupported환경 정보OS: MacOS Ventura 13.3 베타npm, npx version: 9.5.0node version: v18.14.2이에 따른 해결 방법 정리해봅니다. :)강의에 있는 git 프로젝트를 clone 한다.frontenddev 폴더 접근package.json 파일을 아래와 같이 작성 (dependencies 에서 antd 는 4.24.0 버전, 그 외는 2023.03.04 기준으로 최신 버전입니다. )frontenddev 폴더에서 sudo npx @next/codemod new-link . 을 실행한다.components/layouts/AccountForm.tsx 파일에서 <Link href="/signup"> 을 <Link href="/signup" legacyBehavior> 으로 변경Error: Invalid <Link> with <a> child. Please remove <a> or use <Link legacyBehavior>. 해결하기 위함입니다.참고 블로그: https://steady-learner.tistory.com/entry/Nextjs-Error-Invalid-Link-with-a-child-Please-remove-a-or-use-Link-legacyBehavior-%EC%98%A4%EB%A5%98npm i 후 npm run dev 하면 실행 됨을 확인할 수 있습니다.
-
해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
webstorm과 vscode
강의에서는 webstorm이 사용되던데,vscode로 강의를 따라가는데 어려움이 없을까요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
나만의미니프로젝트 cheerio관련질문
원하는 키워드의 값을 담은 상수를 console.log(key,value) 하면 줄바꿈되면서 안에 있는 전체 값들이 나오더라구요 ( const key = $(el).attr("property").split(":")[1]; const value = $(el).attr("content"); 부분입니다)근데 이 값들을 db에 저장하려 for문을 이용해 배열에 넣어봤더니 console.log(key,value)해서 나온 값들이 아닌 마지막 값만 들어갑니다 key와 value에 어떤 형태로 값이 스크랩핑되어 들어가있는건가요..?상수에 배열형태로 들어간 것도 아니고 한줄로 값이 들어간 것도 아니고 .. console.log하면 전체가 나오기는 하나줄바꿈이 되어 나와서 갈피를 못잡겠습니다..스크래핑한 값을 어떻게 저장을하고 넘겨야할지 db로 넘겨야할지 전혀 모르겠습니다................................. 이틀동안 찾아봐도 해결이 안되어서 질문 남깁니다..
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
배포 강의를 시작하시는 분들은 인스턴스 환경변수 분리까지 보신 후에 하시면 좋을 것 같습니다.
처음에 .env파일을 깃허브에 올리시길래 띠용했지만 곧바로 수정하시는군요.지금은 연습 중이라서 올라가도 크게 문제가 없을 것 같고, 또한, 강사님께서 .env가 깃허브에 올라갔을 때 어떻게 대처하는지 알려주시기 때문에 연습 용도로도 좋아보입니다..env파일을 올리는게 찜찜하신 분들은 인스턴스 환경변수 분리까지 보신 뒤에 하시는게 좋을 것 같고, 나는 .env가 노출 된 상황을 한 번 연습해보고 싶다. 하시는 분들은 차례대로 진행하는 것도 좋을 것 같습니다!
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
userRepositorySpySave 왜 ? 0 이 안나와? 는 보십시오.
```typescriptasync create({ email, password, mobileNumber }) { const user = await this.userRepository.findOne({ where: { email } }); if (user) throw new ConflictException('이미 등록된 이메일 입니다.'); return await this.userRepository.save({ email, password, mobileNumber }); }일때 findOne({ where: { email } }) { const users = this.mydb.filter((el) => el.email === email); if (users.length) return { ...users[0] }; return null; }입니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
1:1 관계 등록 API 강의 creatProduct 시 에러가 발생합니다
삽입시 address 값을 입력했는데도 default 값이 설정되어있지 않다고 에러가 뜹니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
nest 실행 (npm run start:dev)이 너무 오래 걸려요
typescript 기초 강의에서 nest를 처음 실행했는데 실행 시 너무 오래 걸립니다..(약 20~30분 정도) windows os에서 실행 햇는데 이유가 있을까요?현재 컴퓨터 사양은 Memory 32G 에 RAM 16 Core 입니다.매번 이렇게 시간이 걸리면 현실적으로 test가 불가능해서 방법을 구하고자 합니다. +추가yarn으로 실행해봐도 비슷하네요..Windows OS에서 WSL 통해서 Ubuntu 환경에서 실행하고 있습니다.
-
해결됨탄탄한 백엔드 NestJS, 기초부터 심화까지
이 강의를 들을 때 필요한 언어공부가 있을까요? 추천 부탁드립니다,
제가 백엔드 공부도 처음이고 언어 공부에서도 c 이후로 는 거의 하지 않았습니다. 프로젝트 단계로 넘어가기 전 언어 공부를 해야 더 도움이 될거같은데 typescript 나 자바스크립트를 선행 언어 공부를 한 후에 들어야 도움이 더 잘 될까요? 아니면 공부 없이도 듣기 괜찮을 까요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
API-Gateway2 섹션 Apollo 서버 구동 에러
Auth와 Resource App 시작 시 아래 사진과 같은 에러가 발생합니다. 강의와 노션에 있는 코드를 그대로 작성했다고 생각하여 패키지 버전 문제로 추정됩니다.현재 제가 사용중인 패키지입니다.강의 중 사용중인 패키지 버전을 공유받고 싶습니다. 해당 오류에 대한 구글링에 실패해서 추가적으로 혹시 알고계신 레퍼런스 있으시면 알려주시면 감사드리겠습니다.
-
해결됨탄탄한 백엔드 NestJS, 기초부터 심화까지
'수업 노트를 확인해 주세요 :)'의 수업노트 위치가 어디인가요?
'첫 시작' 챕터 영상 레이아웃의 하단에 '수업 노트를 확인해 주세요 :)'가 있는데 해당하는 수업노트가 어디 있는건가요?