8-4. 포스트 로딩 구현하기

먼저 초기 로딩을 구현해보겠습니다. 우리가 초기로딩 / 추가로딩 / 특정 유저로딩 을 하게 될 때에, Post 메소드에 하나의 스태틱 메소드를 만들어서 구현을 할것인데요, 한꺼번에 구현하지 않고, 하나 하나 단계별로 구현을 해보도록 하겠습니다.

list 메소드에서 초기로딩 로직 작성하기

우선, Post 모델에 list 스태틱 메소드륾 만들고 다음과 같이 20개의 포스트를 역순으로 불러오는 코드를 작성해보세요:

src/models/post.js

(...)

// 포스트 리스팅
Post.statics.list = function({cursor, username, self}) {
    // 파라미터에 cursor, username, self 가 담긴 객체를 받게 되는데, 
    // 이번 구현 할 때에는 사용되지 않습니다.

    // 나중에 파라미터에 받는 값에 따라 다른 쿼리내용을 가지게 됩니다. 일단은 특별 조건 없이 일반 적인 쿼리를 먼저 구현하겠습니다.
    const query = {}; 

    return this.find(query)
        .sort({_id: -1}) // _id 역순
        .limit(20) // 20개로 제한
        .exec();
};
module.exports = mongoose.model('Post', Post);

꽤 간단하지요? 이제 이것을 리스팅 API 에서 사용해봅시다!

list API - 초기 로딩 구현하기

src/posts/posts.controller.js - list

exports.list = async (ctx) => {
    let posts = null;
    try {
        posts = await Post.list({}); // 임시적으로 빈 객체를 전달해줍니다. 나중엔 파라미터들이 들어가게 됩니다.
    } catch (e) {
        ctx.throw(500, e);
    }

    // 만약에 불러올 데이터가 20개라면, 그 다음 데이터들이 더 있을 수 있습니다.
    // 현재 불러온 데이터 중 가장 마지막 데이터를 기점으로 데이터를 추가적으로 로딩하는 API 의 주소를 만들어줍니다.
    const next = posts.length === 20 ? `/api/posts/?cursor=${posts[19]._id}` : null;

    //  데이터와, 그 다음 데이터를 가져오는 API 주소를 응답합니다.
    ctx.body = {
        next, 
        data: posts
    };
};

초기로딩 API 부분은 끝났습니다! 한번 다음과 같이 테스트 요청을 해보세요.

GET http://localhost:4000/api/posts/
{
    "next": "/api/posts/?cursor=595f8958e3d79767f1e3541d",
    "data": [
        {
            "_id": "595f8972e3d79767f1e35430",
            "count": 51,
            "username": "veloperet",
            "content": "테스팅테스팅",
            "__v": 0,
            "comments": [],
            "likes": [],
            "likesCount": 0,
            "createdAt": "2017-07-07T13:15:30.095Z"
        },
        (...)
        {
            "_id": "595f8958e3d79767f1e3541d",
            "count": 32,
            "username": "veloperet",
            "content": "테스팅테스팅",
            "__v": 0,
            "comments": [],
            "likes": [],
            "likesCount": 0,
            "createdAt": "2017-07-07T13:15:04.270Z"
        }
    ]
}

데이터의 갯수가 20개로 제한되어 나타나게 됩니다. 그리고 next 에 그 다음 데이터들을 불러오는 링크가 주어집니다.

list 메소드에서 추가로딩 / 유저 선택 로딩 로직 작성하기

기존에 만들었던 list 메소드를 조금 수정하여, 특정 id (cursor) 가 주어지면 그 값보다 값이 낮은 데이터들을 불러오고, 또 username 값이 주어지면, 특정 유저가 작성한 포스트들을 로딩을 할 수 있도록, 쿼리가 유동적으로 설정 될 수 있게 코드를 작성해보겠습니다.

src/models/post.js

Post.statics.list = function({cursor, username, self}) {
    // cursor, username 값의 존재 유무에 따라 쿼리가 유동적으로 설정됩니다.
    const query = Object.assign(
        { }, 
        cursor ? { _id: { $lt: cursor } } : { },
        username ? { username } : { }
    );

    return this.find(query)
        .sort({_id: -1}) // _id 역순
        .limit(20) // 20개로 제한
        .exec();
};

여기서 Object.assign 이 사용 된 이유는, 만약에 { cursor, username } 을 그대로 전달하게 된다면 파라미터 값이 설정되지 않았을 때는 이 값들에 undefined 로 설정되어 원하지 않는 결과가 나타나기 때문입니다. 따라서, 객체들을 합치는 방식으로 쿼리를 유동적으로 조합합니다.

list API - 추가로딩 / 유저 선택 로딩 구현하기

이제 방금 수정한 메소드를 통하여 추가로딩과 유저선택로딩도 구현해봅시다. 아까 전 코드와 달라지는 부분은 /api/posts?username=____&cursor=____ 이런식으로 URL 쿼리 값을 받아오는데, 이 부분을 검증하고 메소드를 실행한다는 것 입니다.

src/posts/posts.controller.js - list

const ObjectId = require('mongoose').Types.ObjectId;

(...)

exports.list = async (ctx) => {
    const { cursor, username } = ctx.query; // URL 쿼리에서 cursor 와 username 값을 읽는다

    // ObjectId 검증
    if(cursor && !ObjectId.isValid(cursor)) {
        ctx.status = 400; // Bad Request
        return;    
    }

    let posts = null;
    try {
        posts = await Post.list({cursor, username}); // cursor, username 파라미터를 넣어줍니다
    } catch (e) {
        ctx.throw(500, e);
    }

    // 만약에 불러올 데이터가 20개라면, 그 다음 데이터들이 더 있을 수 있습니다.
    // 현재 불러온 데이터 중 가장 마지막 데이터를 기점으로 데이터를 추가적으로 로딩하는 API 의 주소를 만들어줍니다.
    const next = posts.length === 20 ? `/api/posts/?${username ? `username=${username}&` : ''}cursor=${posts[19]._id}` : null;


    //  데이터와, 그 다음 데이터를 가져오는 API 주소를 응답합니다.
    ctx.body = {
        next, 
        data: posts
    };
};

username 값이 주어졌을 때, next 링크에 username 값도 설정해주는 것 잊지마세요.

이제 추가 로딩과 유저 선택 로딩도 완성이 되었습니다! Postman 에서 아까 전에 테스트 했던 포스트 리스트 결과에서, next 링크 부분을 마우스로 클릭하면 그 주소가 바로 포스트맨 주소창을 복사됩니다. 해당 링크를 통하여 그 다음 포스트들도 확인해보세요.

그 다음엔 http://localhost:4000/api/posts/?username=velopert 이런식으로 username 을 설정하여 쿼리를 해보세요. 이를 테스트 하는 과정에서는 새 계정을 하나 더 만들어서 포스트를 몇개 작성을 하고 테스팅을 하거나, 아니면 첫번째 요청에선 username 을 제대로 입력하고 그 다음 요청에선 username 에 아직 만들지 않은 계정의 유저명을 넣어보세요. 첫번째 요청에선 데이터를 전달받고 두번째 요청에서는 데이터가 비어있으면 성공 한 것입니다.

results matching ""

    No results matching ""