Python์—์„œ API ์ž‘์„ฑ(Flask ๋ฐ RapidAPI ์‚ฌ์šฉ)

Python์—์„œ API ์ž‘์„ฑ(Flask ๋ฐ RapidAPI ์‚ฌ์šฉ)

์ด ๊ธฐ์‚ฌ๋ฅผ ์ฝ๊ณ  ์žˆ๋‹ค๋ฉด API(Application Programming Interface)๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์—ด๋ฆฌ๋Š” ๊ฐ€๋Šฅ์„ฑ์— ์ด๋ฏธ ์ต์ˆ™ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋งŽ์€ ๊ณต์šฉ API ์ค‘ ํ•˜๋‚˜๋ฅผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ถ”๊ฐ€ํ•˜์—ฌ ์ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•˜๊ฑฐ๋‚˜ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋กœ ๋ณด์™„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ปค๋ฎค๋‹ˆํ‹ฐ์™€ ๊ณต์œ ํ•˜๊ณ  ์‹ถ์€ ๊ณ ์œ ํ•œ ๊ธฐ๋Šฅ์„ ๊ฐœ๋ฐœํ–ˆ๋‹ค๋ฉด ์–ด๋–จ๊นŒ์š”?

๋Œ€๋‹ต์€ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋งŒ์˜ API ๋งŒ๋“ค๊ธฐ.

์ด๊ฒƒ์€ ์ฒ˜์Œ์—๋Š” ์–ด๋ ค์šด ์ž‘์—…์ฒ˜๋Ÿผ ๋ณด์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. Python์œผ๋กœ ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

์‹œ์ž‘ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๊ฒƒ

API ๊ฐœ๋ฐœ์—๋Š” ๋‹ค์Œ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

  • ํŒŒ์ด์ฌ 3;
  • ํ”Œ๋ผ์Šคํฌ โ€” ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ๊ฐ„๋‹จํ•˜๊ณ  ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฌ์šด ํ”„๋ ˆ์ž„์›Œํฌ
  • ํ”Œ๋ผ์Šคํฌ-ํœด์‹ ์ตœ์†Œํ•œ์˜ ๊ตฌ์„ฑ์œผ๋กœ REST API๋ฅผ ๋น ๋ฅด๊ฒŒ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋Š” Flask์˜ ํ™•์žฅ์ž…๋‹ˆ๋‹ค.

์„ค์น˜๋Š” ๋‹ค์Œ ๋ช…๋ น์œผ๋กœ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.

pip install flask-restful

์ดˆ๋ณด์ž๋ฅผ ์œ„ํ•œ ๋ฌด๋ฃŒ ์ง‘์ค‘ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.
C#์—์„œ ํ…”๋ ˆ๊ทธ๋žจ ๋ด‡ ๊ฐœ๋ฐœ โ€” 26์›” 28~XNUMX์ผ. ๋„์šฐ๋ฏธ ๋ด‡์˜ ์ž‘๋™ ๋ฐฉ์‹, Telegram API ์ž‘์—… ๊ธฐ๋Šฅ ๋ฐ ๊ธฐํƒ€ ๋‰˜์•™์Šค๋ฅผ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌด๋ฃŒ ์ง‘์ค‘ ํ”„๋กœ๊ทธ๋žจ์ž…๋‹ˆ๋‹ค. ์ƒ์œ„ 30๋ช…์˜ ์ฐธ๊ฐ€์ž๋Š” Skillbox์—์„œ 000๋ฃจ๋ธ”์„ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค..

์‹œ์ž‘ํ•˜๊ธฐ ์ „์—

์šฐ๋ฆฌ๋Š” ๊ธฐ๋ณธ์œผ๋กœ RESTful API๋ฅผ ๊ฐœ๋ฐœํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. CRUID ๊ธฐ๋Šฅ.

์ž‘์—…์„ ์™„์ „ํžˆ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๋‘ ์šฉ์–ด๋ฅผ ์ดํ•ดํ•ฉ์‹œ๋‹ค.

REST ๋ž€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

REST API(Representational State Transfer)๋Š” HTTP ์š”์ฒญ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตํ™˜ํ•˜๋Š” API์ž…๋‹ˆ๋‹ค.

REST API๋Š” ํŠน์ • ๊ธฐ์ค€์„ ์ถฉ์กฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ํด๋ผ์ด์–ธํŠธ-์„œ๋ฒ„ ์•„ํ‚คํ…์ฒ˜: ํด๋ผ์ด์–ธํŠธ๋Š” ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ƒํ˜ธ ์ž‘์šฉํ•˜๊ณ  ์„œ๋ฒ„๋Š” ๋ฐฑ์—”๋“œ ๋ฐ ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ์™€ ์ƒํ˜ธ ์ž‘์šฉํ•ฉ๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๋Š” ๋…๋ฆฝ์ ์ด๋ฉฐ ๋‘˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ์„œ๋กœ ๋ณ„๋„๋กœ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ƒํƒœ ๋น„์ €์žฅ - ํด๋ผ์ด์–ธํŠธ ๋ฐ์ดํ„ฐ๊ฐ€ ์„œ๋ฒ„์— ์ €์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์„ธ์…˜ ์ƒํƒœ๋Š” ํด๋ผ์ด์–ธํŠธ ์ธก์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.
  • ์บ์‹œ ๊ฐ€๋Šฅ์„ฑ - ํด๋ผ์ด์–ธํŠธ๋Š” ์ „๋ฐ˜์ ์ธ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๊ธฐ ์œ„ํ•ด ์„œ๋ฒ„ ์‘๋‹ต์„ ์บ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

CRUD๋ž€?

ํฌ๋ฃจ๋“œ ๋„ค ๊ฐ€์ง€ ๊ธฐ๋ณธ ์ž‘์—…(๋งŒ๋“ค๊ธฐ, ์ฝ๊ธฐ, ์—…๋ฐ์ดํŠธ ๋ฐ ์‚ญ์ œ)์„ ์„ค๋ช…ํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค.

REST API์—์„œ ์š”์ฒญ ์œ ํ˜• ๋ฐ ์š”์ฒญ ๋ฉ”์„œ๋“œ๋Š” ๊ฒŒ์‹œ, ๊ฐ€์ ธ์˜ค๊ธฐ, ๋„ฃ๊ธฐ, ์‚ญ์ œ์™€ ๊ฐ™์€ ์ž‘์—…์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ๊ธฐ๋ณธ ์šฉ์–ด๋ฅผ ๋‹ค๋ฃจ์—ˆ์œผ๋ฏ€๋กœ API ์ƒ์„ฑ์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ะ ะฐะทั€ะฐะฑะพั‚ะบะฐ

์ธ๊ณต ์ง€๋Šฅ์— ๋Œ€ํ•œ ์ธ์šฉ๋ฌธ ์ €์žฅ์†Œ๋ฅผ ๋งŒ๋“ค์–ด ๋ด…์‹œ๋‹ค. AI๋Š” ์˜ค๋Š˜๋‚  ๊ฐ€์žฅ ๋น ๋ฅด๊ฒŒ ์„ฑ์žฅํ•˜๋Š” ๊ธฐ์ˆ  ์ค‘ ํ•˜๋‚˜์ด๋ฉฐ Python์€ AI ์ž‘์—…์— ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

์ด API๋ฅผ ํ†ตํ•ด Python ๊ฐœ๋ฐœ์ž๋Š” AI์— ๋Œ€ํ•ด ๋น ๋ฅด๊ฒŒ ๋ฐฐ์šฐ๊ณ  ์ƒˆ๋กœ์šด ์„ฑ๊ณผ์—์„œ ์˜๊ฐ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๊ฐ€ ์ด ์ฃผ์ œ์— ๋Œ€ํ•ด ๊ฐ€์น˜ ์žˆ๋Š” ์ƒ๊ฐ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด ์ €์žฅ์†Œ์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•„์š”ํ•œ ๋ชจ๋“ˆ์„ ๊ฐ€์ ธ์˜ค๊ณ  Flask๋ฅผ ์„ค์ •ํ•˜์—ฌ ์‹œ์ž‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

from flask import Flask
from flask_restful import Api, Resource, reqparse
import random
app = Flask(__name__)
api = Api(app)

์ด ์Šค๋‹ˆํŽซ์—์„œ Flask, Api ๋ฐ Resource๋Š” ํ•„์š”ํ•œ ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.

Reqparse๋Š” Flask-RESTful ์š”์ฒญ ๊ตฌ๋ฌธ ๋ถ„์„ ์ธํ„ฐํŽ˜์ด์Šค์ž…๋‹ˆ๋‹ค... ์ž„์˜ ์ธ์šฉ์„ ํ‘œ์‹œํ•˜๋ ค๋ฉด random ๋ชจ๋“ˆ๋„ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ์šฐ๋ฆฌ๋Š” AI์— ๋Œ€ํ•œ ์ธ์šฉ๋ฌธ ์ €์žฅ์†Œ๋ฅผ ๋งŒ๋“ค ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ฐ ์ €์žฅ์†Œ ํ•ญ๋ชฉ์—๋Š” ๋‹ค์Œ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

  • ๋””์ง€ํ„ธ ID;
  • ์ธ์šฉ๋ฌธ ์ž‘์„ฑ์ž์˜ ์ด๋ฆ„;
  • ์ธ์šฉํ•˜๋‹ค.

์ด๊ฒƒ์€ ํ•™์Šต ์˜ˆ์ œ์ผ ๋ฟ์ด๋ฏ€๋กœ ๋ชจ๋“  ํ•ญ๋ชฉ์„ Python ๋ชฉ๋ก์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ๋Œ€์‹  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค.

ai_quotes = [
    {
        "id": 0,
        "author": "Kevin Kelly",
        "quote": "The business plans of the next 10,000 startups are easy to forecast: " +
                 "Take X and add AI."
    },
    {
        "id": 1,
        "author": "Stephen Hawking",
        "quote": "The development of full artificial intelligence could " +
                 "spell the end of the human raceโ€ฆ " +
                 "It would take off on its own, and re-design " +
                 "itself at an ever increasing rate. " +
                 "Humans, who are limited by slow biological evolution, " +
                 "couldn't compete, and would be superseded."
    },
    {
        "id": 2,
        "author": "Claude Shannon",
        "quote": "I visualize a time when we will be to robots what " +
                 "dogs are to humans, " +
                 "and Iโ€™m rooting for the machines."
    },
    {
        "id": 3,
        "author": "Elon Musk",
        "quote": "The pace of progress in artificial intelligence " +
                 "(Iโ€™m not referring to narrow AI) " +
                 "is incredibly fast. Unless you have direct " +
                 "exposure to groups like Deepmind, " +
                 "you have no idea how fast โ€” it is growing " +
                 "at a pace close to exponential. " +
                 "The risk of something seriously dangerous " +
                 "happening is in the five-year timeframe." +
                 "10 years at most."
    },
    {
        "id": 4,
        "author": "Geoffrey Hinton",
        "quote": "I have always been convinced that the only way " +
                 "to get artificial intelligence to work " +
                 "is to do the computation in a way similar to the human brain. " +
                 "That is the goal I have been pursuing. We are making progress, " +
                 "though we still have lots to learn about " +
                 "how the brain actually works."
    },
    {
        "id": 5,
        "author": "Pedro Domingos",
        "quote": "People worry that computers will " +
                 "get too smart and take over the world, " +
                 "but the real problem is that they're too stupid " +
                 "and they've already taken over the world."
    },
    {
        "id": 6,
        "author": "Alan Turing",
        "quote": "It seems probable that once the machine thinking " +
                 "method had started, it would not take long " +
                 "to outstrip our feeble powersโ€ฆ " +
                 "They would be able to converse " +
                 "with each other to sharpen their wits. " +
                 "At some stage therefore, we should " +
                 "have to expect the machines to take control."
    },
    {
        "id": 7,
        "author": "Ray Kurzweil",
        "quote": "Artificial intelligence will reach " +
                 "human levels by around 2029. " +
                 "Follow that out further to, say, 2045, " +
                 "we will have multiplied the intelligence, " +
                 "the human biological machine intelligence " +
                 "of our civilization a billion-fold."
    },
    {
        "id": 8,
        "author": "Sebastian Thrun",
        "quote": "Nobody phrases it this way, but I think " +
                 "that artificial intelligence " +
                 "is almost a humanities discipline. It's really an attempt " +
                 "to understand human intelligence and human cognition."
    },
    {
        "id": 9,
        "author": "Andrew Ng",
        "quote": "We're making this analogy that AI is the new electricity." +
                 "Electricity transformed industries: agriculture, " +
                 "transportation, communication, manufacturing."
    }
]

์ด์ œ API ๋์ ์˜ ์ž‘์—…์„ ์ •์˜ํ•  Quote ๋ฆฌ์†Œ์Šค ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํด๋ž˜์Šค ๋‚ด์—์„œ get, post, put, delete์˜ ๋„ค ๊ฐ€์ง€ ๋ฉ”์„œ๋“œ๋ฅผ ์„ ์–ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

GET ๋ฉ”์„œ๋“œ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

ID๋ฅผ ์ง€์ •ํ•˜์—ฌ ํŠน์ • ๊ฒฌ์ ์„ ์–ป๊ฑฐ๋‚˜ ID๊ฐ€ ์ง€์ •๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์ž„์˜์˜ ๊ฒฌ์ ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

class Quote(Resource):
    def get(self, id=0):
        if id == 0:
            return random.choice(ai_quotes), 200
        for quote in ai_quotes:
            if(quote["id"] == id):
                return quote, 200
        return "Quote not found", 404

GET ๋ฉ”์„œ๋“œ๋Š” ID์— ๊ธฐ๋ณธ๊ฐ’์ด ํฌํ•จ๋œ ๊ฒฝ์šฐ ์ž„์˜์˜ ์ธ์šฉ ๋ถ€ํ˜ธ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์‹œ ID๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

์„ค์ •๋œ ๊ฒฝ์šฐ ๋ฉ”์„œ๋“œ๋Š” ๋”ฐ์˜ดํ‘œ ์ค‘์—์„œ ๊ฒ€์ƒ‰ํ•˜๊ณ  ์ฃผ์–ด์ง„ ID๋ฅผ ํฌํ•จํ•˜๋Š” ๋”ฐ์˜ดํ‘œ๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค. ์•„๋ฌด๊ฒƒ๋„ ๋ฐœ๊ฒฌ๋˜์ง€ ์•Š์œผ๋ฉด "Quote not found, 404" ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

์ด ๋ฉ”์„œ๋“œ๋Š” ์š”์ฒญ์ด ์„ฑ๊ณตํ•˜๋ฉด HTTP ์ƒํƒœ 200์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ํ•ญ๋ชฉ์„ ์ฐพ์„ ์ˆ˜ ์—†์œผ๋ฉด 404๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ์ƒˆ ๊ฒฌ์ ์„ ์ถ”๊ฐ€ํ•˜๋Š” POST ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ž…๋ ฅํ•  ๋•Œ ๊ฐ๊ฐ์˜ ์ƒˆ ๊ฒฌ์ ์˜ ID๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ๋˜ํ•œ POST๋Š” reqparse๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์š”์ฒญ ๋ณธ๋ฌธ(์ €์ž ๋ฐ ์ธ์šฉ ํ…์ŠคํŠธ)์— ๋“ค์–ด๊ฐˆ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ตฌ๋ฌธ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค.

def post(self, id):
      parser = reqparse.RequestParser()
      parser.add_argument("author")
      parser.add_argument("quote")
      params = parser.parse_args()
      for quote in ai_quotes:
          if(id == quote["id"]):
              return f"Quote with id {id} already exists", 400
      quote = {
          "id": int(id),
          "author": params["author"],
          "quote": params["quote"]
      }
      ai_quotes.append(quote)
      return quote, 201

์œ„์˜ ์ฝ”๋“œ์—์„œ POST ๋ฉ”์„œ๋“œ๋Š” ๊ฒฌ์  ID๋ฅผ ํ—ˆ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ reqparse๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์š”์ฒญ์—์„œ ์ž‘์„ฑ์ž์™€ ์ธ์šฉ๋ฌธ์„ ๊ฒ€์ƒ‰ํ•˜์—ฌ params ์‚ฌ์ „์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

์ง€์ •๋œ ID๊ฐ€ ์žˆ๋Š” ๊ฒฌ์ ์ด ์ด๋ฏธ ์žˆ๋Š” ๊ฒฝ์šฐ ๋ฉ”์„œ๋“œ๋Š” ์ ์ ˆํ•œ ๋ฉ”์‹œ์ง€์™€ ์ฝ”๋“œ 400์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

์ง€์ •๋œ ID๋ฅผ ๊ฐ€์ง„ ์ธ์šฉ๋ฌธ์ด ์•„์ง ์ƒ์„ฑ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์ด ๋ฉ”์„œ๋“œ๋Š” ์ง€์ •๋œ ID์™€ ์ž‘์„ฑ์ž ๋ฐ ๊ธฐํƒ€ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ ํ•ญ๋ชฉ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ai_quotes ๋ชฉ๋ก์— ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ํ•˜๊ณ  201 ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ์ƒˆ ๊ฒฌ์ ์ด ํฌํ•จ๋œ ํ•ญ๋ชฉ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์˜ ๊ธฐ์กด ๊ฒฌ์ ์„ ๋ณ€๊ฒฝํ•˜๋Š” PUT ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

def put(self, id):
      parser = reqparse.RequestParser()
      parser.add_argument("author")
      parser.add_argument("quote")
      params = parser.parse_args()
      for quote in ai_quotes:
          if(id == quote["id"]):
              quote["author"] = params["author"]
              quote["quote"] = params["quote"]
              return quote, 200
      
      quote = {
          "id": id,
          "author": params["author"],
          "quote": params["quote"]
      }
      
      ai_quotes.append(quote)
      return quote, 201

์ด์ „ ์˜ˆ์ œ์™€ ์œ ์‚ฌํ•œ PUT ๋ฉ”์„œ๋“œ๋Š” ID์™€ ์ž…๋ ฅ์„ ์‚ฌ์šฉํ•˜๊ณ  reqparse๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒฌ์  ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ตฌ๋ฌธ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค.

์ง€์ •๋œ ID์˜ ๊ฒฌ์ ์ด ์žˆ๋Š” ๊ฒฝ์šฐ ๋ฉ”์„œ๋“œ๋Š” ์ƒˆ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ด๋ฅผ ์—…๋ฐ์ดํŠธํ•œ ๋‹ค์Œ ์ฝ”๋“œ 200์œผ๋กœ ์—…๋ฐ์ดํŠธ๋œ ๊ฒฌ์ ์„ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. ์ง€์ •๋œ ID์˜ ๊ฒฌ์ ์ด ์•„์ง ์—†์œผ๋ฉด ์ฝ”๋“œ 201์˜ ์ƒˆ ๋ ˆ์ฝ”๋“œ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ ๋” ์ด์ƒ ์˜๊ฐ์„ ์ฃผ์ง€ ์•Š๋Š” ์ธ์šฉ๋ฌธ์„ ์ œ๊ฑฐํ•˜๋Š” DELETE ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

def delete(self, id):
      global ai_quotes
      ai_quotes = [qoute for qoute in ai_quotes if qoute["id"] != id]
      return f"Quote with id {id} is deleted.", 200

์ด ๋ฉ”์„œ๋“œ๋Š” ๊ฒฌ์ ์˜ ID๋ฅผ ์ž…๋ ฅ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ๊ณต์œ  ๋ชฉ๋ก์„ ์‚ฌ์šฉํ•˜์—ฌ ai_quotes ๋ชฉ๋ก์„ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์„ฑํ–ˆ์œผ๋ฏ€๋กœ API์— ๋ฆฌ์†Œ์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ•œ ๋‹ค์Œ Flask๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

api.add_resource(Quote, "/ai-quotes", "/ai-quotes/", "/ai-quotes/<int:id>")
if __name__ == '__main__':
    app.run(debug=True)

REST API ์„œ๋น„์Šค๊ฐ€ ์ค€๋น„๋˜์—ˆ์Šต๋‹ˆ๋‹ค!

๋‹ค์Œ์œผ๋กœ ์ฝ˜์†”์—์„œ ๋‹ค์Œ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜์—ฌ app.py ํŒŒ์ผ์— ์ฝ”๋“œ๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

python3 app.py

๋ชจ๋“  ๊ฒƒ์ด ์ •์ƒ์ด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

* ๋””๋ฒ„๊ทธ ๋ชจ๋“œ: ์ผœ์ง
* ์‹คํ–‰ ์ค‘ 127.0.0.1:5000/ (Ctrl+C๋ฅผ ๋ˆŒ๋Ÿฌ ์ข…๋ฃŒ)
* ํ†ต๊ณ„๋กœ ๋‹ค์‹œ ์‹œ์ž‘
* ๋””๋ฒ„๊ฑฐ๊ฐ€ ํ™œ์„ฑํ™”๋˜์—ˆ์Šต๋‹ˆ๋‹ค!
* ๋””๋ฒ„๊ฑฐ PIN: XXXXXXX

API ํ…Œ์ŠคํŠธ

API๊ฐ€ ์ƒ์„ฑ๋˜๋ฉด ํ…Œ์ŠคํŠธ๋ฅผ ๊ฑฐ์ณ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด๋Š” curl ์ฝ˜์†” ์œ ํ‹ธ๋ฆฌํ‹ฐ ๋˜๋Š” Insomnia REST ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ Rapid API์— API๋ฅผ ๊ฒŒ์‹œํ•˜์—ฌ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Python์—์„œ API ์ž‘์„ฑ(Flask ๋ฐ RapidAPI ์‚ฌ์šฉ)

API ๊ฒŒ์‹œ

RapidAPI๋Š” 10๊ฐœ ์ด์ƒ์˜ API(๋ฐ ์•ฝ 000๋งŒ ๋ช…์˜ ๊ฐœ๋ฐœ์ž)๊ฐ€ ์žˆ๋Š” ์„ธ๊ณ„ ์ตœ๋Œ€์˜ ๋งˆ์ผ“ํ”Œ๋ ˆ์ด์Šค์ž…๋‹ˆ๋‹ค.

RapidAPI๋Š” ํƒ€์‚ฌ API ์ž‘์—…์„ ์œ„ํ•œ ๋‹จ์ผ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•  ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ž์‹ ์˜ API๋ฅผ ๋น ๋ฅด๊ณ  ์‰ฝ๊ฒŒ ๊ฒŒ์‹œํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

์— ํ•ด, ๋จผ์ € ๋„คํŠธ์›Œํฌ์˜ ์ผ๋ถ€ ์„œ๋ฒ„์— ๊ฒŒ์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ์—๋Š” ๋‹ค์Œ์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ—ค๋กœ ๊พธ. ๊ทธ์™€ ํ•จ๊ป˜ ์ผํ•˜๋Š” ๊ฒƒ์€ ์–ด๋–ค ์–ด๋ ค์›€๋„ ์ผ์œผํ‚ค์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.์—ฌ๊ธฐ์—์„œ ์ž์„ธํžˆ ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.).

Heroku์— API๋ฅผ ๊ฒŒ์‹œํ•˜๋Š” ๋ฐฉ๋ฒ•

1. ํ—ค๋กœ์ฟ ๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„๋Š” Heroku ๋ช…๋ น์ค„ ์ธํ„ฐํŽ˜์ด์Šค(CLI)๋ฅผ ๋“ฑ๋กํ•˜๊ณ  ์„ค์น˜ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์šฐ๋ถ„ํˆฌ 16+์—์„œ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

sudo ์Šค๋ƒ… ์„ค์น˜ heroku --classic

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋กœ๊ทธ์ธํ•ฉ๋‹ˆ๋‹ค.

ํ—ค ๋กœ์ฟ  ๋กœ๊ทธ์ธ

2. ํ•„์š”ํ•œ ํŒŒ์ผ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํด๋”์— ๊ฒŒ์‹œํ•  ํŒŒ์ผ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ํ•„์ˆ˜ Python ๋ชจ๋“ˆ ๋ชฉ๋ก์ด ์žˆ๋Š” requirements.txt;
  • ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์‹คํ–‰ํ•ด์•ผ ํ•˜๋Š” ๋ช…๋ น์„ ์ง€์ •ํ•˜๋Š” Procfile;
  • .gitignore - ์„œ๋ฒ„์— ํ•„์š”ํ•˜์ง€ ์•Š์€ ํŒŒ์ผ์„ ์ œ์™ธํ•ฉ๋‹ˆ๋‹ค.

requirements.txt ํŒŒ์ผ์—๋Š” ๋‹ค์Œ ์ค„์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

  • ํ”Œ๋ผ์Šคํฌ
  • ํ”Œ๋ผ์Šคํฌ ์•ˆ์ •
  • ์ด๊ฐ

์„œ๋ฒ„์—์„œ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•ด์•ผ ํ•˜๋ฏ€๋กœ gunicorn(Python WSGI HTTP Server)์„ ๋ชฉ๋ก์— ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ”„๋กœํ•„ ํŒŒ์ผ์—๋Š” ๋‹ค์Œ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

์›น : gunicorn ์•ฑ : ์•ฑ

.gitignore์˜ ๋‚ด์šฉ:

*.pyc
__pycache__/

์ด์ œ ํŒŒ์ผ์ด ์ƒ์„ฑ๋˜์—ˆ์œผ๋ฏ€๋กœ git repo๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ณ  ์ปค๋ฐ‹ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

git init
git add
git commit -m "First API commit"

3. ์ƒˆ Heroku ์•ฑ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

heroku create

๋งˆ์Šคํ„ฐ ๋ธŒ๋žœ์น˜๋ฅผ ์›๊ฒฉ Heroku ์ €์žฅ์†Œ๋กœ ํ‘ธ์‹œ:

git push heroku master

์ด์ œ ๋‹ค์Œ ๋ช…๋ น์œผ๋กœ API ์„œ๋น„์Šค๋ฅผ ์—ด์–ด ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

heroku ps:scale web=1
heroku open
 

API๋Š” ๋‹ค์Œ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. your-random-heroku-name.herokuapp.com/ai-quotes.

RapidAPI ๋งˆ์ผ“ํ”Œ๋ ˆ์ด์Šค์— Python API๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•

API ์„œ๋น„์Šค๊ฐ€ Heroku์— ๊ฒŒ์‹œ๋˜๋ฉด Rapid API์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ ์ž์„ธํ•œ ๋ฌธ์„œ ์ด ์ฃผ์ œ์—.

1. RapidAPI ๊ณ„์ •์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

Python์—์„œ API ์ž‘์„ฑ(Flask ๋ฐ RapidAPI ์‚ฌ์šฉ)

๋ฌด๋ฃŒ ๊ณ„์ •์„ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. Facebook, Google, GitHub๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Python์—์„œ API ์ž‘์„ฑ(Flask ๋ฐ RapidAPI ์‚ฌ์šฉ)

2. ์ œ์–ดํŒ์— API๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

Python์—์„œ API ์ž‘์„ฑ(Flask ๋ฐ RapidAPI ์‚ฌ์šฉ)

3. ๋‹ค์Œ์œผ๋กœ API์— ๋Œ€ํ•œ ์ผ๋ฐ˜ ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

Python์—์„œ API ์ž‘์„ฑ(Flask ๋ฐ RapidAPI ์‚ฌ์šฉ)

4. "API ์ถ”๊ฐ€"๋ฅผ ํด๋ฆญํ•˜๋ฉด API์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋Š” ์ƒˆ ํŽ˜์ด์ง€๊ฐ€ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

Python์—์„œ API ์ž‘์„ฑ(Flask ๋ฐ RapidAPI ์‚ฌ์šฉ)

5. ์ด์ œ API ์—”๋“œํฌ์ธํŠธ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ž…๋ ฅํ•˜๊ฑฐ๋‚˜ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์Šค์›จ๊ฑฐ ํŒŒ์ผ OpenAPI๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

Python์—์„œ API ์ž‘์„ฑ(Flask ๋ฐ RapidAPI ์‚ฌ์šฉ)

์ด์ œ ์—”๋“œํฌ์ธํŠธ ํŽ˜์ด์ง€์—์„œ API์˜ ์—”๋“œํฌ์ธํŠธ๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ ์—”๋“œํฌ์ธํŠธ๋Š” CRUD(get, post, put, delete)์˜ ๊ฐœ๋…์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

Python์—์„œ API ์ž‘์„ฑ(Flask ๋ฐ RapidAPI ์‚ฌ์šฉ)

๋‹ค์Œ์œผ๋กœ ์ž„์˜ ๊ฒฌ์ (ID๊ฐ€ ๊ธฐ๋ณธ๊ฐ’์ธ ๊ฒฝ์šฐ) ๋˜๋Š” ์ง€์ •๋œ ID์— ๋Œ€ํ•œ ๊ฒฌ์ ์„ ํ‘œ์‹œํ•˜๋Š” GET AI Quote ์—”๋“œํฌ์ธํŠธ๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์—”๋“œํฌ์ธํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋ ค๋ฉด โ€œ์—”๋“œํฌ์ธํŠธ ์ƒ์„ฑโ€ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Python์—์„œ API ์ž‘์„ฑ(Flask ๋ฐ RapidAPI ์‚ฌ์šฉ)

๋‹ค๋ฅธ ๋ชจ๋“  API ์—”๋“œํฌ์ธํŠธ์— ๋Œ€ํ•ด ์ด ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ฐ˜๋ณตํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒŒ ๋‹ค์•ผ! ์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค. API๋ฅผ ๊ฒŒ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค!

๋ชจ๋“  ๊ฒƒ์ด ์ˆœ์กฐ๋กญ๊ฒŒ ์ง„ํ–‰๋˜๋ฉด API ํŽ˜์ด์ง€๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

Python์—์„œ API ์ž‘์„ฑ(Flask ๋ฐ RapidAPI ์‚ฌ์šฉ)

๊ฒฐ๋ก 

์ด ๊ธฐ์‚ฌ์—์„œ๋Š” API๋ฅผ Heroku ํด๋ผ์šฐ๋“œ์— ๊ฒŒ์‹œํ•˜๊ณ  ์ด๋ฅผ RapidAPI ๋””๋ ‰ํ† ๋ฆฌ์— ์ถ”๊ฐ€ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค์™€ ํ•จ๊ป˜ Python์—์„œ ์ž์ฒด RESTful API ์„œ๋น„์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๋ฅผ ์‚ดํŽด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ํ…Œ์ŠคํŠธ ๋ฒ„์ „์—์„œ๋Š” API ๊ฐœ๋ฐœ์˜ ๊ธฐ๋ณธ ์›์น™๋งŒ ํ‘œ์‹œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ณด์•ˆ, ๋‚ด๊ฒฐํ•จ์„ฑ ๋ฐ ํ™•์žฅ์„ฑ๊ณผ ๊ฐ™์€ ๋‰˜์•™์Šค๋Š” ๊ณ ๋ ค๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

์‹ค์ œ API๋ฅผ ๊ฐœ๋ฐœํ•  ๋•Œ ์ด ๋ชจ๋“  ๊ฒƒ์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€