카테고리 없음

7. 미니터(Miniter) API 개발 (팔로우와 언팔로우 엔드포인트)

Fullstacknology 2022. 1. 6. 15:02

  이번에 구현할 엔드포인트는 팔로우와 언팔로우 기능이다. 팔로우 한 사용자의 타임라인을 볼 수 있게 하는 기능이다. 팔로우, 언팔로우하고 싶은 사용자의 아이디를 HTTP 요청으로 보내면 API에서 요청을 처리하는 식으로 구현할 것이다. 

 

 

팔로우 엔드포이트에 전송할 JSON 데이터는 다음과 같다.

 

{"id" : 1,    "follow" : 2}    # id는 해당 사용자의 아이디, follow는 팔로우 하고자하는 사용자의 아이디

 

 

 

언팔로우 엔드포인트에 전송할 JSON 데이터는 다음과 같다.

 

{"id" : 1,    "unfollow" : 2}

 

 

 

팔로우와 언팔로우의 코드는 다음과 같다. 

 

@app.route("/follow", methods=['POST'])
def follow():
    payload            = request.json
    user_id            = int(payload['id'])
    user_id_to_follow  = int(payload['follow'])               # 언팔로우는 unfollow 입력
    
    if user_id not in app.users or user_id_to_follow not in app.users:
        return '사용자가 존재하지 않습니다.', 400
    
    user = app.users[user_id]
    user.setdefault('follow', set()).add(user_id_to_follow)   # unfollow 의 경우 add 대신에 discard
    
    return jsonify(user)

 

 

  팔로우, 언팔로우 요청이 중복되게 들어온 경우 중복된 ID가 여러번 저장되는 것을 방지하기 위해서 list가 아닌 set을 사용한다. 

 

  문제는 set은 list 와 다르게 json 모듈에 의해 JSON으로 변경되지 않는다. 따라서 임의로 set을 json으로 변환하도록 해야 하는데 이를 위해서 기존의 JSONEncoder를 상속하는 CustomJSONEncoder 클래스를 만들어 해결하도록 한다. 코드는 아래와 같다. 

 

 

from flask.json import JSONEncoder

class CustomJSONEncoder(JSONEncoder):
    def default(self, obj):
        if isinstance(obj, set):
            return list(obj)
        
        return JSONEncoder.default(self, obj)
        
app.json_encoder = CustomJSONEncoder

 

 

 

지금까지의 전체 코드는 다음과 같다. 

 

 

from flask import Flask, jsonify, request
from flask.json import JSONEncoder

class CustomJSONEncoder(JSONEncoder):
    def default(self, obj):
        if isinstance(obj, set):
            return list(obj)
        
        return JSONEncoder.default(self, obj)

app                 = Flask(__name__)
app.id_count        = 1
app.users           = {}
app.tweets          = []
app.json_encoder    = CustomJSONEncoder

@app.route("/ping", methods=['GET'])
def ping():
    return "pong"

@app.route("/sign-up", methods=['POST'])
def sign_up():
    new_user                        = request.json
    new_user["id"]                  = app.id_count
    app.users[app.id_count]         = new_user
    app.id_count                    = app.id_count +1
    
    return jsonify(new_user)

@app.route("/tweet", methods=['POST'])
def tweet():
    payload     = request.json
    user_id     = int(payload['id'])
    tweet       = payload['tweet']

    if user_id not in app.users:
        return '사용자가 존재하지 않습니다.', 400
    
    if len(tweet) > 300:
        return '300자를 초과했습니다.', 400
    
    user_id = int(payload['id'])
    app.tweets.append({'user_id': user_id, 'tweet': tweet})
    
    return '', 200

@app.route("/follow", methods=['POST'])
def follow():
    payload              = request.json
    user_id              = int(payload['id'])
    user_id_to_follow    = int(payload['follow'])

    if user_id not in app.users or user_id_to_follow not in app.users:
        return '사용자가 존재하지 않습니다.', 400
    
    user = app.users[user_id]
    user.setdefault('follow', set()).add(user_id_to_follow)

    return jsonify(user)

@app.route("/unfollow", methods=['POST'])
def unfollow():
    payload             = request.json
    user_id             = int(payload['id'])
    user_id_to_follow   = int(payload['unfollow'])

    if user_id not in app.users or user_id_to_follow not in app.users:
        return '사용자가 존재하지 않습니다.', 400
    
    user = app.users[user_id]
    user.setdefault('follow', set()).discard(user_id_to_follow)

    return jsonify(user)