상세 컨텐츠

본문 제목

[2.5차/15기 김제성] API & REST API

본문

https://www.youtube.com/watch?v=WXsD0ZgxjRw&t=9528s 영상 리뷰를 토대로 정리하였습니다

 


Interface

: 기능을 우리가 컨트롤할 수 있게 해주는, interact with software (don’t need to understand about specific implementation)

ex)

  • play button
  • making upper case character function ~ also API

 


API : application programming interface

다른 소프트웨어 시스템과 통신하기 위해 따라야하는 규칙을 정의 (=메뉴판)

지정된 형식으로 요청, 명령을 받을 수 있는 수단

https://www.youtube.com/watch?v=ckSdPNKM2pY

우리가 직접 특정 컨텐츠에 대한 내용을 요구하는 코드를 짤 필요 없이 웹페이지 아이템들을 클릭함으로써 api를 요청할 수 있다.

 

네이버 클라우드 서비스들도 api 요청을 통해 활용할 수 있다

 


REST API (representational state transfer)

: URI와 HTTP method를 활용해서 자원과 행위를 표현

(URL로 어떤 자원에 접근할 것인지, method로 어떤 행위를 할 것인지 표현하여 API 설계)

 

: REST의 원칙을 잘 지키고 파악하기 쉽게 만들었다 = restful

 

: 데이터는 JSON 혹은 XML을 통해 주고 받는

활용도 good 다른 사람들도 보고 파악이 쉽게 끔

ex)
--- GET
 /movies/inception/actors    (O)
--- /getTopRatedMovies                   (X) 이렇게 쓰지 않는다

*URL 내에서는 동사를 사용하지 않고 명사 형태로만 (ex. /movies, /movies/id=25)

*resource = reference of object

웹 내 하나하나 데이터(HTML, 이미지, 음성데이터 ,,) = Resource

그 resource를 uri로 표현 = element

element의 집합 = collection

 

 

*CRUD - HTTP verbs 로 resource handle

  • client-server architecture
  • statelessness : 각 요청이 별개로 separate
  • cacheability : client-server 간 상호 작용을 간소
  • layered system -json 형태
  • code on demand (optional)
  • uniform interface
    • resource identification in requests - URI
    • resource manipulation through representation
    • self-descriptive messages
    • hypermedia as the engine of application state

REST API를 만들기 위한 가이드라인

Use JSON as the Format for Sending and Receiving Data XML은 더이상 많이 사용X
Use Nouns Instead of Verbs in Endpoints HTTP verbs
Name Collections with Plural Nouns instead of https://mysite.com/post/123 , use https://mysite.com/posts/123
Use Status Codes in Error Handling  
Use Nesting on Endpoints to Show Relationships 종점 URL 중첩해서 명확하게 쓰기 ex)https://mysite.com/posts/postId/comments
Use Filtering, Sorting, and Pagination to Retrieve the Data Requested 방대한 DB에서 값 잘 찾을 수 있도록
Use SSL for Security https://
Be Clear with Versioning ~/v1 ~/v2
Provide Accurate API Documentation  

https://www.freecodecamp.org/news/rest-api-best-practices-rest-endpoint-design-examples/

 


Spotify

💡

curl(client url) 명령어는 프로토콜들을 이용해 URL 로 데이터를 전송하여 서버에 데이터를 보내거나 가져올때 사용하기 위한 명령줄 도구 및 라이브러리이다.

쉽게말해 예를들어 자바스크립트 환경에서 REST API(http)를 테스트하고싶다면 보통 ajax, fetch 를 이용해 요청을 보내는 것과 같이, SHELL(커맨드라인 환경)에서 REST API(http) 테스트 하고 싶으면 curl 명령어를 이용하면 된다 라고 이해하면 된다.

https://inpa.tistory.com/entry/LINUX-📚-CURL-명령어-사용법-다양한-예제로-정리

 

 


Twilio

  • create message
curl -X POST "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID/Messages.json" \
--data-urlencode "From=+15017122661" \
--data-urlencode "Body=Hi there" \
--data-urlencode "To=+15558675310" \
-u $TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN

 

twilio를 통해 보낸 문자 내용의 json 형태

{
  "account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "api_version": "2010-04-01",
  "body": "Hi there",
  "date_created": "Thu, 30 Jul 2015 20:12:31 +0000",
  "date_sent": "Thu, 30 Jul 2015 20:12:33 +0000",
  "date_updated": "Thu, 30 Jul 2015 20:12:33 +0000",
  "direction": "outbound-api",
  "error_code": null,
  "error_message": null,
  "from": "+15017122661",
  "messaging_service_sid": "MGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "num_media": "0",
  "num_segments": "1",
  "price": null,
  "price_unit": null,
  "sid": "SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "status": "sent",
  "subresource_uris": {
    "media": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Messages/SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Media.json"
  },
  "to": "+15558675310",
  "uri": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Messages/SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.json"
}
  • index.html로 페이지 만들기
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link
      rel="stylesheet"
      href="https://fonts.googleapis.com/css?family=Open+Sans"
    />
    <style>
      body {
        font-family: "Open Sans", sans-serif;
        margin: 5%;
      }
    </style>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.13"></script>
    <script src="https://unpkg.com/vue-silentbox@2.3.1/dist/vue-silentbox.min.js"></script>
    <title>Pick.le: Pick your pics 🥒</title>
  </head>
  <body>
    <div id="app">
      <h1>Pick.le: Pick your pics 🥒</h1>
      <h2>{{ callToAction }}</h2>
      <silent-box :gallery="gallery"></silent-box>
    </div>

    <script>
      Vue.use(VueSilentbox.default);
      const app = new Vue({
        el: "#app",
        data() {
          return {
            callToAction: "Submit your photos of applepie!",
            gallery: [],
          };
        },
        methods: {
          async loadImages() {
            // TODO: Use the Messaging API to use submitted photos
            // const response = await fetch("/api/")
            // TODO: Create a web-based API that matches this expected response
            this.gallery = [
              {
                src: "data:image/jpeg;base64,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",
                description: "Look at this kitteh",
                alt: "A kitteh",
                thumbnailWidth: "200px",
              },
              {
                src: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHCBUVFBgVFBUZGBgZGBoaGBoaGxoaGh0aGhsaGhsbGRsbIC0kGx0pIBoYJTcmKS4wNDQ0GyM5PzkyPi0yNDABCwsLEA8QHhISHjQrJCkyMjg7NTY8MjU1MjIyOzIyMjgwNTI2MjI7MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIALcBEwMBIgACEQEDEQH/xAAcAAABBQEBAQAAAAAAAAAAAAAEAAEDBQYCBwj/xAA/EAACAQIEAwYDBQYGAgMBAAABAhEAAwQSITEFQVEGImFxgZETMqFSscHR8AcUQpLh8RYjVHKCkxViNESDM//EABoBAAIDAQEAAAAAAAAAAAAAAAIDAAEEBQb/xAAtEQACAgEEAQMDBAEFAAAAAAAAAQIRAwQSITETIkFRFGFxMoGhsZEFUsHR8f/aAAwDAQACEQMRAD8A9mpUqVQgqVKlUIKlSpVCCpUqaahB6VNNPUIKlSpVCCpUqVQgqVKlUIKlSpVCCpUqVQg1MTTM0UDiMQdhSsmRRXIcIOTC2vAVEcWKByk7mmMCs0tQ30PWFBT44CojxIVWYrEAbVU3cQxOlZMmrknwasWkjLs1P/khUbcVWswtu41TDhrnmaX9bNjHpMce2aJeKrUw4itZ+zwxhzNFrgyOdEtXl+BUsGL5LlMep50Ql4GqA2SK6W6y7UyGukn6kJlp4v8ASy6u3oFVd6+x20FJbpOppzdB0op6lz64JDHt9iCW+0aVSZDTUrfMfwaClSpV2jlipUqVQg1KlUN+4FBJMee1U2krZaVgPFeKfCEIue4VJVNpjqY08OtYPE9sr7Eq5No/ZCwYmBqfvBqfEWiLxvm+ysWJITKQRAEMWBBEDppVdxVsLcaXtB2kxBbMJMmApEDwrhZ9dvltTa/B2tNpIx7jf3LnhnEsUGGZmKmSMxBOgnUGP171o+HdobbtkbusN+n6968vwt+1bYlLV1NdD3mEfzA1qwENr4+fIrqAzGJGpCkEiJk9OdBjz5cbtO19w9Rpsb7VX8G/RwRIIPlXdY/B4hsoNq7niJ6z4wNtN6ucJxVjo6kH6HyNdDF/qOOT2y4ZysmlceuS4pVEl0Hn71LW9ST6M7VD0qakTRFCpVwbgHMe9N8VftD3FDuXyXTJK5ZopFx1oe680M8iSLjGyHFX+QoJrwG9T3qp8SSTArl5sru2dDDjTVBLYyTApirtXeCw0VYAAUEU5IKU4xdRRWrw+d6ItcPUcqMLaVA2LApiwxj2LeScuhxhQOVMdKb9+XrUJxIbahlsj0UlJ9k+eufjVCX8KdRQbmw9qXY73KSsOddlKjy1KplqgoRFK3YFDZDTi4wot6T5QG1+zDMgpUL8c9KVH5Yg7JF5SpUq65hGpVBfxKJGZgsmBJAk9BWdfjDXLhykhFMcwTB1bl7UnLmjjVsZjxSn0XOIxLBoXTrOunh0qu4hiA/deQOUfWfSq+/xZVZteokmQSBP9JNS2sZbdQc6yVmJAMDcx0rk5NS8tpPj4N0NPtptFTi+HC0Q9ss6sWDhiCRM5cm0dPQVmsZ2buXbpuKxVZAywQ3MkSOWsT41pPiu4bK5YEHTKIPqR9am4LdKnvqZ85GgJ10086x45rf6VVm/dKMHzZX8I4PeM5w9tc6tOcyVCnuiCYBMT5Gru5Zt5clwZgNRnUMOcct9TU6cRXMczqOgg/U865xWKkQrqfDukxrrA5elanCLjwzLLJOT5BMNhbKFnRSGO4RiM3SFJEHaiG4nbQ97Mp5llI9+vvVBjOO3EQZbaPBIJObcaEQDoZFWPA+0q3e7eCK5JAUkgR3QokjViW2nYGkxxRbpP/Jc4yrc03+5e4W7mt5lYMNSCI2G43O229IYolTkBkgwQToesbUkxVpE+ItsLK6aAMZ5aeQ3qqu8YDEg2Qy8pgH2pmSXjqpVx+RMIOTfpDbOLvAQzFvKJ+810eKld1b1FB2GVtVwzR1ED6kgVM+EUCTaeN4zA/c1JTzvlS/sbtx3yv6/7OX48s/IPaaEu9pkkg2wPMFZ8jRFzDI8f5DeZC/nJqO5g1jKbQj1FFuzLt3+wyKwf7f5BG7V2V+ZSpnQAzprrMeFSJ20wogSwJ5fj3o0qvxXBbbmcjDwGooJODWw05XMcgh6czNFHPXaDeDHLo1I7V4MglrgECTMTHkDVTd7b4AMY+KR1CSPSTNUt/g6HRbR/wBxZvf5d9qAvdnW3ygR1B/KmLUQl+pArSxXUj0Lh3abCXoCXVDHZWlWnprpVqrmdjFeNWuBupzC4gIMgAa9RzFEhsVbPcvuCfmgkeO363piy474YD0kvY9stgEa1xiMGrCvJuG9tsZa0ci6o07w73PYiJ9ZrSYT9oyN89plOmzKd/OAPet0c+Nrkxy02WL4LZuAsbk5zl+zVmnDgooPhvazD3SBJRvsuI9j8v1q9N1SN6ix4pJuIM55YupKgL4Qp8gobF4xVMTROGvKaRHHcqLdpWP8KkLVGKRXcCnrToV5GAGBvUZCmjrtgEVneNZrSl11jcUvJhcVYzHJSdFrkFKsV/i1PGmrJviaPDI9IZwKhbEgSfag7t4zVdj8elv5jEz9I0rfLUpKzJHC3wR9osYhy5YZlnTlrHM+AIqhw7rpnYAMGgA5TmnkfPMY8qpeIXoxUKxyuykE7SIPpzHoKsMZhmKt8Je8uhBI2naT1j6+NcfUZXOVs6+HCoRUbDL/AA8hGKuO9JYDQZd4zRP62qssYu0jFX7oRe6AASTHVhC8vrNX/B3Fy0sKVJXVW3B51n+N8OXM7JM6lgY31OmvOKXt280GpW3GTL/A8QV+7aAkgmG0mBqBE0yYy4pAZGbrkGUb7ESSdPGsthFS3hmvPZdyHC6XCsArox7vyzp5kUIe1aoYt2GMiGD3HfXoqiB08a0KDatfwJaVukafHYvFKGZMCtwfwFbjEjoWTKC3/E+vOrTBWvi2bZvJ8NyczKO7l30E6xqN+lZnB4rGXLyhUKqmZcgGW2oSVO/dJ10JnlWxVzAnfnzB05R409SvihEotAOMs2ktu6kRIzSAwJMAZxzHjPrQ2FsYS4qgqisdSUme7rM/wbHTXSi8Rw1bifDuO7KDMBsp3nvEDvxyn79afh/CbFohkBLrMEsTy5iY+lC093CVEUvT27LBxmhQsgDc7e9NlCHUAeQk+h/pUyYodNfX8qfPmPPynKKa9r5FXJHK3s2gU+NclAw0fIxOkQNuvWnfCoQASfRm6z11G1S5ANo84FX+Sr+CCznBhnDHoAfz19qe2xcFlYFeoBYT4daGv4a6H/y3yLBAyW00n5ZLGSN9AK5wuCvBpuYhnEHuhESSdpKxAnXQiqXxRftdoJxLdyM2U9YCz5ZqGXCPt8QzpmBVTBjaRFQYnh1xwmS66OBDOBoY5lWM+x51IuAvrbI+OWuyCGYFVI6Ea0D5dtBp0uGTYjKFy9yJnUgGfCoGRAYKsYH8Gb9TU+IwRI0uMGG5nfzywfr0qTD4LKhXMTPPM3TWDM7+NTbbqilKl2VWM/d5HxF1MaOFnXaZ6wfana1YaLaEBuiwfSNR+VGjg6l85uXJBnLm7pjQDrHrO9Hm2I009KHwX2g3mrpsz78HRjoQRJ+YD9TUF/szZb+FZ/8AWAf151pyqssMqtzggEeeuxrm5hEKnKAjRowH4HceFTwJdEWokY/E8AyDuNtpqNf1t7UfwN7qdxmzCNO9r61ZmzcCywVzJnJoQORhjrzkA+9R3cKRBA15dazyxTg90R/mU47ZFL2g4diWPxLLl1GpT+MeX2x5a+BqjTtHiVGVZkaagyCOo61vLF8ncZWHsfPpU2Iw9pwWdJYAax3jtz5gTzpkZSfN8iW9vDVoxmB7W4rY2yx9qs17ZXU1uWiBV/ZwNrNCxOmlQcU4YjIRFM82RLsrbjbqjrA9r7NwfN6GheN8WW4hCmaxtvhvw7hB2mtPhMMpFVLWSl6Q1poxe4x74BidqVb/APcl6Uqy7X8jvIXFxwR05nyqjx6LcHd0I11qzKSZb0FQYnCgjTQjan59049GbHUWZfH8P+IsOMpUyrjQiOv2q54tfuZEuW2VCCFuF8uQ54GYTue7yjc+NajC22MhogdRJnwqr47w1biMmUw4g5YkNybp1rPGEopN8o0xyJyoazjGs23ujvqrKAAPmEAGDy73Py3o+0+HxCC5LLm0iO9OuhEHoddtN6p+H417l4YcBrcMlzvQyuikLcQ6d3aYBiTNaSxYt4cQNAdtJAPnyHPpua24oWl00Z80ql9zuzhbS2zbCrlIKkEann3hudTNCWOEWVUlLKBgQ6kKJDqDlYHedTr4miLuJIcBUkayxIA20jmdacO/KB5CfvpznFcCVGQG2JZjAIEx78/x3rpZGm0frSKlGEO9dtYyiSYpCTfLGNrpEKgzqa703g/dQrcTw6yDftyNxnUn2mTQ47SYTnc065H/ACq+PklS+C2tvBkKPeu3vA6FZrOJ2wwnLOdY+Ue/zbUXh+NWHkh4A+aRtPXWr3VxZNj7oscwH2pn0HhTFujMPrQacXw7bXF3jmNaITFWj8txCZiJ18qFflE5+Ai1fIO+au2xGm/l/Wh9OUb8jXIQ1duqKpHaX3AEupJ8CNuupimXEsTqFP8AyPtqK4NuuAkcqBqXyF6Sc37kZggPgDJ/rUdviSEkA6qYI1BB6QdfcUTZTSSPasD2w7TWMwFss11JUMhIUEcmOzga6a89pq6l1HsuMVJm+TGidvrTvja854V25Bhblk7AZlI9yDt71oD2nsBcxk9AILe06VJZMkfS+AvBfKNVbvqdDuRMjw0qBrwJgMQeUbH0NZAcf+IZsrlIM9/5vPKp/E1Z4DGi4oFxz8STtCgDkANyI50P1Cb2vsj07irLm/i2tgFlzpzZRBHmOnjRFi8txZRgRVI165aIM50J0/p6U923Ci7hyV1JZRty/h6fnRxyO/8AgBwRb3UGpiTz6+1QSYlDI9fbwPgYNc8MxrXAwcAMomRMEc/15V0mIDMUbuOpjcd4HbL1PhUk01x7lK0zOY3idy3c70ovX9eZ9QKsuH8cV2NtmDHSGHQxE+pAqbHYBbkI8ExMxznSAfSaqDwC5aurcOQbaCQsR82g+/8AsiHpTTNbljnFezD8VZDNRlq3lFB8U/y7gAO6hj6kj8JrlsbpQqKjdlJOSVFt8SlVH+/GlVb4l+KRpHf2H30Jh+II7lBuNfMdRUuJ0U1lcfbykMDBnSND6RVZdS4TUReLEpJmrx11ktsyCSNvz8Y3imtKXQNGpUH6VW8B4gXBS4c3MTvHMHrWhsBVEe1aoJZVafHwJneN01yZKxxG6xYhMj2i4aNVYyV1WQSOe+4GvWCxxe9feFYJJhg2uWCYIDGPUCd6url8273ftkI8gEd4E6sQ4/h5kHz25jXcPhMQ4KyCCGMaBgOU+NJ9UVV/sNtPmv3LLDWUVVUFiQAO8ZJgbzR9pSdthufyoVk7/h4dKA7V8YGHwrkMFdlKW9iS5ECBzjc+VaYxViHb4RS9rO1zWX+HaykiDmBDL6wd99Kw2L4u91i9y4zMRBMwI6QIAHhWcvWHbdyddj+t65XDMNhTnij7yGwtexdHHBfl1P0qDEcQLRm+lAkMOUU+QmqWKK5Dc2FriU6n2qO/xIrooIPUn8KiUVzcQVajG+UU5Ohn4lcP8fsAPwqL96ufbb+Y8qT26hYRWiKj7IC37mkwXa68iZHh42ZiQ3/I/wAX0PjV9wrt+6Wgl62bjrIDhguYcswjQjaRWBtDXWihSpQim6XZffZu8L+0F84z2FySMwDksBOpEiDpy+tXvEu29hAPgg3WOuzIq/7iwknwA9q8uQUQlIlx0WsabNDxXtjirqm2MqIRByAyQf8A2Jn2iswbIbSrfBWc29T3eDltV0P0NJ88YunwaI4qXBW2rQUUwfWrJ7MDKwiKZMKp5UHlXbHKNAlu5Ra4p9s7abd41KMCo61K2FBAVB3tAOpPSlucWxiaXZteDYxbtpSxDGAGXnI0nTrvNGWbJRs1uGUnVTzB8ar+FcCFlCzMM+UZmJhVn+EesCaIsYnYTIHMaEfn/Sq37XyYpxjJvaOto22zpDKQVAMxB3VhRVzDC/lPyssbbyDII6UjfTKxbRQCzTsDG/51mcNxa7iL6W7WW0DJLDVsqiSCTvtyinwlFqu7FbJO31XubTCoxYhwGM6EgaECJMddOlT31zHUyY7p/CobfxFB7wJgdZgCq3E4p1bMWKqATGkE6afrrV5WoqmJjByfAPjsQlwqjowZdmMjuk6jx669DQvE8KttwFJKsoYTuNxE86M4wsXVaBle2B/yBkDw0mpfhi4ATuhy+n6BoNjlH7mqElHa10UfwzT1ffugpUnwsb5kFYhtD5Gs9jhIrTXk3FUeMwpkxrSddjdqXwL0s0uDN28S9t8yaa1q+FcaW4ArnXx09/zFUI4XcuNCDzJ0Ao5uysgf5hB593T01BFTDOS5Roz+OXEnyaggkQDp4H8qYWgNQuvOaocNwXEJ8j7csx/Kj8LevHu3FiBuY9pGlao6i2lJMwPGl+mSZPjMSLdtnP8ACpPsJryPiNy5fc3LrFiZgHZR9lRsBW97QI57uoQgSQJnwJ5fjWZu4I8tfKhep9VGnFiilZm7mF6CoWtkVoEwblsoBnp5VDewZBgiTz/Qpsc3sHKBQu2lRhela/A8BR+8y/U/nUOM4G9ts9sKV00nX67imxzxfQtwMu1tulRsh3ir+/ZuAyyQDERr5Caks8IuP8ien96LzJAuCMxqTAEmprfB7twjQAdSa9B7Ldk8rm7eUaaBDBBPU9fKthi8KhXVQY20GlVPU7f0itqumeKXuDOhAHeJ+z16UhhmBh1KnoRFeg3LKWywVYza+lZrjVwUqGrc3Q3xpcgiAAbVb2OyuKdgotZQdczwAAeZ5+m9VPD8MbhhZ8Ov9K9rwIbIpf5sonzjX61fTByZHFcGTwXYs2171zMecLA+poxeBFdq1DNToPCaVPBGb5FLUSRlf/Die8gPI/qKyXEeHXLFzIQSrHuGN9dv91erOgqtvIpZcyhsplZ5MNiPpVeGMeExkNRJmJHAb5QOF1I+WSGg9REekzVzgezSLla4zMREjTKT6axvvWgxDwu+tBm43MEemv8ATehlGKD8kpIpO3OPFtEEtLM3c5HKPmJ5RI9/CsVh+0F1HDHVdZSYB0jcgn+1aLi11MZiLVmTlRmDOAf+QBP+0a9aH472aw1u2xtO2cMIDMDmB0gCJ0EmddqfGMKuSGQ9KUQO/wBsc+ZfhZFIjRy2hOsyBWt4BwhVRcQx77KrIeSqyzrPM6zWCbg+S21xiB3VKg6EywGmsGAZ961mJ40FwqW0YM4REYqy5VjKN51ETvTFGCe5ImRSa2r5NpburcXMsTzEz66cqHuAd4MpJjXQEQP71hOF45lu5Ucx4khT4+HrW24djQ4mcwHPQksdxHQa6+FC5KffDM88Tx/gWItqVg7chERHTpFDcFs9+5bBIykGDzknUdRWgFlXQmNfmB/XrUuEtIO8FGY6Fo1jkKLHiksi54YmWdbWq5AP3BqVX0Uq2+GIjzSKe8k6+9BXrWtWRGViD/cdaHvJFY8uJSTTG4510CJby/L1k0Qj6a1yqmaZ1nUVj2KPA9vcEi9CkDfrUJg0OSRPSmW4BzonTqylCuiZ7QYQRIoN8EmUqLYJOzaBh5nnRXxxUb3Ad9DFDJqPNFqzNYi3ctkKwDLy8tNDG3IVacLxgyhGAO8D85ru7aVlgjb5TGmvL8arsTZClMpgkD3Jilwk093sPdSVMt7+LtruBtppUHxLL/NAnQTHPlVbjL5IVMqjKT8oMkzGsnU+PjUGhMuIAiF16TOv62o5ZXu46JDHaLdsBYENpvMHbxrp2QRkQKeUCJ/UVmMQHd8ttm7x2zGBrAnx/Ok/ErqXMjEtk0gRqFBJPt7TRbm1wgvC/dmxw2KBX7PLqfepnJK6a/Ss5huK23BbQhTl9TtuOcGp8Ni2cEIGI1JjWBz9KHek9rFvG1yRcTwpYyuvXbfpp+PSspiuEX7j5Vtu09Bp77Vsr6vbK5x8ygjrG+o5HWrHAMQuYESxkQflERJHXfyqsUdsvgkp+njkB7K9m/hANcEN0Bk78zt7Vr2WKFwjaVPnHWtcWqMc7cjp99JpIRFcA+NJjUunYNexHfaq57yhoJ1o9jzrM8YxGXnzkn8KzZpUrNOKN8Fq4zNvGWDHNoOoHpUPFrrJZuOujQSA2oBJmNOcQKH4dihc7w3GnPp/b3oftHfzKqTCz3gOZjT0q1JbbDUPWkYrAXHUs2ZpJJYzrJO/ufrRyXDsx06wOUxr786ivIV+XeII6jpFRLcB6qf4YH0PWr33yb0rHxOFBG4id+Y8SOe9CY620hQdh9PvjQfra3wUG4O7mDAgmG0jdiByH513izaDtkHdJGVuewJ+siiU2kXfNAfB8C0O6EO2Uyp5roSR46D2rX9msO4zFoAgdeRO81S8KwAa4Whsq/JyEEbkeOtazCjQIIBY7wJjnrVwe6Vv2MupnxSLi3omnl5bT99TWLiuquNJ3B60FikK2mVIUxC6696JJ/8AbU/SicGmXKnRZJ8TWuE2ppHLklV/csKVdRSrcZipxbl4MZYkeM/lUPxNIOviNxVrjsLmU5YB++qIiGIYFW2/EfrxrFnUovk14XGS4JWWNvepFWaDS73o5gbciOvnRdt10gwT/CdD7GszakOaaI3tGKrbltpmKumNQlKXLEmHCdFQoMzRLCRpUz4XmK4C8iNqHa0qYTknyisdXJ02HkK6xPC2ADMQZOi6zqAZ8qs1T26V3e7xk7xHtVxxra9xTm74MyyEMNYMiG6a7/UUFxfHOwY9IUQIGUaCOo996vsT3WDQNDOoke3PyrL8RxMK1sSQRrtA1B95ApW1Lg04+XdA2HuOBmI02BYGCd9CB0I0qC9igRqYbXmfL8xR9jigyKpAARcq9CZYkkdSW+lC8GtfEvXLjSCtu5cXLEh1hhlB9fSnQim6QxzaTbQH8N7LhWGViAWQ7gE90MOR8JkeFX1sgAFGM/xKRp4wZ1G3KhLuIe+Q9wgsukhFVmM/M2XcjbyAovCwuh1peam+CNtxV9hbYguFDsdO6s6xzgH1o7D4j4fdO/oZnxG9QYO2DJ/GiCiQDGwMzz3/AAoEm+bESrosF4hFWiPlWXAkgEdNfvP5istY7x/W1Wt6+8qDyAUa8gIo8UqTbE5IW0kGjEdKk+P1qrxGLKKCQYJieU/oGlgLpuMdNFEkdQCJHhv9Km/1bfcpx4sKxWNAG9UN+w107QPOav3woOpAmpbeEWNNPSqljc3TYUZqK4KHCWGtg6ldvH9aCuxhpJzayd+dWd5BE/rX+9QYLXeOnjr/AGo4wSqJN77M1xrh5tj4i6rMN4Tsa5wXBC4zvCqRIbUaxIAgd41d9ov/AORQfxEffP4UJwpXKpJYwIjU5RJmPpQ1FS2ocpy22CWuEFQxLmIiDzkgmfvomzwckC451JAUAAAAdRy09tKtwrNAI0ogqSRrtoOlEsVgyzyBMEuWRAkneOXTSrmxbAAZhtpPQEia5s4cCAPM0RctqyMCYWDLdBzPtWnHDaqMuSe5kT5WKudNcx8oGWfT7zVhh3kz7VmLTi7dRFLKIdhmIl8pXVgDMa6DzrUWLeUQPz++i06cpuXt/bF5o0kn3/QVmpVzSroWZaCqr+I4VXEncDlVhQmItEgwSPb8aLMrjTVgY3Ursxq41WLQDmQmdJI5TI69OdQtxTNoQrf+rxqeoOpX1FA9oCEvAm3e0PzgZQTzERJB86z2PxqNMuRyGZGkeIKNJ9SPOvPShNyro9BjhBxtm34dj1L5FvQxOttwXHUhGkHruTU9nG3szK9pBB1cXRkHmGAZZ00g15XZ4iqN3r7XADmgoq6gTuWLcunjNX+GwZa6jfvWHYuFcsLjrdyGIAJOrFTpMbVsUJRQieON3Z6Zds5TEgyJGv4VDlg6iqTF8GgK6lWCg6ktmVRzDJB1BJieZ6VPw6bZIRHYAqrCS6ktzUu4KgaSY59Jq225VVGavTd2WbiRQrW260XiCVUsUaNoEEz/AF9fSo867Bu9ElTGYDqRNSUfkuMuCpxuHYgxVBjcIBup16An7q1V/EBT8tw+SE/d+FdvhjEwCKV44vofDK4nntzDActP112o/s+xtOzrGZrbKJE6xm0/ljzOtav/AMYHE5AwPkRUi8NAiFgRGmw/RoY45RdpjZZ4yVNFBYwICnKOem+ld2eHOavmwzK2wgAcx6zRdvBnWBqIo1ivgTLN7lHh+GsN6KGCaI8/rV2LJCljsP1typKpOoFTwRQvztlTh+HlOU+NEnCEx+vSj0uKdAw9xXYXpBFFHDFdAyyt9lLfwbNK8jvXWAwhttnHQiPMRVxlHPSh2vW5gOk/7hv+dD4kpbr5J5LW0iW2YrliwEa0YtuRO87EainFvr921WsTRW9FLfsu2+3Sp8PhQo050di71q389xFnXvMBI9aiONtLvcQebDmJqvEk+WF5G1wAYnAFtx50+GUWxAn0rq9x3DLM30UbmWAAG0ydI5T4+NA4zjli2qOsvmY5o0IXwV4kkn2HlTI4ox9RW6T4osM3OKl+J0XN1iPr/aqDi/aG0llHR2Q3RCOyrAIMEspOoHTn1oLBcSGJxK/BxGS5lIW1lYIxXMSzDNznbw0OlFK10Eo2rZpWuOozNoAR3RKz4AnUnyAFA4viDFtSFVe6FBlSdCxbrBIGvjVIlrGy64q4rHP3cmoykgsFbcIJIAOu/ITWo7P8Kk/FYDLp8Nd4C6Dw61lalKbhFjajCG+RaYLgwVkcHUK0jrnKHfwy1aiwaYMetOGNdaEIwVJHMnKUnbZ18I0qXxKVHwL5J64YV3Sp0otgAV/yms5x34bKQ1snTcKuYeR3Fa0rXLWx0pMsdjoZdp4PxRL1tv8AJD5RqJUCNp+WDrAB11Gh0rO8SxOMckkPz0AYLrvCjSvpf4I6D2pvgjoPaqWNL2Qbzt+7PmXD8Vx6W/hKb3w4K5IfLlLZiunIkT7jY1Z8P7V8QtaZHy7EAONBtX0MLI6D2p/gDoPYUbjF9oFZWumeFj9oGIAUPauDK2bSdYkgEPPM777REaz4n9odpkj93uK4hpIRgzjm+aSV30Eb17b+7D7I9hTHCL9lfYUHhh8F+dnhdv8AaApUBi6sXNxmFtNWOhWA2q7tO80Zh/2moqZWRm1giNGTLuCTo0zpEGvZjg1+yvsK5/cU+wv8oqnp4P2C+odVweVWv2n2QzTmKwcoClI2AUQTJ1OpAGnLQVO/7RcJ3XD6lYZSjsQeWug89+Veltwy0d7aHzRfyqF+CWDvYtHztofwoHp4P5Is/wBkeZ2v2hYGFkXtMw7wzfZggmSAcuwPpWr4d2jwjElcdYhhqr3FUzpAAYzG/j4Ve/4fw3+ns/8AWn5U57NYQ74az/1p+VV9NG7V/wCSpZrVMouO9r8KlllGJsO7LChLinfmSD3YGok6xWN4b24RmW2biqDIOYwpEGAzsQANBrpvA5T6U/ZTBc8LY/60/Ko7fZXA8sJYH/5p+VXLTxk7YWPMoxaSMXg+2OFt2mYXbOYuRlEyDMA5Z7ywR3tOdEYXtml4ZQ6Q2vdcIRozZdHJBIQ6+IEa1rG7J4EjXCWD/wDkn5Vx/g7A/wCjsf8AWn5UP00UqTaC867aMXjuNXcyrbZ1IzKSHzjU6O8AkAZuokeWk13jKXHUMthgGVXVigbUks3ehojWOgMjetW3Yrh/+ks/yKPurn/BHD/9JZ/lFRaVVV/wW9Su9pj8Tx60gIVyrq4R/wB2ZVELlCyDoTpHkImms9olKycV3bmZBNxM0g6Nlk5Zg6+MEgmth/gbhw/+na/lrodiOH/6Oz/IKn00a7ZX1H2RgGv4d3Q3CrlwIdSGcqIG8yOQ6Cq3i2K4abrK4DKIWczK87Gcp5FZ1ncjWvUf8EcO/wBJZ/lFcnsNw+f/AIdr+UUUNPGPuy5alv2PNcFj8DZcpaNtrQDGGdV+IGLAK5IBeJO40AGm0i8V7S2s727aoVfKA1uBChQNCGXv90a/3r1NuwvDz/8ATtfy/lSTsRgFMjCW5/20TwRbttsFahr2R53Zx5ur/l4SGlYDFWnfMRLZRm0md4qxwmBxnxB8PDARpncIOYnvj6ETtXomG4JhrfyWEWOiirBLSDZQPSl/Sq//AEY9W0qRl8P2aDoi4hgcogqjMJ1BgsdY0G3vWktWwqhVACgAAAQABoABRYC9BXQUdKZDCo8IzTzyk/UCV0FNFU9M2C94N8M0qJmlV7UVuZ1SpUqeANTE0qVLZaGmnpUqhB6QpUqIoempUqtkFSpUqEsVNSpVRBqcUqVQgiK5yClSqMg4WllpqVSkSxmtzSNulSqi7Y3w6b4XjSpVKJbG+EetI2zMzSpVRLHFszvTG2fClSqyWIqaYKZpUqEuzorXYNKlUIKlSpURQqVKlUIf/9k=",
                description: "Another Kitteh",
                alt: "Cutie",
                thumbnailWidth: "200px",
              },
            ];
          },
        },
        mounted() {
          this.loadImages();
        },
      });
    </script>
  </body>
</html>

 

  • twilio로 번호 만들어서 문자 수신 받기

/incoming-message

// This is your new function. To start, set the name and path on the left.

exports.handler = function(context, event, callback) {
  // Here's an example of setting up some TWiML to respond to with this function
  console.log(`Incoming message: ${event.Body}`);
	let twiml = new Twilio.twiml.MessagingResponse();
  twiml.message('Thanks for your submission! :)');
    
  console.log(`TwiML was ${twiml}`);

  // This callback is what is returned in response to this function being invoked.
  // It's really important! E.g. you might respond with TWiML here for a voice or SMS response.
  // Or you might return JSON data to a studio flow. Don't forget it!
  return callback(null, twiml);
};

 

 

twilio로 만든 전화번호로 문자를 받으면 어떻게 답장할지를 incoming message 함수를 통해 설정

  • html 파일을 업로드해서 deploy하고 public으로 바꿔주면 더이상 local이 아니라 인터넷에 내 웹사이트를 기재할 수 있게 된다.

serverless

twilio function을 통해 html 페이지를 실제 인터넷 상에 올림

web hooks ~ reverse API (api calls you)

  • SMS로 받은 사진을 index.html로 연결시켜 사진을 바꿔보기

/api/pics

exports.handler = async function (context, event, callback) {
  const client = context.getTwilioClient();
  const gallery = [];
  
  /* This is the format we need to match. Here for reference
    [
      {
        src: "https://placekitten.com/200/300",
        description: "Look at this kitteh",
        alt: "A kitteh",
        thumbnailWidth: "200px",
      },
    ];
  */
  const messages = await client.messages.list({ to: context.TWILIO_NUMBER });
  for (const message of messages) {
    // You can have multiple medias on each message
    const pics = await message.media().list();
    for (const pic of pics) {
      // Add to the gallery array, use the outer loop's message value to put the same body
      // for each pic
      gallery.push({
        src: "https://api.twilio.com" + pic.uri.replace(".json", ""),
        description: message.body,
        alt: message.body,
        thumbnailWidth: "200px",
      });
    }
  }
  // Twilio Function will automatically turn gallery into proper JSON and set the 
  // header to `application\json`
  return callback(null, gallery);
};

 

index.html 수정

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link
      rel="stylesheet"
      href="https://fonts.googleapis.com/css?family=Open+Sans"
    />
    <style>
      body {
        font-family: "Open Sans", sans-serif;
        margin: 5%;
      }
    </style>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.13"></script>
    <script src="https://unpkg.com/vue-silentbox@2.3.1/dist/vue-silentbox.min.js"></script>
    <title>Pick.le: Pick your pics 🥒</title>
  </head>
  <body>
    <div id="app">
      <h1>Pick.le: Pick your pics 🥒</h1>
      <h2>{{ callToAction }}</h2>
      <silent-box :gallery="gallery"></silent-box>
    </div>

    <script>
      Vue.use(VueSilentbox.default);
      const app = new Vue({
        el: "#app",
        data() {
          return {
            callToAction: "Submit your photos of burritos!",
            gallery: [],
          };
        },
        methods: {
          async loadImages() {
            // Our API is on the same server so we don't need to specify the host
            // NOTE: fetch is asynchronous and returns a `Promise`, so we'll `await`
            const response = await fetch("/api/pics");
            // NOTE: The `json` method on the response object is also asynchronous
            // Setting the gallery object automatically causes the API to refresh because
            // we bound it to the plugin as part of the `data` API of Vue.
            this.gallery = await response.json();
          },
        },
        mounted() {
          this.loadImages();
        },
      });
    </script>
  </body>
</html>

해외로 MMS전송이 안되지 않아 제대로 구현은 어려웠다

원래는 가운데에 문자로 보낸 사진이 자동으로 들어갔어야 했다

 

💡

비동기 처리 async

  •  특정 코드가 끝날때 까지 코드의 실행을 멈추지 않고 다음 코드를 먼저 실행하는 것을 의미한다. 비동기 처리를 예로 Ajax, setTimeout 등이 있다.
  •  network latency 때문에
  • 자바 스크립트는 심지어 싱글 스레드 (한 번에 한 작업씩)이기 때문에 별도의 객체, promise 객체를 사용
  • fetch는 URL을 인자로 받고 미래시점에 얻게될 API 호출 결과를 promise객체로 리턴

https://www.daleseo.com/js-window-fetch/

 

관련글 더보기

댓글 영역