Nest js 독학 삽질 일기 Day 5: Read 구현, 실수로 .env 파일을 깃허브 업로드, 또 깃헙 오류 오류.., createQueryBuilder 사용해보기, custom Repository 더 알아보기 (0.3 ver 이후)

Dorito·2022년 9월 19일
0

NestJS

목록 보기
5/10
post-thumbnail

Create는 했고, RUD 구현하기

Migrating to TypeORM 0.3

이게.. 0.2에서 0.3 올라갈 때 엄청 뭔가 많이 바뀌어서 혼란이 많아보인다. 관련해서 정리해놓은 문서 아카이브 함.
https://wanago.io/2022/07/11/api-with-nestjs-migrating-to-typeorm-0-3/

TypeORM 0.3 업뎃 내용 (봐도 잘 모르겠는데.. 일단 아카이브 해둠)
https://github.com/typeorm/typeorm/releases/tag/0.3.0

일단 Create를 해놨으니까 CustomRepository 쓰는건 보류로 하고 메서드부터 구현하자.
나중에 한번 더 다시 갈아엎을 예정임

하... 이게 0.3으로 올라가면서 deprecated된 코드가 많아서 또 엄청 헤매고 있다.
이게 막 뭔가 참고서라도 있었으면 좋겠지만 최근 업뎃이라 절대 안된다! 내가 다 해내야 함! 미래의 내가 다 해주겠지 뭐. 비효율 끝판왕같기는 하지만;


CRUD구현은 깃허브 코드를 보면서 따라해볼 생각인데

  1. https://github.com/sramocki/nestjs-typeorm-example-migrations/tree/master/src/car

여기 예제 코드를 보면서 해볼 생각이다.

추가로 구글링 중 괜찮은 블로그 자료 찾아서 적음
2. https://circleci.com/blog/getting-started-with-nestjs-and-automatic-testing/
여기 코드도 참고할 것임

개념

uuid는 언제 사용할까

사실 가오 때문에 uuid를 pk로 써보자! 하고 봤는데 막상 어디에 써야할 지 모르겠다. 싶어서 uuid when to use websidte 키워드로 구글링함

스택오버플로우 When is it appropriate to use UUIDs for a web project?
https://blog.boot.dev/clean-code/what-are-uuids-and-should-you-use-them/
https://geshan.com.np/blog/2022/01/nodejs-uuid/

글을 참고해보니
1. UUID를 사용할 경우 가장 큰 장점은 UUID를 생성하여 데이터베이스 행과 같은 것을 식별하는 데 사용할 수 있다.
2. 전혀 관련이 없는 회사나 조직에서 사용하는 UUID는 중복 없이 함께 참조할 수 있다
3. auto-increment 값을 사용하여 UserId를 저장하면 누구나 웹 페이지의 소스를 보고 데이터를 얻기 위해 임의의 정수 값을 시도할 수 있다는 문제점이 있음
4. GUID는 순차적 형식으로 생성되지 않으므로, GUID를 하나씩 생성하면 순서를 쉽게 추측할 수 없다
5. auto-increment가 속도 이슈에서 빠르다.
6. 대충 사용자들이 볼 수 있는 테이블에서는 uuid 쓰는데 내부적으로는 auto-increment 쓰는 경우가 많다고 구글링하면서 봄.

대충 일단 CRUD 구현할 때 언제쓰이나 해서 구글링해봤는데
아직까지는 잘 모르겠다.
구체적으로 해보면서 알지 않을까

환경 변수, config파일 그리고 .env

.env와 환경변수를 config파일보다 선호하는 이유

HTTP tutorial

Http 통신에서 Get Parameter가 구체적으로 어떤 위치에 어떻게 작동하는지 구글링을 해봐야지 제대로 사용할 수 있을 것 같다. (HTTP 통신 관련 기초가 없다는걸 깨달음.)
쿼리스트링에 ?key=value 로 들어가는 걸 얘기하는 것이었다! 이해완.

what is http parameter 로 구글링 함
https://www.seobility.net/en/wiki/GET_Parameters
여기 설명 자세함! -> HTTP 개념 관련해서 블로그: 네트워크 카테고리로 따로 빼놨다.
https://www.javatpoint.com/http-tutorial

Read 구현 part 1

@Read All Board 구현

깃허브 링크
// 이때 엄청난 실수를 해버렸다... (env 파일 올림.. 에러로 삽질함 바로 다음챕터 내용)

오예 ~


Github ERROR:

.env 파일을 깃헙에 올려버림

  • 커밋 잘게 쪼개서 깃허브 올리는 연습하는데...
    .env 파일까지 올라가버렸다.

걍 깃허브 홈페이지 레포지토리 드가서 걍 직접 삭제해서 시키는대로 커밋함

이런 짓을 하지 말았어야 했다.

-> env 파일 커밋 내역 남아있음 젠장.. (글 뒤에 해결 내역 있음)

이런... 커밋내역에 그대로 파일이 올라가있어서 더 구글링함..

git push가 안됨

그냥 깃 풀해줘도 안되어서.. 더 구글링해서 여기
git pull --rebase 로 해결함

근데 명령어가 구체적으로 어떤 상황 무슨 의미인지몰라서 또 보는중..

Git 브랜치 - Rebase 하기 에서 확인함..!

.gitignore 파일등록했는데도 추적되는 문제 해결

.gitignore가 제대로 작동되지 않아서 ignore처리된 파일이 자꾸 changes에 나올 경우..
git의 캐시가 문제가 되는거라 아래 명령어로 캐시 내용을 전부 삭제후 다시 add All해서 커밋하면 된다.
여기 문서 참고

git rm -r --cached .
git add .
git commit -m "fix: add .env to .gitignore"
git push

.env 파일이 커밋내역에 그대로 파일이 올라가있어서 커밋 히스토리 삭제

나랑 똑같은 실수하신 분 블로그 있다 최고

$ git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch *.env' --prune-empty -- --all

하고 git push --force 해줬따...


오예 해결함..

후훗.. 문제의 커밋에서 .env 파일 빠졌다.

깃허브 언어설정..

  • vsc 터미널에서 깃 업로드하는데 웬 한글

    깃허브 에러창이 한글로 뜬다는걸 자각했음.
    매국노로서 가오 상함.. (농담이고 에러 찾기 힘듦)
  • vsc 설정

    음...대충 구글링해서 vsc세팅도 확인해보고 했는데 문제 없었고
    구글링해보니까 여기서 설정파일 건들면 됨: 참고 링크

이러고 터미널 새로 켜주면 됨!

  • vsc 터미널 새로 켰는데 아니 이게 뭔 갑자기 분위기 독일
  • iterm2 에서...

    터미널에서는 잘되는데? ;;;
  • 아.. 내가 따라치면서 오타냈는 듯.
    손가락이 제 자아랑 상관이 없는 것 같습니다.
    걍 복붙으로 다시 시도해보니까 영어로 잘뜸 히히

Read 구현 2 (find by author)

깃허브 링크

uuid를 어따쓰지... 일단 author로 찾을 수 있는 메서드를 구현해보겠습니다.

일단 내가 참고해서 보는 코드에서는

// car.service.ts
  async getCarById(carId: number): Promise<Car> {
    const car = await this.carRepository.findOneBy({ id: carId });
    if (car) {
      return car;
    }
    throw new HttpException('Car not found', HttpStatus.NOT_FOUND);
  }
// car.controller.ts
@Get(':id')
  async getCarById(@Param('id') id: string): Promise<Car> {
    return this.carService.getCarById(Number(id));
  }

https://circleci.com/blog/getting-started-with-nestjs-and-automatic-testing/
여기 어떻게 해야할지 CRUD 관련 코드 대박 잘나와있음 이럴수가.. 여기 참고해보면서 써야지. (글 위에도 링크 추가함) customRepository, 에러 처리까지 되어있어가지구 내가 딱 필요로 했던 제대로 된 문서 같다.

대충 이 메서드가 가장 베이직한듯.

// Create: 엔티티 저장하기
this.productsRepository.save(product);

// Read: 모든 엔티티 가져오기
this.productsRepository.find();

// Read: 엔티티 가져오기
this.productsRepository.findOneBy({ id: id });

// Update: 엔티티 데이터 업데이트 하기
this.productsRepository.update(id, data);

// Delete: 엔티티 제거하기
this.productsRepository.remove(product);

아니 근데 findOneBy()하니까 author에 해당하는 하나의 값만 가져와서.. 다른 메서드 찾아봐야할듯
나는 author에 해당하는 모든 값을 가져와보고 싶다..
find 메서드에 대해서 샅샅이 공식문서부터 해보고 여기도 구글링 해봤는데

해봐도.. 안된다 oTL 내가 뭘 놓치고 있는 걸까..

구글링 키워드 괜찮은 것 찾은 듯
typeorm find with parameters 검색해보았다.
오 !! 괜찮은듯
https://stackoverflow.com/questions/55240553/what-is-wrong-with-the-parameters-in-my-typeorm-where-clause-for-the-querybuilde
글 참고하면서 나름 구성요소들 파악하면서 (솔직히 가라친거임) 코드 썼는데
포스트맨에 쏴졌다..!!!
캬아아아아악 성공

  • blog.service.ts
  async getBoardsByAuthor(author: string): Promise<Board[] | undefined> {
    return this.boardRepository
      .createQueryBuilder('board')
      .where('board.author = :author', { author })
      .getMany();
  }
  • blog.controller.ts
  @Get('/:author')
  async getBoardByAuthor(@Param('author') author: string) {
    return await this.boardService.getBoardsByAuthor(author);
  }

이렇게 썼다. (근데 제대로 코드가 맞는건지도 제대로 쓴건지도 잘 모르겠다.)

createQueryBuilder

createQueryBuilder 검색.. (메서드라는 말이 맞는지는 모르겠다.)
https://itchallenger.tistory.com/230 여기 typeORM 쿼리빌더에 대해서 깊게 포스팅 한 글이 있어서 열심히 읽고 있다.

TypeOrm 0.3부터 @EntityRepository는 deprecated 되고 사람마다 다 방식이 다르고 이해가 가지를 않아서... 더 찾아봐야한다는 이유로 계속 미뤘다.
아 근데 좀 미련이 남아서 좀 더 custom repositroy 구글링 함 (뭔지만 알아보자..) 어떤 느낌인지만 보고싶음..

그리고 typeORM 기본 사용법NestJS와 사용하는 TypeORM 기초 여기 글에 무슨 수업글을 잘 정리해두셔서 도움이 많이 되었다. 아니 솔직히 이 글 보고 틀 잡으면 될 듯. 매핑방법 어쩌구도 있는데 아직 거기까지는 잘 모르겠다. 나중에 참고해야지.

Custom Repository 행방을 찾아서

일단 custom Repository가 뭐지

여기 글 참고하면 된다.

대충.. 내가 이해한 바로는
service에서 DI한 라인 11 에 있는 Repository 를 cmd 누르고 클릭하면

이런 클래스가 나온다.
저 클래스를 받아와서 더 확장시켜서 내 입맛에 맞게 쓸 수 있는것이라고 이해함.

원래 0.2 버전에서는 @EntityRepository 데코레이터를 사용하면 되었는데 deprecated 되었다고 함...
구글링해보니 사람마다 대체 방법이 너무 많아서 일단 공식문서를 보고 왔다.


라고 해서 따라해봤는데

안된다.

일단 저기서 불러오는 dataSource 에 대해서 뒤벼봐야겠다.
... 한참 뒤져봤다.
but!! 잘 모르겠다.;;;; 휴.. ㅠㅠ 개념이 섞인건가.. 감이 안잡힘 아무리봐도.

나랑 똑같은 문제로 물어보는 스택오버플로우 글 찾았는데 답변이 없다.

더 구글링 해보니 여기 문서에서

이런 자신만만이를 만났다.

https://github.com/leosuncin/nest-typeorm-custom-repository
저기 글에서 깃헙 첨부되어있었는데, 참고용으로 가져옴 (근데 데이터소옿스의 ㄷ 도 안나오는데 뭐임)

  • task.repository.ts
import type { Repository } from 'typeorm';
import type { Task } from './task.entity';

export interface TaskRepository extends Repository<Task> {
  this: Repository<Task>;

  findDone(): Promise<Task[]>;

  findPending(): Promise<Task[]>;
}

export const customTaskRepositoryMethods: Pick<
  TaskRepository,
  'findDone' | 'findPending'
> = {
  findDone(this: Repository<Task>) {
    return this.findBy({ done: true });
  },
  findPending(this: Repository<Task>) {
    return this.findBy({ done: false });
  },
};
  • task.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';

import { TaskRepository } from './task.repository';
import { TaskCreate } from './dto/task-create.dto';
import { TaskUpdate } from './dto/task-update.dto';
import { InjectRepository } from '@nestjs/typeorm';
import { Task } from './task.entity';


// DI
@Injectable()
export class TaskService {
  constructor(
    @InjectRepository(Task)
    private readonly taskRepository: TaskRepository,
  ) {} 
  

  findAll() {
    return this.taskRepository.find();
  }

  findAllDone() {
    return this.taskRepository.findDone();
  }

  findAllPending() {
    return this.taskRepository.findPending();
  }
  

이런식으로 쓰는듯

Custom Repository 구성은 이해했는데, 그걸 어떻게 사용할 지는 이 문서를 참고해서 할 예정임.
저기 문서에선 create, update 쪽만 구현해놨기 때문에 나중에 시도해보도록 하겠습니다.

근데 interface랑 class 차이가 뭐지

ts interface vs class 로 구글링해서 스택오버플로우 문서를 봤다.

At it's most basic, a class is essentially an object factory (ie. a blueprint of what an object is supposed to look like and then implemented), whereas an interface is a structure used solely for type-checking.
While a class may have initialized properties and methods to help create objects, an interface essentially defines the properties and type an object can have.

마무리하면서...
일단 글 구성에 대해서 고민이 많았는데 이런 식으로 내용 적으면 될 것 같다.
그리고 또 구글링해보니까!! 페이지네이션이라는 것도 찾았다.
CRUD 다 만들고 나면 (금방 할 것 같은데, Custom Repository때문에 살짝 지연... 그리고 이상한 곳에서 오류나서 삽질 중..) 페이지네이션도 한번 구현해봐야겠다!!

0개의 댓글