#api

닥터핸닥터핸· 3개월

Supabase - 백엔드를 넘어서 새로운 가능성을 열다

"Queue, Cron, Background Tasks까지? Supabase는 정말 어디까지 진화할까요?" 요즘 Supabase가 제공하는 새로운 기능들이 주목받고 있습니다. 이 글에서는 Dev.to의 Taishi가 소개한 Supabase의 새로운 기능들을 살펴보고, 실용적인 예제와 함께 그 가능성을 탐구해보겠습니다. Supabase란 무엇인가요? Supabase는 Firebase의 오픈소스 대안으로 시작된 프로젝트로, 데이터베이스, 인증, 실시간 업데이트, 서버리스 함수 등 다양한 기능을 제공합니다. 최근 Supabase는 Queue, Cron, Background Tasks 등 백엔드 기능을 강화하며 개발자들에게 더 많은 도구를 제공하고 있습니다. 이런 기능은 특히 서버리스(Serverless) 환경에서 애플리케이션을 개발하는 데 유용합니다. 이번 글에서는 최근 강화된 Queue, Cron, Background Tasks에 대해서 소개합니다. 새로운 기능 살펴보기 1. Queue Queue는 작업을 대기열에 추가하고 순차적으로 실행할 수 있는 기능입니다. 복잡한 작업을 관리하거나, 대량의 데이터를 처리할 때 유용합니다. 예제 코드: import { createQueue } from 'supabase-functions'; const queue = createQueue('email-sender'); queue.on('process', async (job) => { await sendEmail(job.data); }); Supabase의 Queue는 Deno 환경에서 실행되며, 작업의 실패와 재시도를 자동으로 관리합니다. (참고로 Supabase는 내부적으로 Deno를 사용하여 서버리스 함수 (Edge Functions)를 실행합니다. Supabase Edge Functions는 Deno 런타임 위에서 작동하며, 타입스크립트를 기본 언어로 사용합니다.) 2. Cron Cron은 정기 작업을 설정하는 기능입니다. 예를 들어, 매일 자정마다 데이터를 정리하거나, 매주 보고서를 생성할 때 사용할 수 있습니다. 예제 코드: import { schedule } from 'supabase-functions'; schedule('0 0 * * *', async () => { await cleanupDatabase(); }); 표준 CRON 표현식을 사용해 원하는 시간에 작업을 예약할 수 있습니다. 복잡한 서버 관리를 하지 않아도 되니 효율적입니다. 3. Background Tasks Background Tasks는 비동기 작업을 처리하는 데 사용됩니다. 사용자가 대기하지 않아도 되는 작업(예: 이미지 처리, 데이터 분석)을 배경에서 실행할 수 있습니다. 예제 코드: import { createTask } from 'supabase-functions'; const task = createTask('image-processor'); await task.dispatch({ imageId: '1234' }); 이 기능은 사용자의 경험을 방해하지 않으면서 중요한 작업을 처리할 수 있는 강력한 도구입니다. Supabase의 새로운 기능으로 개발 가능한 애플리케이션 이메일 마케팅 플랫폼: Queue를 사용해 이메일 발송 자동화하기. 정기 보고서 생성: Cron으로 데이터 분석 결과를 주기적으로 생성하기. 이미지 업로드 서비스: Background Tasks로 대량의 이미지 처리하기. 결론 Supabase는 점점 더 강력한 백엔드 기능을 제공하며, 개발자가 애플리케이션에 집중할 수 있도록 돕고 있습니다. 특히, 백엔드 구축에 많은 시간을 할애하기 어려운 소규모 팀이나 1인 개발자에게는 최적의 선택이 될 것 같습니다.
327
1
0
아란아란· 4개월

OpenAI의 모든 유료 사용자가 이제 o1 모델 API 사용 가능

한 줄 요약: OpenAI가 수학과 과학 분야에서 PhD 수준의 성능을 보이는 새로운 AI 모델인 o1을 모든 유료 API 사용자 대상으로 쓸 수 있게 공개함. 사용 가능 범위 확대 OpenAI가 모든 유료 API 사용자들에게 o1 대규모 언어 모델의 프리뷰 버전과 미니 버전을 공개함 이전에는 OpenAI 플랫폼에서 $1,000 이상을 사용했던 "Tier 5" 개발자들만 이 API에 접근할 수 있었음 ChatGPT 유료 사용자들은 몇 주 전부터 사용 가능했으나, 인터넷 검색 기능은 제공되지 않음 OpenAI는 모델들의 스트리밍 기능을 활성화했으며, 이를 통해 사용자들이 응답 생성 과정에서 점진적으로 결과를 받을 수 있게 됨 o1의 주요 특징과 능력은 무엇인가 성능 특징 o1-preview는 고급 추론과 문제 해결을 위해 설계됐으며, 여러 과학 분야에서 PhD 수준 이상의 성능을 보임 코딩과 수학 능력이 이전 모델들보다 향상됐으나, GPT-4o보다는 응답 속도가 느림 mini 버전은 o1-preview보다 기능이 제한적이나, 더 빠른 응답을 제공함 구체적인 능력 예시 인간의 사고 과정과 유사한 단계별 문제 해결 방식으로 훈련됨 응답은 더 느릴 수 있으나, 정확도가 크게 향상됨 국제 수학 올림피아드 입학 시험에서 83%의 정답률을 기록함(GPT-4o는 13%) 생물학, 물리학, 화학, 코딩 분야에서 PhD 수준의 전문가 기준을 초과하는 성능을 보임 아래는 가격 정책 참고 입력 토큰과 출력 토큰 기준으로 과금됨: o1-preview 입력: 백만 토큰당 $15 출력: 백만 토큰당 $60 o1-mini 입력: 백만 토큰당 $3 출력: 백만 토큰당 $12 GPT-4o 입력: 백만 토큰당 $2.50 출력: 백만 토큰당 $10 기타 특징들 캐시된 입력에 대해 할인이 제공됨 GPT-4o와 달리 o1 모델은 배치 처리가 불가능함
217
1
0
고준환고준환· 3년

질문nodejs + 네이버api(내위치 파란점) 추가

안녕하세요 이번에 nodejs + 네이버api로 제 위치 주변 약국찾기를 완성하였습니다. 그런데 제 위치를 보여주는 파란점을 추가하면 좋겠다싶어 이리저리 찾아보던중 overlay라는 함수가 필요하더군요. 기쁜마음으로 index.html에서 수십번 스스로 코드 변형 및 추가를 해보았으나 잘 되지가 않았습니다. 혹시 어디를 고치고 추가해야하는지 도움을 좀 구할 수 있을까요?.   저의 기존 index.html은 아래와 같고 사진처럼 보이게 하기 위한 overlay함수를 추가하려고 합니다 <html> <head> <!-- script type는 자바스크립트, src를 넣어 소스는 다른 곳에 있다고 지정 ex) 네이버 open api에 있는 정보--> <script type="text/javascript" src="https://openapi.map.naver.com/openapi/v3/maps.js?ncpClientId=xeulgqnc95&amp;submodules=geocoder"></script> <script src="https://code.jquery.com/jquery-3.6.1.min.js" integrity="sha256-o88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ=" crossorigin="anonymous"></script> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <div style="margin-top: 20px; margin-bottom: 10px; font-weight: bold;"> 약국 지도💊 </div> <div id="map" style="width:100%; height:80%"> </div> </body> <script> $(document).ready(async function(){ let XY = await getLocation(); //alert("위도" + XY.lat); //alert("경도" + XY.lng); // reverseGeocode는 비동기형이라 await 추가 await naver.maps.Service.reverseGeocode({ location: new naver.maps.LatLng(XY.lat, XY.lng) },function(status, response){ let result = response.result; let items = result.items; //console.log(items[0].addrdetail.sido); //console.log(items[0].addrdetail.sigugun); let sido_arr = items[0].addrdetail.sido.split(" "); let gubun_arr = items[0].addrdetail.sigugun.split(" "); let sido = ""; let gubun = ""; if(sido_arr.length ==1) { sido = sido_arr[0]; gugun = gubun_arr[0] } else if(sido_arr.length > 1) { sido = sido_arr[0]; gugun = sido_arr[1] } console.log(sido); console.log(gugun); $.ajax({ url: "/pharmach_list", type: "GET", // GET을 통해 밑에 주석처리한 api url 부분 ?뒤부터 눈에 보이게끔 값들을 하나하나 입력해줌 cache: false, //cache는 쓰지 않을거라 false dataType: "json", //dataType은 json으로 받겠다 data: {"Q0": sido, "Q1": gugun, "QT": "", "QN": "", "ORD": "", "pageNo": "1", "numOfRows": "1000"}, success: function(data) { console.log(data); //지도를 삽입할 HTML 요소 또는 HTML 요소의 id를 지정합니다. var mapDiv = document.getElementById('map'); // 'map'으로 선언해도 동일 //옵션 없이 지도 객체를 생성하면 서울 시청을 중심으로 하는 16 레벨의 지도가 생성됩니다. var mapOptions = { center: new naver.maps.LatLng(XY.lat, XY.lng), zoom: 14 } var map = new naver.maps.Map(mapDiv, mapOptions); data.items.item.forEach(function(it, index){ let dutyName = it.dutyName; let dutyAddr = it.dutyAddr; let dutyTel1 = it.dutyTel1; let dutyTime = ""; if(it.dutyTime1s && it.dutyTime1c) { dutyTime += "월요일: " + it.dutyTime1s + " ~ " + it.dutyTime1c + "<br>"; } if(it.dutyTime2s && it.dutyTime2c) { dutyTime += "화요일: " + it.dutyTime2s + " ~ " + it.dutyTime2c + "<br>"; } if(it.dutyTime3s && it.dutyTime3c) { dutyTime += "수요일: " + it.dutyTime3s + " ~ " + it.dutyTime3c + "<br>"; } if(it.dutyTime4s && it.dutyTime4c) { dutyTime += "목요일: " + it.dutyTime4s + " ~ " + it.dutyTime4c + "<br>"; } if(it.dutyTime5s && it.dutyTime5c) { dutyTime += "금요일: " + it.dutyTime5s + " ~ " + it.dutyTime5c + "<br>"; } if(it.dutyTime6s && it.dutyTime6c) { dutyTime += "토요일: " + it.dutyTime6s + " ~ " + it.dutyTime6c + "<br>"; } if(it.dutyTime7s && it.dutyTime7c) { dutyTime += "일요일: " + it.dutyTime7s + " ~ " + it.dutyTime7c + "<br>"; } if(it.dutyTime8s && it.dutyTime8c) { dutyTime += "공휴일"; + it.dutyTime8s + " ~ " + it.dutyTime8c + "<br>"; } let pharmacy_location = new naver.maps.LatLng(it.wgs84Lat, it.wgs84Lon) let marker = new naver.maps.Marker({ map: map, position: pharmacy_location }); var contentString = [ '<div class="iw_inner">', ' <h3>'+dutyName+'</h3>', ' <p>'+dutyAddr+'<br />', ' '+dutyTel1+'<br />', ' '+dutyTime, ' </p>', '</div>' ].join(''); var infowindow = new naver.maps.InfoWindow({ content: contentString, maxWidth: 440, backgroundColor: "#eee", borderColor: "#2db400", borderWidth: 5, anchorSize: new naver.maps.Size(30, 30), anchorSkew: true, anchorColor: "#eee", pixelOffset: new naver.maps.Point(20, -20) }); naver.maps.Event.addListener(marker, "click", function(e) { if (infowindow.getMap()) { infowindow.close(); } else { infowindow.open(map, marker); } }); }); }, error: function(request, status, error) { } }); }); }); // geolocation은 gps와 관련된 객체, 이 객체가 존재하면 getLocation 실행함 // getCurrentPosition 사용시 현재 위치를 알 수 있다, position 이라는 객체를 통해 현 위치 파악 async function getLocation() { let XY = new Object(); if(navigator.geolocation) { let promise = new Promise((resolve, rejected) => { navigator.geolocation.getCurrentPosition((position) => { resolve(position); }); }); let position = await promise; //위도 position.coords.latitude //경도 position.coords.longitude XY.lat = position.coords.latitude XY.lng = position.coords.longitude } return XY; } </script> </html>   현재는 이렇게 보입니다 https://pharmacy1234.herokuapp.com/   그리고 저의 이메일입니다! [email protected]  
1.1K
1
0