Over-fethcing && Under-fetching

공부의 기록·2021년 11월 12일
0

Dev Computer Science

목록 보기
7/18
post-thumbnail

서론

당신이 RESTful API 를 통해서 데이터를 받을 때,
다음과 같은 상황이 있었을 것이다.

  1. 한 모델 데이터의 일부분만 필요한 상황
  2. 다수 모델의 데이터의 일부분 씩이 필요한 상황.

그런데 이 모든 경우에 우리는 불필요할 정도로 많은 데이터를 받아야 한다.
그것은 기본적으로 RESTful APIjson 타입으로 정보를 넘겨주기 때문이기도 하다.

아래에서 1번 Over-fetching 과 2번 Under-fetching 에 대해서 자세히 알아보도록 하겠다.

사전 정의

당신은 mongoDB 를 사용하고 있고 mongoose 의 Schema 기능을 통해 다음과 같은 데이터 모델을 다루고 있다. express 를 통해서 프로젝트 셋팅이 끝났다는 전제를 하고 있으며 Controller 에서 데이터 요청을 하는 상황이다. View Template 로는 [PUG]를 사용하고 있다.

  1. userSchema && userModel(User)
const userSchema=mongoose.Schema({
  email: {type:String, required:true},
  username: {type:String, required:true},
  password: {type:String, required:true},
  description: {type:String},
  imageArray: [ {type:mongoose.Schema.Types.ObjectId, ref:"Image"} ],
});
const userModel=mongoose.model("User",userSchema);
  1. imageScheam && imageModel(Image)
const imageSchema=mongoose.Schema({
  title: {type:String, required:true, default:"untitled"},
  imageURL: {type:String, required:true, default:null},
  owner: {type:mongoose.Schema.Types.ObejctId, ref:"User"},
});
const imageModel=mongoose.model("Image",imageSchema);

Over-fetching

한줄 설명

한 대상에서 일부분의 데이터만 필요한 경우에도, 해당 대상의 모든 데이터를 받게 되는 문제점

코드 예시

당신은 유저 검색과 관련된 Controllers 를 만들어야 한다.
당신이 [H] 를 입력하면 유저 이름에 [H]가 들어간 사람을 찾는 것이다.

import userModel from "../model/userModel";
export const searchUserGet=async(req,res)=>{
  const { saerch:username }=req.body;
  
  const userDB=await userModel.findOne({username});
  return (userDB) ?
    res.render(".../view/screen/searchPage.pug",{ userDB }) : 
    res.render(".../view/screen/searchPage.pug",{ userDB:null, error:"404 Not Found"});
};

위 코드를 통해 당신은 다음과 같은 유저 배열을 얻게 되었다.

const userDB=[
  {
    id:124151351421
    email:"Anonymous001@gmail.com",
    username:"Anonymous001",
    password:"malktmkqelmtlkeqm",
    description:"I'm anonymous! Nice to meet you",
    imageArray:[]
  },
  {
    id:521513214122 
    email:"Hello@gmail.com",
    username:"Hello",
    password:"qtklmeqkltmkqler"
    description:"Hello It's a Test Object Array",
    imageArray:[ObjectId(142142151),ObjectId(15125124)]
  }
];

그런데 당신의 View Template 에서는 다음의 정보만을 사용한다.

  1. id : 유저 고유값
  2. username : 유저 이름
  3. imageArray : 업로드한 이미지 보유 여부

그렇기 때문에 다음과 같은 문제점 들을 겪게 되었다.

  1. email, password : 같은 민감성 정보를 frontend 에서 다루게 되는 이슈
  2. description : 같이 상대적으로 많은 데이터 공간을 할애하는 정보도 주고받게 되는 이슈

이것이 RESTful API 에서 데이터를 받아올 때 발생할 수 있는 현상이며 이를, Over-fetching 이라고 부른다.

Under-fetching

한줄 설명

N 개의 대상의 데이터를 받기 위해서는 N 번의 API 호출이 필요한 문제점

코드 예시

당신은 인스타그램을 클론코딩 하려고 한다.
수많은 기능 중에서도 당신은 개인피드 에서 기본기능을 담은 세 가지 화면을 보여주려고 한다.

  1. 개인 피드
  2. 상세 이미지
  3. 팔로우, 팔로잉 확인

2번과 3번을 위해서 각 mongooseSchema 에 새로운 항목을 넣고 DB 를 이전했다.

  1. userSchema
userSchema=mongoose.Schema({
  following:[{type:mongoose.Schema.Types.ObjectId, ref:"User"}],
  followed:[{type:mongoose.Schema.Types.ObjectId, ref:"User"}]
)};
  1. imageScheam
imageSchema=mongoose.Schema({
  descirption:{type:String},
  hahstags:{type:String},
});

Controller 를 만들기 전에,
각 화면에서 어떠한 모델의 어떤 정보가 필요한지 생각해보자.

  1. 개인피드
    1.1. userModel

  2. 상세 이미지
    2.1. userModel
    2.2. imageModel

  3. 팔로잉, 팔로우 확인
    3.1. userModel

이제 각 부분의 controller를 만들어보자

import userModel from "../model/userModel";
import imageModel from "../model/imageModel";

export const feedGet=async(req,res)=>{
  const { id:userId }=req.params;
  
  const userDB=await userModel.findById({id}).populate("Image");
  return (userDB) ?
    res.render(".../view/template/userFeed",{ userDB } :
    res.render(".../view/template/userFeed",{ userDB:null, error:"404" };
};

export const detailGet=async(req,res)=>{
  const { id:imageId }=req.params;
  
  const imageDB=await imageModel.findById({id}).populate("User");
  return (imageDB) ?
    res.render(".../view/template/imageDetail",{ imageDB } :
    res.render(".../view/template/imageDetail",{ imageDB:null, error:"404" };
};
export const followListGet=async(req,res)=>{
  const { id:userId }=req.params;
  
  const userModel=await userModel.findById({id});
  return (userModel) ?
    res.render(".../view/template/followList",{ imageDB } :
    res.render(".../view/template/followList",{ imageDB };
};

위 코드를 보면 알 수 있겠지만,
userModel 과 imageModel 데이터를 호출할 때 2줄의 코드를 쓰는 것이 아니라
populate 메서드(mongoose)를 이용해서 1줄의 코드로 호출한 것을 알 수 있다.

하지만,
morgan 같은 상태관리 모듈을 설치해서 API 호출 내역을 살펴보면..
여러 번의 API 호출 내역이 발생한 것을 알 수 있다.

GET /userModel/:id
GET /imageModel/:id

이렇듯
하나의 Controller(서비스, 페이지 등)를 표현하기 위해서
여러 번의 API 호출이 발생하게 되는 상황을 Under-fethcing 이라고 한다.

해결 방안

그렇다면 이러한 문제를 해결할 수 있는 방법에는 어떠한 것이 있을까?
가장 대표적인 해결 방법은 GraphQL이다.

profile
2022년 12월 9일 부터 노션 페이지에서 작성을 이어가고 있습니다.

0개의 댓글