44,000원
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
createWorkspaceMembers 도 transaction 걸어줘야 하나요?
안녕하세요 이장우 닮은 제로초 선생님,// workspaces.service.ts async createWorkspaceMembers(url: string, email: string) { const workspace = await this.workspacesRepository.findOne({ where: { url }, relations: ['Channels'], }); // queryBuilder 버전 this.workspacesRepository .createQueryBuilder('workspaces') // typeorm은 innerJoin 하면 join한 테이블은 가져오지 않는데, // innerJoinAndSelect을 하면 join한 테이블을 다 가져온다. .innerJoinAndSelect('workspaces.Channels', 'channels') .getOne(); const user = await this.usersRepository.findOne({ where: { email } }); if (!user) return null; const workspaceMember = new WorkspaceMembers(); workspaceMember.WorkspaceId = workspace.id; workspaceMember.UserId = user.id; await this.workspaceMembersRepository.save(workspaceMember); const channelMember = new ChannelMembers(); channelMember.ChannelId = workspace.Channels.find( (v) => v.name === '일반', ).id; channelMember.UserId = user.id; await this.channelMembersRepository.save(channelMember); }강의에서 위와 같이 createWorkspaceMembers 를 작성하셨는데, 여기도 transaction을 걸어주는게 낫겠죠? 걸어주는게 맞다면, 아래와 같이 하면 되나요? async createWorkspaceMembers(url: string, email: string) { const queryRunner = this.dataSource.createQueryRunner(); await queryRunner.connect(); await queryRunner.startTransaction(); try { const workspace = await queryRunner.manager.findOne(Workspaces, { where: { url }, relations: ['Channels'], }); const user = await queryRunner.manager.findOne(Users, { where: { email } }); if (!user) return null; const workspaceMember = new WorkspaceMembers(); workspaceMember.WorkspaceId = workspace.id; workspaceMember.UserId = user.id; await queryRunner.manager.save(workspaceMember); const channelMember = new ChannelMembers(); channelMember.ChannelId = workspace.Channels.find( (v) => v.name === '일반', ).id; channelMember.UserId = user.id; await queryRunner.manager.save(channelMember); await queryRunner.commitTransaction(); } catch (error) { console.error(error); await queryRunner.rollbackTransaction(); } finally { await queryRunner.release(); } }
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
ENOENT: no such file or directory, stat \public\index.html
안녕하세요. 강사님지금 sleact db를 생성하였고 table도 다 생성된 상태입니다.nest-typeorm 폴더와 front 폴더 를 둘 다 실행시키면 api/users api를 요청할 때ENOENT: statusCode":404, no such file or directory, stat \public\index.html'이러한 에러가 발생합니다. middlewares/frontend.middleware.ts 파일의 경로가 잘못되어 있나 해서 res.sendFile( path.join(__dirname, '..', '..', '..', 'public', 'index.html'), );를 res.sendFile(path.join(__dirname, '../', 'public', 'index.html'));로 바꿔주었더니api 로그인 페이지로 가지 않고 바로 workspace로 가집니다.response도 html파일로 옵니다. (어떠한 api를 요청해도 마찬가지입니다.) 어떤 부분에서 잘못되었는지 감이 안 잡히네요...힌트라도 주시면 감사하겠습니다!
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
ExceptionsHandler 에러가 발생합니다.
class-transformer 도 같이 설치후 요청을 날려보면 아래와 같은 의도하지 않은 에러미세지가 출력됩니다.{ "statusCode": 500, "message": "Internal server error" }또 동시에 터미널에 아래와 같은 에러 로그가 출력됩니다.[Nest] 8570 - 2023. 05. 27. 오전 10:48:03 ERROR [ExceptionsHandler] data and salt arguments required Error: data and salt arguments required at Object.hash (/Users/apple/Documents/sideProjects2/sleactNestJS/node_modules/bcrypt/bcrypt.js:137:17) at /Users/apple/Documents/sideProjects2/sleactNestJS/node_modules/bcrypt/promises.js:29:12 at new Promise (<anonymous>) at Object.module.exports.promise (/Users/apple/Documents/sideProjects2/sleactNestJS/node_modules/bcrypt/promises.js:20:12) at Object.hash (/Users/apple/Documents/sideProjects2/sleactNestJS/node_modules/bcrypt/bcrypt.js:133:25) at UsersService.postUsers (/Users/apple/Documents/sideProjects2/sleactNestJS/dist/main.js:426:55) at processTicksAndRejections (node:internal/process/task_queues:96:5) at async UsersController.join (/Users/apple/Documents/sideProjects2/sleactNestJS/dist/main.js:1247:9)ChatGPT에 문의해보니 bcrypt에러 같다고 하는데, bcrypt는 수정하지 않았고 문제도 없어보입니다. 제가 강의를 보며 수정한 코드는 4군데 입니다.users.service.ts 에 기존 Exception 코드 날리기async postUsers(email: string, nickname: string, password: string) { const user = await this.usersRepository.findOne({ where: { email } }); if (user) { throw new UnauthorizedException('이미 존재하는 사용자입니다'); }Users.ts entity에 Validation 추가하기 @IsEmail() @ApiProperty({ example: 'kim@gmail.com', description: '이메일', }) @Column('varchar', { name: 'email', unique: true, length: 30 }) email: string; @IsString() @IsNotEmpty() @Column('varchar', { name: 'nickname', length: 30 }) nickname: string; @IsString() @IsNotEmpty() @Column('varchar', { name: 'password', length: 100, select: false }) password: string; main.ts에 useGlobalPipes 꼽기app.useGlobalPipes(new ValidationPipe()); httpException.filter.ts response status 수정하기const err = exception.getResponse() as | { message: any; statusCode: number } | { error: string; statusCode: 400; message: string[] }; if (typeof err !== 'string' && err.statusCode === 400) { return response.status(status).json({ success: false, code: status, data: err.message, }); } response.status(status).json({ success: false, code: status, data: err.message, }); } }공식문서도 보았는데, 해결이 안되어서 질문 남깁니다.
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
sleact 테이블 생성에 실패 하시는 분들을 위한 팁
강의 4~ 5분 즈음에 sleact 테이블을 생성하는데요아래의 에러 메시지가 나오면서 테이블 생성에 실패 하시는 분들은> a-nest@0.0.1 db:create > ts-node ./node_modules/typeorm-extension/dist/cli/index.js db:create -d ./dataSource.ts /Users/user/Documents/SideProjects/sleact/a-nest/node_modules/mysql2/lib/connection.js:161 const err = new Error( ^ Error: Can't add new command when connection is in closed state at Connection._addCommandClosedState (/Users/gim-uijung/Documents/SideProjects/sleact/a-nest/node_modules/mysql2/lib/connection.js:161:17) at Connection.end (/Users/gim-uijung/Documents/SideProjects/sleact/a-nest/node_modules/mysql2/lib/connection.js:902:26) at Query.onResult (/Users/gim-uijung/Documents/SideProjects/sleact/a-nest/node_modules/typeorm-extension/dist/database/driver/mysql.js:27:28) at Connection._notifyError (/Users/gim-uijung/Documents/SideProjects/sleact/a-nest/node_modules/mysql2/lib/connection.js:241:17) at Connection._handleFatalError (/Users/gim-uijung/Documents/SideProjects/sleact/a-nest/node_modules/mysql2/lib/connection.js:180:10) at Connection._handleNetworkError (/Users/gim-uijung/Documents/SideProjects/sleact/a-nest/node_modules/mysql2/lib/connection.js:193:10) at Socket.emit (node:events:513:28) at Socket.emit (node:domain:489:12) at emitErrorNT (node:internal/streams/destroy:151:8) at emitErrorCloseNT (node:internal/streams/destroy:116:3) {}dotenv 패키지를 설치하세요.npm i dotenvdotenv 설치하는 부분이 편집 과정중 어디선가 생략된것 같아요.아주 간단 한건데 이거 때문에 삽질을 좀 해서 혹시나 도움이 될까 싶어 올립니다.
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
객체를 저장하는 경우도 있나요?
안녕하세요. 혹시 디비에 객체를 저장하는 경우도 있나요? 예를들어 아래처럼 5개의 색상 키와 그 키에 해당하는 string을 값으로 가지는 객체 형태를 유저 정보에 저장하고 싶어요.// Color 객체 예시 입니다. { RED: string; BLUE: string; GREEN: string; YELLOW: string; PURPLE: string; }nest&typeorm는 처음이다보니 chatgpt의 도움을 많이 받고 있는데요. 객체는 저장이 되지 않지만 postgresql 에서는 이런 방법을 알려주긴하더라고요. export class User extends BaseEntity { @PrimaryGeneratedColumn() id: number; @Column() email: string; // 생략... @Column({ type: 'jsonb', nullable: true }) categories: { [key in Color]: string } | null; // 생략... 이 5개에서 늘어나거나 줄어들일이 없어서 테이블을 만드는게 맞는지 고민이 돼서요. 위와 같이하는건 좀 이상한 방법일까요? 이럴거면 그냥 email:string 하듯이 RED:string 이런식으로 컬럼 5개로 저장하는 방법이 나을까요?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
axios로 http 요청시 req,res 로깅하는 방법을 찾고있습니다.
안녕하세요 nest.js 로깅 관련해서 질문 넣을게요 axios로 http 요청 주고받을때 req, res에서 로깅을 하고 싶은데요...검색해보면 https://stackoverflow.com/questions/55431189/nestjs-logging-the-request-response-from-httpservice-callsthis.httpService.axiosRef.interceptors.request.use(config => console.log(config)); 이렇게 사용하라고 추천해주셨는데, 혹시 req,res 로그를 보거나 쌓을 수있는 다른 방법이 있을까요?
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
테이블 관계 질문한가지 있습니다!
안녕하세요. 강좌를 바탕으로 개인적으로 토이 프로젝트를 만들어보려고 하고있는데요.지도에 마커로 위치를 표시할수 있고, 마커 하나당 게시글 하나를 포함합니다. 게시글에는 제목, 설명, 사진이 들어갑니다. 프론트에서 지도화면에서는 마커들을 표시하고 마커 하나를 눌렀을때 해당하는 게시글과 사진을 보여주고 싶습니다. 마커 테이블과 게시글 테이블을 만들어서 one to one 관계가 좋을까요, 아니면 이런경우 하나의 테이블에 마커와 게시글 정보를 넣으면 될까요? chatGPT를 사용해봤는데 답변이 두가지입니다.Marker와 Post 테이블 간에 일대일 (one-to-one) 관계를 설정하는것이 좋다. Marker와 Post 테이블을 조인하여 필요한 정보를 가져올 수 있다.하나의 테이블에 마커와 게시글 정보를 함께 저장하고, 해당 정보를 조회할 때는 필요한 컬럼들만 선택하여 조회하는 것이 좋다. 마커 정보와 게시글 정보가 함께 저장되므로, 마커를 클릭하여 게시글 정보를 조회할 때 JOIN 연산이 필요하지 않아 성능상 이점이 있다. 테이블 구조를 어떻게 짜는것이 맞는것인가요? 그리고 테이블 구조 짜는것이 어려운데 이런것을 판단하기 위해 어떻게 학습하면 좋을까요?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
Identifying relation 과 non-identifying relation
안녕하세요! 보여주신 erd에서 궁금증이 생겨서 질문 드립니다.dms의 ReciverId과 mentions의 Receiverid 만 Non-identifying relation으로 맺어져 있고 나머지 관계들은 모두 Identifying Relation으로 맺어져 있는 이유가 뭘까요?Non-Identifying Relation과 Identifying Relation의 차이는 Non의 경우는 부모와 자식의 관계를 맺을때 자식이 부모 없이도 독립적으로 존재 가능한 것이고, Identifying-Relation은 자식이 부모 없이는 존재가 불가능한 차이로 알고 있습니다. DM과 Mention의 Receiver가 존재하지 않는다면, DM과 Mention의 정보가 불완전해질 것 같은데, 왜 non-identifying 일까요?typeorm entity 코드를 봐도, DM과 User entity의 Sender와 Receiver의 코드가 완전 똑같은데, 왜 ERD에서는 Receiver는 non-identifying 이고 Sender는 identifying인지 모르겠습니다.
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
pm2 에러
ec2-ubuntu 환경에서 pm2사용하는데sudo npm run start:prodcross-env NODE_ENV=production PORT=80 pm2 start dist/src/main.js실행하였는데Error: EACCES: permission denied, mkdir '/root/.pm2/logs'Error: EACCES: permission denied, mkdir '/root/.pm2/pids'Error: EACCES: permission denied, open '/root/.pm2/module_conf.json'Error: EACCES: permission denied, mkdir '/root/.pm2/modules'에러가 발생해서 제로초님이 답변하신거 찾아보고 노드 재설치도 했는데같은 에러가 발생합니다
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
dist/main.js 경로
Script not found: C:\Users\USER\Documents\project\linkfit-backend\dist\main.js이렇게 에러가 나서 보니까 main.js경로가 dist/src/main.js에 있던데 이게 맞나요?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
Relation 테이블 관련 에러
Movie, User 테이블하고 many-to-many 로 만든 Favorite 테이블이 있는데 Favorite 테이블에 저장하려고 할 때 이런 에러가 납니다.query failed: INSERT INTO `favorite`(`id`, `userId`, `movieId`) VALUES (DEFAULT, DEFAULT, DEFAULT) error: Error: Unknown column 'id' in 'field list' query: ROLLBACK [Nest] 782975 - 04/08/2023, 6:59:26 PM ERROR [ExceptionsHandler] Unknown column 'id' in 'field list' Movie 는 이렇게 만들어져있구요import { Entity, Column, PrimaryGeneratedColumn, ManyToMany, JoinTable } from 'typeorm'; import { User } from '../users/users.entity'; @Entity() export class Movie { @PrimaryGeneratedColumn() readonly id: number; @Column({ length: 100 }) title: string; @Column('text', { nullable: true }) desc: string; @ManyToMany(() => User, (user) => user.favorites) @JoinTable({ name: 'favorite' }) favorites: User[]; }User 는import { Entity, Column, PrimaryGeneratedColumn, ManyToMany, JoinTable } from 'typeorm'; import { Movie } from '../movies/movies.entity'; @Entity() export class User { @PrimaryGeneratedColumn() readonly id: number; @Column() username: string; @ManyToMany(() => Movie) @JoinTable({ name: 'favorite' }) favorites: Movie[]; }그리고 Favorite 은import { Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import { User } from '../users/users.entity'; import { Movie } from '../movies/movies.entity'; @Entity() export class Favorite { @PrimaryGeneratedColumn() id: number; @ManyToOne(() => User, (user) => user.favorites) user: User; @ManyToOne(() => Movie, (movie) => movie.favorites) movie: Movie; } 그런데 DB 를 보면 Favotie 테이블에 id 칼럼이 없습니다.그래서 favoriteRepository.save() 할때 에러가 난다고 의심하고 있는데요, favorites.service.ts는import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { Favorite } from './favorites.entity'; @Injectable() export class FavoritesService { constructor( @InjectRepository(Favorite) private readonly favoriteRepository: Repository<Favorite>, ) {} async create(userId: number, movieId: number): Promise<Favorite> { const favorite = new Favorite(); favorite.user = { id: userId } as any; favorite.movie = { id: movieId } as any; return await this.favoriteRepository.save(favorite); } }이렇게 되어있습니다.어디를 고쳐야 하는걸까요?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
일반적인 ORM 사용패턴(DDL, DML) 문의
수업에서는 기존 DB라 typeorm-model-generator를 사용했는데요,저의 질문의 요점은 ORM으로 DML 위주의 사용이 보편적인가 하는 것입니다.제가 python하다가 node.js로 넘어와서, python 예를 들어 죄송합니다만,https://velog.io/@youngkiu/SQLAlchemy-with-DDLpython에서는 model도 create table sql로 만들지 않고, model을 생성하고, ORM에서 DDL 처리도 같이 해주었습니다.스프링에서도 DDL은 ORM을 사용하지 않고, DB에서 직접 처리한다는 이야기를 듣기도 하여,업계에서 ORM의 일반적인 사용방법이 궁금하여 질문드립니다.늘 많이 배우고 있습니다. 감사합니다.타입스크립트 책 얼릉 출간해 주세요. 바로 구매하겠습니다.
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
httpException 에러 응답이 제대로 나오지 않습니다.
강의 내용 처럼 postman에서 에러 응답을 받고 싶습니다. 하지만 제대로된 에러 응답을 받지 못하고 있습니다.시도한 내용첫번째로, postman에서 post || localhost:3095/api/users 로 body에 아무런 내용없이 send를 보냈습니다.이후, 에러 응답으로 "msg":"이메일이 없네요."라는 답을 받았습니다. (성공) body에 이메일을 작성하여 send를 보냈지만,"msg":"이메일이 없네요."라는 이전과 동일한 에러응답을 받았습니다. (실패) 이메일을 send해도 "이메일이 없네요"라는 에러응답으로 답을 받고,다른 것으로 send를 해도 "이메일이 없네요"라고 에러응답을 받았습니다. 이를 해결하려고 하는데, 참고할만한 코드가 있을까요? users.service.ts@Injectable() export class UsersService { constructor( @InjectRepository(Users) private usersRepository: Repository<Users>, ) {} getUser() {} async join(email: string, nickname: string, password: string) { if (!email) { throw new HttpException('이메일이 없네요', 400); } if (!nickname) { throw new HttpException('닉네임이 없네요', 400); } if (!password) { throw new HttpException('비밀번호가 없네요.', 400); } const user = await this.usersRepository.findOne({ where: { email }}); if (user) { throw new HttpException('등록된 사용자입니다.', 401); } const hashedPassword = await bcrypt.hash(password, 12); await this.usersRepository.save({ email, nickname, password: hashedPassword, }); } } [계속 아래 이미지와 같은 에러 응답만 출력됩니다] 또한, 깃헙에서 코드를 참고하려했으나아래와 같이 진도가 달라서 어려웠습니다. ㅠㅠ 제로 초님께서 작성해주신 users.service.ts는 아래 코드 입니다.완성된 users.service.ts 내용인 것 같아서, 본 강의에 참고하기 어려워서 질문드렸습니다.@Injectable() export class UsersService { constructor( @InjectRepository(Users) private usersRepository: Repository<Users>, @InjectRepository(WorkspaceMembers) private workspaceMembersRepository: Repository<WorkspaceMembers>, @InjectRepository(ChannelMembers) private channelMembersRepository: Repository<ChannelMembers>, private dataSource: DataSource, ) {} async findByEmail(email: string) { return this.usersRepository.findOne({ where: { email }, select: ['id', 'email', 'password'], }); } async join(email: string, nickname: string, password: string) { const queryRunner = this.dataSource.createQueryRunner(); await queryRunner.connect(); await queryRunner.startTransaction(); const user = await queryRunner.manager .getRepository(Users) .findOne({ where: { email } }); if (user) { throw new ForbiddenException('이미 존재하는 사용자입니다'); } const hashedPassword = await bcrypt.hash(password, 12); try { const returned = await queryRunner.manager.getRepository(Users).save({ email, nickname, password: hashedPassword, }); const workspaceMember = queryRunner.manager .getRepository(WorkspaceMembers) .create(); workspaceMember.UserId = returned.id; workspaceMember.WorkspaceId = 1; await queryRunner.manager .getRepository(WorkspaceMembers) .save(workspaceMember); await queryRunner.manager.getRepository(ChannelMembers).save({ UserId: returned.id, ChannelId: 1, }); await queryRunner.commitTransaction(); return true; } catch (error) { console.error(error); await queryRunner.rollbackTransaction(); throw error; } finally { await queryRunner.release(); } } } 해결방법이 있을까요:?
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
front, front-js, front-rq 폴더 질문
총 2개의 질문사항이 있습니다. GitHub에서 제공해주신 front폴더를 사용하려고 하는데, 아래와 같이 이름이 다른 front 폴더가 총 3개가 있습니다.front-jsfront-rqfront 질문1. 이 중, 어떤 폴더에서 npm run dev의 명령어를 입력해야 하는 것인지 궁금합니다. 질문2. front이름 뒤에 붙어있는 js와 rq의 의미가 궁금합니다!
- 해결됨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, // }); } }
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
webstorm과 vscode
강의에서는 webstorm이 사용되던데,vscode로 강의를 따라가는데 어려움이 없을까요?
- 미해결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 설치버전 프론트 웹소켓 설치버전
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
유닛테스트 도중 'findByEmail' 의 함수를 못찾고 있습니다.
문제점: 제목 그대로 유닛테스트 도중 'findByEmail' 의 함수를 못찾고 있습니다.<에러발생 사진><제 코드>users.service.spec.tsusers.service.ts추가질문 : 추가 질문으로 위로 올려 보시면 users.Service.spec.ts에서 두번째 사진중 빨간네모박스 체크를 했는데 기존 UsersServie 코드로 하면 모듈에서 인식을 못하는지 아래와 같은 에러가 떴습니다. 이거 다른해결 방법이 있나요?< 모듈 사진추가>users.module.tsapp.module.ts
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
OneToMany 관계에서 FK 데이터를 Repository를 이용하여 insert시 오류
우선 제 프로젝트에서 구성하고 있는 DB의 일부분입니다. 간단하게 p_references 와 m_references, 그리고 parts 와 models 테이블에 그림파일의 정보를 가지고 있는 images객체의 배열이 필요한데 mysql이다보니 이걸 다 One to Many로 추가시켰습니다. 여기에 images의 각각 대상 테이블에 대한 FK를 nullable : true 상태로 추가시켰습니다. 물론 이렇게 구성하면 images 테이블안에 적어도 한개의 FK를 포함한 입력값만 허용하도록 Guards 를 추가시켜야 될꺼 같습니만... 간단히 이해도를 위해 설명을 추가한거고요.여기서 문제는 p_references/m_reference 와 images table과 연결 시킬때 원래 계획된 대로 images 테이블 안에 string 이나 int 형식의 column이 추가되는것이 아닌 대상 테이블 객체가 잡히는 문제인데요.entities/images.ts@Entity("Images", { schema: "workplaces" }) export class Images { @PrimaryGeneratedColumn({ type: "int", name: "imageID" }) id: number; @Column('varchar', { name: 'images', nullable: true }) image: string; @Column('bool', { name: 'isOwn', nullable: false, default: false }) isOwn: boolean; @ManyToOne(() => Mreferences, (mreferences) => mreferences.images, { onDelete: "SET NULL", onUpdate: "CASCADE" }) @JoinColumn([{ name: 'modelNumber', referencedColumnName: 'serialNumber' }]) mreferences: Mreferences; @ManyToOne(() => Preferences, (preferences) => preferences.images, { onDelete: "SET NULL", onUpdate: "CASCADE" }) @JoinColumn([{ name: 'partsNumber', referencedColumnName: 'serialNumber' }]) preferences: Preferences; @ManyToOne(() => Parts, (parts) => parts.images, { onDelete: "SET NULL", onUpdate: "CASCADE" }) @JoinColumn([{ name: 'partsID', referencedColumnName: 'id' }]) parts: Parts; @ManyToOne(() => Models, (models) => models.images, { onDelete: "SET NULL", onUpdate: "CASCADE" }) @JoinColumn([{ name: 'modelID', referencedColumnName: 'id' }]) models: Models; }이것이 images entity에서 설정한 코드입니다. 이렇게 해서 자동으로 생성된 DB 의 ERD가 처음에 올린 스샷으로 제대로 의도된대로 생성된걸 확인할 수 있습니다.기본 설명이 너무 길어졌는데, 이제 여기 강의의 "typeorm 쿼리 빌더" 강의에 나온대로 새로운 데이터를 insert 요청이 발생하면 Images Repository를 이용해서 저장을 하려하는데 문제가 발생드려서 문의드립니다.reference-book.service.tsimport { Injectable, NotFoundException } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Mreferences } from '../entities/Mreferences'; import { Repository } from 'typeorm'; import { ReferencebookModelDto } from './dto/referencebook.model.dto'; import { Videos } from '../entities/Videos'; @Injectable() export class ReferenceBookService { constructor( @InjectRepository(Mreferences) private referenceModelRepository: Repository<Mreferences>, @InjectRepository(Images) private imagesRepository: Repository<Images>, ) { } async addReferenceModel(addReferenceModel: ReferencebookModelDto) { const referenceModelBook = new Mreferences(); const referenceModelImages = new Images(); referenceModelBook.serialNumber = addReferenceModel.serialNumber; referenceModelBook.name = addReferenceModel.modelName; referenceModelBook.brands = addReferenceModel.brand; //..... 생략 await this.referenceModelRepository.save(referenceModelBook); } }이렇게 작성시, 아무런 문제 없이 FK관련 column 값들을 제외하곤 이상없이 제대로 DB에 저장이 되는데요. 문젠 FK 관련한 값에서 제대로 작동하지 않습니다.const data = new Images() 로 새로 Images객체를 생성하여, ERD에서 처럼 거기에 등록된 modelNumber 값을 입력한 dto객체의 images.image 값으로 지정해주고 저장하면 될 줄 알았는데 실제 생성된 Images객체엔 modelNumber 문자열이 존재하는 대산 mreferences 객체만이 존재합니다. 강의에서 직접 다룬 프로젝트는 아니지만 제가 강의를 보면서 직접 따라하다 발생한 문제라 강의관련 문의에 올렸습니다.어딘가에서 오류가 있던걸까요? 추가로 혹시나 필요할까 해서 dto 파일도 올립니다/dto/referencebook.model.dto.tsimport { ApiProperty } from "@nestjs/swagger"; import { Images } from "../../entities/Images"; import { Brands, Categories } from "../../common/types/enum.types"; import { Videos } from "../../entities/Videos"; export class ReferencebookModelDto { @ApiProperty({ example: 'WX532433', description: 'Uniq Serial Number', required: true, }) public serialNumber: string; @ApiProperty({ example: 'Aug-23-2023', description: 'Updated Date', required: true, }) public updateDate: Date; @ApiProperty({ example: 'Samsung Dryer', description: 'Model Name', required: true, }) public modelName: string; @ApiProperty({ example: ['afd34323', 'ty23142'], description: 'Serial number List of related parts ', required: false, }) public relatedParts: string[]; @ApiProperty({ example: ['https:/atlanticappliance.com/parts/p?pid=WX532433/image1.jpg'], description: 'Links of own images location', required: false, }) public images: Images[]; @ApiProperty({ example: ['https:/atlanticappliance.com/parts/p?pid=WX532433/video1.mp4'], description: 'Links of own videos location', required: false, }) public videos: Videos[]; @ApiProperty({ example: 'This is a parts for testing model, WX532433', description: 'Scraped description of current product from other sites', required: false, }) public description: string; @ApiProperty({ example: 'Washer', description: 'Product categories', required: true, }) public category: Categories; @ApiProperty({ example: '24Inch', description: 'Product Variant Options', required: false, }) public variant: string; @ApiProperty({ example: '27.7', description: 'Product Weight', required: false, }) public weight: number; @ApiProperty({ example: 21.49, description: 'Product height', required: false, }) public height: number; @ApiProperty({ example: 21.49, description: 'Product width', required: false, }) public width: number; @ApiProperty({ example: 21.49, description: 'Product depth', required: false, }) public depth: number; @ApiProperty({ example: 'Samsung', description: 'Brand', required: false, }) public brand: Brands; }
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
mysql 설치는 윈도우에 대해서만 해주는 것인가요?
해당 강좌는 윈도우 기반인가요?설치에 대해서 윈도우만 설명하고 있어서 글을 적어보았습니다.