TIL(12월 26일)

오세명·2021년 12월 26일
0

1. Mongoose

1.1 Schema

  • 연결된 주소에서 컬렉션을 만들고, 그 컬렉션에서 생성되는 다큐먼트의 모양을 정의한다.
  • mongoose 모듈의 Schema 생성자 함수를 인스턴스화하여 생성하는데, 인자로 전달하는 option 객체를 통해 스키마의 형태가 구체화된다.
const mongoose = require('mongoose');
const someSchema = new mongoose.Schema(option)
  • option 객체의 key는 다큐먼트의 필드명이 되며, value는 해당 필드에 관한 정보를 바인딩한다.

1.1.1 NestedObject type definition

  • 어떤 필드가 중첩된 객체 타입을 가질 때, 두 가지의 방법을 통해 타입을 정의할 수 있다.
  • 하나는 필드에 바인딩되는 값에 직접 객체를 할당하고 그 객체 타입의 필드를 직접 정의한다.
  • 새로운 스키마를 만들고, 해당 필드에 바인딩한다. 스키마 레퍼런스를 사용하면 새로운 다큐먼트가 만들 때 해당 필드에 대해 새로운 ObjectId가 만들어진다.
  • 두 가지 방법 중 옳고 그른 것은 없으며, 상황에 맞게 사용하면 된다.
// 1.
new mongoose.Schema({
  address: {
    street: String,
    name: String,
  }
})

// 2.
const addressSchema = new mongoose.Schema({
  street: String,
  name: String,
})

new mongoose.Schema({
  address: addressSchema
})

1.2 Model

  • 실제 다큐먼트를 생성하는 생성자 함수이다.
  • 인자로 전달된 스키마 타입을 준수한다.
  • 모델의 인스턴스가 다큐먼트이다.
const someModel = mongoose.model(collectionName, schemaName)

1.3 CRUD

1.3.1. CREATE

// 1. 쿼리 생성 후 저장
const inMemoryDocument = new Model(document);
inMemoryQuery
  .save()
  .then(successCallback)
  .catch(failureCallback)

// 2. await 키워드를 이용한 다큐먼트 생성
// 프라미스, 콜백 패턴 전부 사용할 수 있다.
await Model.create(document): Promise<T>
Model.create(document, Callback: (error, result) => void)

1.3.2. READ

  1. 쿼리 생성후 .exec() 메서드로 조회
const query = Model.find({})
const foundData = query.exec();
foundData.then(...)
  1. await 키워드로 쿼리를 직접 실행
// 위와 아래는 같음
const foundData = await Model.find({})
const foundData = await Model.find({}).exec();

1.3.3. UPDATE

  • 만약 스키마를 정의할 때 어떤 필드에 대해 Built-in Validation을 추가로 설정하였다면, 편리해 보이는 모든 메서드를 사용하지 않는 것이 좋다고 한다. 왜냐하면 그러한 메서드는 스키마 벨리데이션 타입을 무시하고 직접 업데이트를 하기 때문이다.
  • 따라서 로컬에서 해당 다큐먼트를 읽은 후 뮤테이션을 한다음 save 메서드로 db에 저장하는 것을 추천한다.

1.3.4. DELETE

  • 1.3.3의 예외로, 삭제의 경우 스키마 벨리데이션을 할 필요가 없기 때문에 편리한 메서드를 자유롭게 써도 무방하다고 한다.

<추가로 공부할 부분>
1. Populate
2. SQL vs NOSQL
3. Database indexing

2. RTK(Reduxjs/toolkit)

  • 리덕스 코어를 재미있게 공부한 다음 한동안 리코일을 열심히 공부하였다. 상태관리 라이브러리마다 각각의 특징이 있기 때문에 다시 한 번 리덕스를 보면서 리코일과 비교를 해보고 싶었다.
  • App을 구성하는 글로벌 스테이트 섹션과 로직을 slice 단위로 관리하는 것이 편해보였다.
  • 툴킷의 유틸 함수가 기존 코어의 불편함을 많이 해소시켜준다고 하는데, 내일 관심있게 봐야겠다.

2.1. How to make slice

  • createSlice 함수에 options 객체를 전달하여 생성한다.

  • Fields of options

    1. The name of state: string
    2. initialState: any
    3. reducer: 객체인데, 뒤에 상술할 액션 타입에 대해 newState를 리턴하거나 기존 state를 뮤테이션 하는 로직을 작성한 함수가 바인딩된다. immer를 적용한 것과 동시에 switch 문으로 분기처리를 했던 코어 로직보다 훨씬 더 가독성이 좋아진 것을 확인하였다.
    4. extraReducers: Thunk 미들웨어로부터 dispatch된 액션들에 대해 처리할 로직을 작성한다. 비동기 프로세스를 라이프사이클로 해석하여 진행, 성공, 실패에 따라 분기처리를 한다. actionCreator.toString()이 암묵적으로 액션 타입을 반환한다는 점에서 신선하였다. 코어에서는 비동기 로직을 모두 처리한 다음 리듀서와 직접적으로 연관된 액션(툴킷에서는 3.reducer와 관련된 액션)으로 전달하는데, 3의 경우 1에서 정의된 도메인에 한정적으로 로직이 그려지기 때문에 이러한 장치를 마련하지 않았나 싶다. createAsyncThunk API를 한 번 정독해봐야 겠다.
  • ReturnValue: sliceObject

    1. sliceObject.actions: ActionCreator 함수들이 바인딩 된 객체이다. nameOfSlice/keyOfReducer의 형태로 액션 타입이 결정되며, keyOfReducer 프로퍼티에 해당 크리에이터가 바인딩된다.
    2. sliceObject.reducer: 잘 아는 리듀서이다.

2.2. How to make store

  • configureStore 함수에 options 객체를 전달하여 만들 수 있다.
  • options 객체의 reducers 프로퍼티는 객체를 바인딩하는데, 이 객체의 key가 top-level state의 한 섹션이되며, 바인딩 되는 함수가 해당 섹션의 리듀서 함수가 된다.
  • reducers 프로퍼티 말고 다른 옵션은 무엇이 있는지 찾아보아야 겠다.

<추가로 할 일>
1. 튜토리얼 마지막 부분 정독
2. 간단한 미니 프로젝트(RTK & EXPRESS)

profile
오네명입니다.

0개의 댓글