GithubHelp home page GithubHelp logo

nest-js-101's Introduction

고객 만족 💐 대박 리뷰 이벤트 💐 고객 감동

Hits

Hello! 👋

🏕 habitat

habitat url
📧 Email [email protected]
🥕 Youtube https://www.youtube.com/@dusunax
🌱 Blog/tech https://velog.io/@dusunax
🌾 Blog/diary https://dusunax.tistory.com/
👩‍🌾 Notion https://dusunax.notion.site

🪬 Tech Stack

category skills
Front-end 🐔 JavaScript TypeScript React Next.js Tanstack Query Redux Zustand StyledComponent Tailwind Three.js
Back-end 🐤 Node.js Nest.js MongoDB
Others Github, Docker, AWS, Agile Methodologies

⌛️ 2024's Learning Goals

  • 📚 Conducting a deep dive into my current tech stack to enhance my computer science knowledge, aiming to become a long-term contributing developer.
    • Processing: Modern Javascript Deep Dive(2023), Modern React Deep Dive(2024.3~), Typescript
  • 📝 Building a portfolio/blog by 2024 to showcase TILs (Today I Learned) and project examples etc.
  • 🧩 Researching and gaining insights into monorepos, design systems, and web views.
  • 🤖 build a AI related projects.

GitHub stats

dusunax's GitHub stats

nest-js-101's People

Contributors

dusunax avatar valentine256 avatar

Watchers

 avatar

nest-js-101's Issues

docs: DB_001

DB_001

부족하지만 Todos와 Tasks api 작업을 일단락했습니다.
공부를 더 하면 개선할 수 있는 점들이 있습니다.

001. Todos & Tasks

  • Todos: Todo 리스트입니다.(checked 상태를 토글할 수 있습니다.)
  • Tasks: 특정 Todo에 연결된 Task를 생성하여, 별도의 리스트로 관리합니다.
    • 하나의 Todo에 하나의 Task만 생성할 수 있습니다.
    • Task를 삭제해도 Todo는 삭제되지 않습니다.

다음 작업에서 Todo

  • 12월 2일 전까지 user authorization, 도커, 쿠버네티스 관련 학습
  • 다음에 mySQL 말고 다른 RDS 또는 Mongoose 써보기
  • Test + CI/CD 필요

개선점

  • 의존성 주입을 통해서 tasksModule에서 todosService는 사용할 수 있었는데, 반대로 todo 기능에서 task repository를 변경하는 기능을 시간상 구현하지 못함 (front에 의존하는 식으로 땜빵)
  • typeORM에 @OneToOne, @OneToMany 같은 관계형 테이블에 관련된 데코레이터가 있는 데 사용하지 못하고 삭제한 점
  • 유닛 테스트의 mocking이 어색하다. 잘 작성하는 법이 있을 것
  • e2e 테스트에 경로 관련 config 필요

오늘 작업

  • tasks에 todos 주입: export TodoService & import TodoModule
    • task 생성 시, todoService.update({ task_id })
    • task의 findAll을 task[]에서 todo[]를 반환하도록 변경
    • task의 findOn을 task에서 todo를 반환하도록 변경
    • todo 및 task의 update 로직 개선: 특정 게시글을 삭제하고 다시 추가하던 이전 기능 ⇒ TypeOrm의 update()로 교체
  • 유닛 테스트에 DI의 TodosService mock 추가 (헤멤)
  • findFilteredTodos(): (1)FilterTodoDto 작성 (2) 쿼리 스트링에 todo id 추가 (findFilteredTasks에서 todo_id 검색을 위해 사용)
  • optional한 value에 @IsOptional() 데코레이터 추가
  • TodoService.create(): 이미 task로 등록한 todo id 예외 추가
const isExistingTask = await this.findTasksFiltered({ todoId });
if (isExistingTask) throw new NotAcceptableException(`Requested todo's task is already existing`);
  • TodoService.delete(): 실패했을 때 예외 오류 수정
    • (1)result의 affected를 확인하거나, (2)async 함수로 변경 후 try catch 추가 => (2)로 진행
const result = await this._todoRepository.delete({ id }); //DeleteResult { raw: [], affected: 0 }
  • patch 순서 바꿈 (헤멤)
@Patch("complete")
@HttpCode(HttpStatus.ACCEPTED)
completeTodo(@Body() completeTodoDto: CompleteTodoDto) {
  return this.todosService.toggleCompleted(completeTodoDto);
}

@Patch(":todo_id")
@HttpCode(HttpStatus.CREATED)
update(@Param("todo_id") todo_id: Todo["id"], @Body() todoData: UpdateTodoDto) {
  return this.todosService.update(todo_id, todoData);
}
  • 스웨거 적용: 오늘은 내가 swagger 요리사~

🌱 일요일 공부 끝

image

feat: `/todos GET` (1)날짜 (2)title 검색 쿼리 추가

feat: /todos GET (1)날짜 (2)title 검색 쿼리 추가

  • 목적: 전체 todo 리스트 api 개선
  • 기능: weekly 구현을 위한 날짜 검색 기능 추가, title 검색 기능 추가
    • from과 to가 있을 때, from과 to 사이의 날짜 검색
    • search 값이 있을 때, title이 쿼리값을 포함하는 지 검색
    • from과 to가 있고 search값이 있을 때, 두 가지 조건을 AND 연산
  • api: GET /todos?from=2023-11-12&to=2023-11-20&search=공부

Like, Find

구분 설명 사용 방법 예시
Like 특정 패턴을 포함하는 문자열 데이터를 찾음 %(와일드 카드 문자)와 함께 특정 패턴을 포함하는 문자열을 찾는 데 사용 %apple%는 'apple'을 어디든 포함하는 문자열을 찾음 (SQL문 LIKE)
Find 특정 조건에 맞는 데이터 찾음 데이터베이스의 특정 테이블에서 조건에 맞는 데이터를 조회할 때 사용 .find({ where: { name: Like('%John%') } })는 이름에 'John'을 포함하는 데이터를 찾음

검색

where에 배열을 넣으면? OR 연산!

  • 이렇게 구현하면? from에서 to인 검색 결과 || seach를 포함한 검색 결과를 반환함
    • (원하는 결과가 아님)
async findFilteredTodos({ from, to, search }): Promise<Todo[]> {
  const whereConditions = [];

  if (from && to) {
    whereConditions.push({ created_at: Between(from, to) }); // 날짜 검색 조건
  }

  if (search) {
    whereConditions.push({ title: Like(`%${search}%`) }); // 문자열 검색 조건
  }

  return this._todoRepository.find({ where: whereConditions }); // 조회
}

AND 연산하려면? 쿼리 빌더 queryBuilder!

async findFilteredTodos({ from, to, search }): Promise<Todo[]> {
  const queryBuilder = this._todoRepository.createQueryBuilder('todo'); // 쿼리 빌더 구성

  if (from && to) {
    queryBuilder.andWhere('todo.created_at BETWEEN :from AND :to', { from, to }); // 날짜 검색 쿼리
  }

  if (search) {
    queryBuilder.andWhere('todo.title LIKE :search', { search: `%${search}%` }); // 키워드 검색 쿼리
  }

  return queryBuilder.getMany(); // 쿼리를 실행
}

docs: 백엔드 기술 선택 => NestJS, TypeORM, MySQL

docs: 백엔드 기술 선택 => NestJS, TypeORM, MySQL

투두리스트 토이 프로젝트의 Backend 지원을 위한 api를 제작합니다.
강의 예제가 아니라, 스스로 nestJS로 서버를 만드는 것은 처음이기 때문에 막히는 점이 많습니다.
일요일(11월 13일) 작업에서 고민했던 내용입니다.

image

왜 TypeORM, MySQL인지?

최근에 혼자 작업한 토이프로젝트에는 편의성을 위해 서버리스인 Firebase의 Firestore를 주로 사용했고,
작년까지는 종종 mongoDB를 사용했습니다.
MySQL은 퍼블리싱 작업을 할 때나, 웹개발을 처음 접했을 때 쇼핑몰들을 만들었던 때에 사용했었습니다.
JQuery에서 React로 넘어와 프론트엔드 개발을 시작한 이후에는, RDS로 작업한 적이 없습니다.

워낙 화면을 그리는 일을 좋아하기 때문에, 100% 백엔드 api 구현은 첫 작업입니다.

이번 nestJS에 사용할 데이터베이스를 선택할 때, TypeORM, Sequelize, Mongoose를 놓고 고민했습니다.
세 가지를 선택한 기준은 백엔드 개발자 분들이 TypeORM, Sequelize를 사용하는 걸 본 적이 있고,
저한테 Mongoose가 익숙하기 때문이었습니다.

NestJS는 도전하는 새로운 스택이기 때문에 익숙한 작업 형태(mongoose)보다는 TypeORM, Sequelize에 눈을 돌리게 되었습니다.
그리고 이전 백엔드를 공부하던 동료들이 TypeORM을 처음 배우고, Sequelize를 나중에 도입하던 모습을 봤었기 때문에
TypeORM이 더 단순할 것이라 생각했고, typescript 지원이 더 잘 되어있다고 알고 있어서 TypeORM을 먼저 사용하려 합니다.

image

TypeORM의 경우, 주로 SQL 데이터베이스를 대상으로 하고 있어서 NoSQL 기능 지원이 완벽하지 않다고 알고 있어 RDS를 선택했습니다. 또한 백엔드 api를 일정 기간 지원하기 위한 용도의 AWS 계정을 새로 만들었고, RDS 엔진을 선택하는 데 Aurora와 MySQL 선택에 대해 고민하게 되었습니다.

AWS에서 장점으로 내세우는 고가용성이 지금 프로젝트들에 중요하지 않을 것이고, MySQL이 범용적이고, 유연하다고 생각하여 MySQL로 작업했습니다.
MySQL로 작업할 지, 또는 다른 RDS를 사용할 지 고민이 되었기 때문에, main 브랜치에서 chore 브랜치로 이동했습니다.

결론

생각보다 DB 선택에 있어 고민을 오래 하게 되었는데, 이번 작업을 통해 다음 목표를 이뤄보려 합니다.

1) SQL을 복습하고 심화하기

  • javascript 쇼핑몰 페이지들은 무조건 테이블 1개로 작업했었기 때문에, 이번 todostasks의 관계를 구현하면서 좋은 RDS, 정규화 맛보기가 될 것이라 생각합니다.

2) 테스트에 익숙해지기

  • react 컴포넌트보다 REST api가 테스트에 더 용이하다고 생각됩니다. 테스트에 익숙해지고, 테스트 하기 쉬운 코드에 대해 감을 잡아보려 합니다.
  • 유닛 테스트와 e2e 테스트를 진행하면서, 좀 더 안정성 있는 서비스를 만드는 습관을 들일 수 있을 것이라 생각합니다.

3) 백엔드 이해하기

  • 직접 스웨거 문서를 만들고, api를 짜면서 겪은 경험을 통해서 (1)앞으로 문제 상황이 발생했을 때 원인 파악에 도움이 되고 (2)스스로 해결할 수 있는 범위가 넓어질 것이라고 생각합니다.
  • NestJS의 config이나 데코레이터 기능 알기
app.useGlobalPipes(new ValidationPipe({
  whitelist: true,
  forbidNonWhitelisted: true, // 가비지한 값 아예 거름
  transform: true // Param 받아서 넘겨줄 때 타입 맞게 transfrom
}))

4) AWS랑 친해지기 (AWS를 통해서 RDS, Docker 사용하기)

  • 서버리스에 편함에 익숙해지면서, AWS에 대한 필요성을 느끼지 못했던 기간이 있습니다.
  • 컨퍼런스나 온라인 세션을 통해 AWS에서 제공하는 서비스를 통해 간단히 구현할 수 있는 사례도 알게되었고, 또한 웹개발에 대한 시야를 넓히기 위해서 AWS와 좀 더 친해지려 노력 중입니다.

image
image

일요일 공부 끝!

  • 7시간 26분 🪴

api 임시 배포: heroku_231115

api 임시 배포: heroku

  • 1회차 api 작업 목표일자인 금요일까지 완료하기 위해서 임시 배포했습니다.
    • 학습 이후에 docker + AWS EC2로 변경 예정
  • 구현
    • /posts api 확인 후, 배포 주소 전달함
    • /tasks api 기능 구현 완료 필요

오공완! 🌱

시간: 11월 15일, 9시반~11시 55분
공부: nestJS 기초 공부 by 공식문서, udemy 강의
내용: emitDecoratorMetadata, inversion of control, DI container

image

메모 ✏️

  • findOne 버그 수정
    • id로 특정 아이템 찾을 때, NotFoundException 추가 (그런데 에러가 안 뜬다면?!)
    • id로 특정 아이템 찾을 때, await 없으면 그냥 Promise {<pending>}
      • falsey로 안 잡힘 ⇒ NotFoundExcepotion 404로 못 잡고 그냥 200
async findOne(id: Todo["id"]): Promise<Todo> {
  const todo = await this._todoRepository.findOneBy({ id: id });

  if (!todo) throw new NotFoundException(`Todo ${id} not found`);
  return todo;
}
  • inversion of control 제어권 전위
    • 복잡성 ⇒ 너무 많은 코드
      • 한 서비스에 여러 레포
      • 한 클래스에 여러 서비스
  • injectaion!
// A. origin
export class TodoService {
  todoRepo: todoRepository;

  constructor(todoRepo: TodoRepository) {
    this.todoRepo = todoRepo;
  }
}

// B. typescript syntatic sugar
export class TodoService {
  constructor(public todoRepo: TodoRepository) {}
}

// C. 데코레이터
@Injectable() // Marking the class for registration(inside of the DI container), the registration process'll be automatically applied to the decorator.
  constructor(
    @Inject("TASK_REPOSITORY")
    private _taskRepository: Repository<Task>
  ) {}
}
  • provider : things that can be used as dependencies for other classes
@Module({
   controllers: [~~Controller],
   providers: [~~Service, ~~Repository]
})

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.