Create는 했고, RUD 구현하기
이게.. 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구현은 깃허브 코드를 보면서 따라해볼 생각인데
여기 예제 코드를 보면서 해볼 생각이다.
추가로 구글링 중 괜찮은 블로그 자료 찾아서 적음
2. https://circleci.com/blog/getting-started-with-nestjs-and-automatic-testing/
여기 코드도 참고할 것임
사실
가오
때문에 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 구현할 때 언제쓰이나 해서 구글링해봤는데
아직까지는 잘 모르겠다.
구체적으로 해보면서 알지 않을까
.env와 환경변수를 config파일보다 선호하는 이유
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
깃허브 링크
// 이때 엄청난 실수를 해버렸다... (env 파일 올림.. 에러로 삽질함 바로 다음챕터 내용)
오예 ~
걍 깃허브 홈페이지 레포지토리 드가서 걍 직접 삭제해서 시키는대로 커밋함
이런 짓을 하지 말았어야 했다.
-> env 파일 커밋 내역 남아있음 젠장.. (글 뒤에 해결 내역 있음)
이런... 커밋내역에 그대로 파일이 올라가있어서 더 구글링함..
그냥 깃 풀해줘도 안되어서.. 더 구글링해서 여기 봄
git pull --rebase
로 해결함
근데 명령어가 구체적으로 어떤 상황 무슨 의미인지몰라서 또 보는중..
Git 브랜치 - Rebase 하기 에서 확인함..!
.gitignore가 제대로 작동되지 않아서 ignore처리된 파일이 자꾸 changes에 나올 경우..
git의 캐시가 문제가 되는거라 아래 명령어로 캐시 내용을 전부 삭제후 다시 add All해서 커밋하면 된다.
여기 문서 참고
git rm -r --cached .
git add .
git commit -m "fix: add .env to .gitignore"
git push
나랑 똑같은 실수하신 분 블로그 있다 최고
$ git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch *.env' --prune-empty -- --all
하고 git push --force
해줬따...
오예 해결함..
후훗.. 문제의 커밋에서 .env 파일 빠졌다.
이러고 터미널 새로 켜주면 됨!
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
글 참고하면서 나름 구성요소들 파악하면서 (솔직히 가라친거임) 코드 썼는데
포스트맨에 쏴졌다..!!!
캬아아아아악 성공
async getBoardsByAuthor(author: string): Promise<Board[] | undefined> {
return this.boardRepository
.createQueryBuilder('board')
.where('board.author = :author', { author })
.getMany();
}
@Get('/:author')
async getBoardByAuthor(@Param('author') author: string) {
return await this.boardService.getBoardsByAuthor(author);
}
이렇게 썼다. (근데 제대로 코드가 맞는건지도 제대로 쓴건지도 잘 모르겠다.)
createQueryBuilder
검색.. (메서드라는 말이 맞는지는 모르겠다.)
https://itchallenger.tistory.com/230 여기 typeORM 쿼리빌더에 대해서 깊게 포스팅 한 글이 있어서 열심히 읽고 있다.
TypeOrm 0.3부터 @EntityRepository는 deprecated 되고 사람마다 다 방식이 다르고 이해가 가지를 않아서... 더 찾아봐야한다는 이유로 계속 미뤘다.
아 근데 좀 미련이 남아서 좀 더 custom repositroy 구글링 함 (뭔지만 알아보자..) 어떤 느낌인지만 보고싶음..
그리고 typeORM 기본 사용법은 NestJS와 사용하는 TypeORM 기초 여기 글에 무슨 수업글을 잘 정리해두셔서 도움이 많이 되었다. 아니 솔직히 이 글 보고 틀 잡으면 될 듯. 매핑방법 어쩌구도 있는데 아직 거기까지는 잘 모르겠다. 나중에 참고해야지.
여기 글 참고하면 된다.
대충.. 내가 이해한 바로는
service에서 DI한
라인 11
에 있는 Repository 를 cmd 누르고 클릭하면
이런 클래스가 나온다.
저 클래스를 받아와서 더 확장시켜서 내 입맛에 맞게 쓸 수 있는것이라고 이해함.
원래 0.2 버전에서는 @EntityRepository
데코레이터를 사용하면 되었는데 deprecated 되었다고 함...
구글링해보니 사람마다 대체 방법이 너무 많아서 일단 공식문서를 보고 왔다.
라고 해서 따라해봤는데
안된다.
일단 저기서 불러오는 dataSource 에 대해서 뒤벼봐야겠다.
... 한참 뒤져봤다.
but!! 잘 모르겠다.;;;; 휴.. ㅠㅠ 개념이 섞인건가.. 감이 안잡힘 아무리봐도.
나랑 똑같은 문제로 물어보는 스택오버플로우 글 찾았는데 답변이 없다.
더 구글링 해보니 여기 문서에서
이런 자신만만이를 만났다.
https://github.com/leosuncin/nest-typeorm-custom-repository
저기 글에서 깃헙 첨부되어있었는데, 참고용으로 가져옴 (근데 데이터소옿스의 ㄷ 도 안나오는데 뭐임)
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 });
},
};
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 쪽만 구현해놨기 때문에 나중에 시도해보도록 하겠습니다.
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 aninterface
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때문에 살짝 지연... 그리고 이상한 곳에서 오류나서 삽질 중..) 페이지네이션도 한번 구현해봐야겠다!!