클러스터 맵 추가 모든 캠핑장을 보여주는 index 페이지에 클러스터 맵을 추가 해보자. mapbox를 사용한다. https://docs.mapbox.com/mapbox-gl-js/example/cluster/ Create and style clusters | Mapbox GL JS Use Mapbox GL JS' built-in functions to visualize points as clusters. docs.mapbox.com 위 링크로 들어가서 필요한 코드를 붙여넣는다. 이 코드는 이미 boilerplate에 포함되어있다. clusterMap.js라는 파일을 새로 만들어서 스크립트 부분을 붙여 넣는다. 참고로 나는 맵 스타일을 light-v10 버전으로 바꿨다. mapboxgl.accessTok..
지오코딩 지오코딩은 람이 읽을 수 있는 주소를 지도상의 위치로 변환하는 과정이다. 우리가 보통 쓰는 글로 된 주소를 입력하면 위도와 경도로 변환한다. 여기서는 지오코딩 API인 Mapbox를 사용하기 때문에 Mapbox에 접속해서 회원가입을 한다. 설치 Mapbox에는 mapbox-sdk라는 Node 클라이언트가 있어서 npm으로 설치하면 된다. npm install @mapbox/mapbox-sdk 실습 환경변수 설정 회원가입하고 어카운트에 들어가면 access token이 있다. 그것을 복사해서 .env에 아래의 등호 옆에 붙여 넣는다. MAPBOX_TOKEN= Mapbox 설정 아래 코드를 boilerplate.ejs에 붙여 넣는다. mapbox api를 사용하기 위한 스크립트다. 함수를 정의해 놓..
이미지 추가 캠핑장 편집 버튼을 누르면 이미지를 추가 할 수 있게 바꿔보자. 1. edit.ejs에서 form에 enctype="multiplart/form-data"를 추가한다. 여러 개의 이미지를 입력받을 수 있게 하기 위해서다. 2. 파일 선택기를 추가한다. Add Images 3. 라우트의 put에 upload.array('image') 미들웨어를 추가한다. 4. 캠핑장 편집을 수행하는 controller에 위치한 editCampground 함수에 아래 코드를 추가한다. const imgs = req.files.map(f => ({ url: f.path, filename: f.filename })); camp.images.push(...imgs); await camp.save(); 이미지 삭제 편..
Cloudinary 캠핑장을 생성할 때 이미지 파일을 입력받고 입력받은 이미지는 cloudinary라는 클라우드에 저장한다. cloud name, api key, api secret을 사용할 예정이다. 패키지 설치 npm i multer dotenv cloudinary multer-storage-cloudinary new 페이지의 form에 enctype="multipart/form-data"를 추가한다. multipart/form-data는 모든 문자를 인코딩하지 않음을 나명시한다. 파일이나 이미지를 서버로 전송할 때 사용한다. 서버에서 req.body를 출력해보면 body가 비어있는데, 이는 multipart/form-data를 파싱하지 않았기 때문이다. 파싱하기 위해 미들웨어 multer을 사용한다..
passport 라이브러리 설치 passport는 node 앱에 인증을 추가해주는 유명한 도구이다. 구글이나 트위터, 페이스북 같은 계정으로도 로그인 할 수 있게 해준다. 이 프로젝트에서는 로컬 계정으로만 로그인 할 수 있게 구현한다. npm i passport passport-local passport-local-mongoose 사용자 계정 모델 User 스키마를 정의할 때 사용자 이름과 비밀번호는 지정하지 않는다. plugin이 스키마에 사용자 이름과 비밀번호를 추가해주기 때문이다. const mongoose = require('mongoose'); const passportLocalMongoose = require('passport-local-mongoose'); const Schema = mong..
DB 정의 아이디와 비밀번호를 저장하는 데이터베이스를 만들어보자. const userSchema = new mongoose.Schema({ username: { type: String, required: [true, 'Username cannot be blank'], unique: true }, password: { type: String, required: [true, 'Password cannot be blank'], unique: true } }) 비밀번호 암호화 비밀번호를 있는 그대로 저장하면 안 된다. 그런 일이 벌어져서는 안 되지만 누군가가 데이터베이스에 몰래 접근했다고 하자. 그럼 모든 사용자의 아이디와 비밀번호를 알 수 있을 것이다. 이런 상황을 막기 위해 비밀번호는 암호화해서 저장해야 한..
설치 npm i connect-flash 미들웨어 추가 flash는 session을 사용하므로 app.use(session ... ) 뒤에 넣어야 합니다. 캠핑장 생성하거나 수정 등등을 할 때 req.flash(키값, 메시지)를 하면 메시지가 res.locals의 속성으로 설정이 되어서 flash.ejs로 변수들을 보낼 수 있습니다. res.locals의 property들은 request의 라이프 타임 동안만 유효합니다. app.js const flash = require('connect-flash'); app.use(flash()); app.use((req, res, next) => { res.locals.success = req.flash('success'); res.locals.error = req..
세션 개요 쿠키는 많은 것을 저장할 수 없습니다. 브라우저의 쿠키 크기에는 제한이 있기 때문입니다. 또한, 쿠키는 서버 측에서 정보를 저장하는 것만큼 안전하지 않습니다. 그래서 세션이 필요합니다. 모든 데이터를 쿠키에 저장하지 않고 세션 id만 저장하였습니다. 하지만 서버에서는 그 쿠키만 있으면 해당하는 id의 모든 정보를 알 수 있습니다. 참고로, 이 데이터 저장소는 일반적인 데이터베이스와는 다릅니다. 세션 실습 세션 실습을 하기위해 먼저 cmd창에서 npm i express-session을 합니다. const colors = require('colors'); const express = require('express'); const app = express(); const session = requi..
Express 라우터 큰 앱 하나에 라우트를 많이 넣으면 코드의 길이가 매우 길어집니다. 실제로 앱을 만들때는 그렇게 하지 않기 때문에 Express 라우터를 사용합니다. 아래와 같은 라우트를 만들어봅시다. Route Method GET /farms POST /farms GET /farms/:id GET /farms/:id/edit farms.js const express = require('express'); const router = express.Router(); router.get('/farms', (req, res) => { res.send('All Farms'); }) router.post('/farms', (req, res) => { res.send('Creating Farm'); }) ro..