웹
-
[Trouble Shooting] Puppeteer (on Lambda) 오류: Navigation failed because browser has disconnected!웹/Project 2024. 5. 6. 23:53
오류 환경AWS LambdaNode.js 18@sparticuz/chromium@112.0.2puppeteer-core@19.8.0 오류 내용 Error: Navigation failed because browser has disconnected! at new LifecycleWatcher (/opt/nodejs/node_modules/puppeteer-core/lib/cjs/puppeteer/common/LifecycleWatcher.js:95:223) at Frame.goto (/opt/nodejs/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Frame.js:206:25) at CDPPage.goto (/opt/nodejs/node_modules/pu..
-
[Trouble Shooting] Puppeteer 오류: Protocol Timeout웹/Project 2024. 4. 15. 00:50
오류 내용 AWS Lambda 내에서 Puppeteer 라이브러리를 활용해 크롤링 할 때 Protocol Timeout 에러 발생 Puppeteer의 page 객체의 goto() 메서드를 호출하였을 때 이런일이 발생하였다. 트러블슈팅 과정 처음에는 Navigation timeout 에러가 발생했고, 해당 에러를 이전에 경험한 적이 있어서 크롤링 대상 홈페이지에 오류가 난것은 아닌지 확인. 정상적으로 접속되는것을 확인 Navigation timeout을 발생시키는 default timeout limit을 늘려보았으나 Protocol timeout이 발생함. Puppeteer 깃허브 페이지의 issue를 확인해보았으나 나와 같은 오류에 대한 정보는 존재하지 않았음. 환경의 문제인지 확인하기 위해 로컬에서 동..
-
AWS EC2 서버 인스턴스 변경(AWS 프리티어 갱신, 마이그레이션)웹/Project 2024. 4. 1. 14:24
문제 상황 - KAU 공지사항 알림이 서비스의 API 서버를 AWS EC2 서비스로 프로비저닝하고 있다. - AWS 프리티어 기간이 만료되어 기존 EC2 인스턴스를 온디맨드로 유지하게 되면 매달 10불 이상이 청구된다. - CloudFront, Route53은 기존 계정이 계속 관리하고 인스턴스의 소유 계정만 변경하여 비용 청구를 최소화 하고자 한다. - AWS EC2가 제공하는 AMI 복제 및 공유 기능을 활용하여 마이그레이션을 단 30분 내에 마칠 수 있다. (아키텍처에 따라 복잡성이 올라갈 것으로 예상된다) AMI는 Amazon Machine Image로, 인스턴스의 스냅샷을 생성하여 다른 인스턴스에 해당 스냅샷을 참조해 빠르게 인스턴스를 설정할 수 있게 해주는 서비스이다. AMI를 사용하지 않는다..
-
[Spring Boot] Thymeleaf로 layout을 구현하는 방법웹/Spring 2024. 1. 13. 23:17
0. 개요 스프링 부트를 사용해 MVC 패턴을 기반으로 하는 웹 어플리케이션을 만들 때, 반복되는 코드(boilerplate)가 다수 있다. 그러한 코드를 줄이기 위해서는 Thymeleaf가 지원하는 fragment 기능과 layout을 설계할 수 있도록 하는 외부 라이브러리의 도움을 받아야 한다. 그 방법에 대해서 포스팅 하겠다. 1. Thymeleaf, Thymeleaf-layout-dialect 설치 (Gradle을 사용한 빌드인 경우) build.gradle에 다음과 같이 외부 라이브러리를 import 해주자. dependencies { implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' // Thymeleaf imple..
-
[Express.js/MongoDB] Routing? Routing!웹/Express.js + MongoDB 2023. 2. 26. 00:51
목표 Routes, Router, Routing 이 무엇인지 간략히 알아본다. Express.js의 라우팅 시스템을 알아본다. 과정 라우팅이란 무엇인가? 클라이언트 상에서 HTTP 메서드를 통해 "어떤 사이트 주세요" 라고 요청하면 그에 해당하는 파일을 주는 것이라고 설명할 수 있다. 그런 요청들은 매우 다양해서(GET, POST, PATCH, DELETE ...) 어떤 한 객체나 프로그램이 관리하는 게 효율적이지 않겠는가? 어떤 음식점이 대박이 나서 영업 시간 내내 웨이팅이 있다고 해보자. 만약 그 식당에 메인 쉐프만 있다면 쉐프가 주문을 받고 결제를 한 뒤, 음식을 내야할 것이다. 한 사람이 이 모든것을 소화하기엔 너무 버거운 작업량이다. 그래서 홀에서 서빙을 하는 웨이터를 두기로 한다. 웨이터를 영..
-
[Express.js/MongoDB] UPDATE 기능 구현하기웹/Express.js + MongoDB 2023. 2. 24. 16:54
목표 CRUD 기능 중 UPDATE 기능을 구현합니다. 과정 1. UPDATE가 가능한 홈페이지를 만듭니다. 2. npm 모듈 중 `method-override` 라이브러리를 설치해 적용합니다. const methodOverride = require("method-override"); app.use(methodOverride("_method")); 3. 라우트 핸들링을 다음과 같이 해줍니다. app.get("/apperals/:id/edit", async (req, res, next) => { const apperal = await Apperal.findById(req.params.id); res.render("edit", { apperal }); }); app.patch("/apperals/:id", ..
-
[Express.js/MongoDB] READ 기능 구현하기웹/Express.js + MongoDB 2023. 2. 24. 16:24
목표 CRUD 기능 중 READ 기능을 구현한다. 과정 사실 지난번 포스팅에서 제품을 READ하는 기능을 추가하였지만, 해당 제품의 Detail 페이지를 만들어 보다 더 자세한 READ 기능을 구현해보겠습니다. 1. 먼저, 다음과 같은 라우트 핸들러를 작성합니다. app.get("/apperals/:id", async (req, res) => { const apperal = await Apperal.findById(req.params.id); res.render("details", { apperal }); }); 2. 다음과 같은 화면을 구성합니다. 3. ID를 잘못 입력한 경우를 대비해 오류 처리를 해줍니다. app.get("/apperals/:id", async (req, res, next) => {..
-
[Express.js/MongoDB] CREATE 기능 구현하기웹/Express.js + MongoDB 2023. 2. 24. 15:22
목표 Express.js와 MongoDB를 연결하여 CREATE 기능을 구현한다 과정 Express.js와 MongoDB에 대한 설정이 모두 완료되었다는 가정하에 진행합니다. 렌더링 방식은 ejs 템플릿 엔진을 이용한 SSR(Server Side Rendering) 방식으로 진행합니다. 0. 기본 서버 코드 설정 const express = require("express"); const app = express(); const mongoose = require("mongoose"); // mongoose setting mongoose.set("strictQuery", true); main() .then(() => console.log("Mongo Connected!")) .catch((err) => co..