Junhyuyk Seo

Integrate server with apihandler

Showing 50 changed files with 744 additions and 103 deletions
1 +node_modules
2 +npm-debug.log
...\ No newline at end of file ...\ No newline at end of file
1 +FROM node:14
2 +
3 +LABEL title="TFT-APIHandler"
4 +LABEL version="1.00"
5 +
6 +# set working directory
7 +WORKDIR /app
8 +
9 +# install modules and dependencies
10 +COPY package*.json ./
11 +RUN npm install
12 +
13 +# copy source codes
14 +COPY ./ ./
15 +
16 +#start application
17 +CMD [ "node", "server.js" ]
...\ No newline at end of file ...\ No newline at end of file
1 +exports.COORDINATES = {
2 + "서울특별시" : {
3 + "종로구" : [60, 127],
4 + "중구" : [60, 127],
5 + "용산구" : [60, 126],
6 + "성동구" : [61, 127],
7 + "광진구" : [62, 126],
8 + "동대문구" : [61, 127],
9 + "중랑구" : [62, 128],
10 + "성북구" : [61, 127],
11 + "강북구" : [61, 128],
12 + "도봉구" : [61, 129],
13 + "노원구" : [61, 129],
14 + "은평구" : [59, 127],
15 + "서대문구" : [59, 127],
16 + "마포구" : [59, 127],
17 + "양천구" : [58, 126],
18 + "강서구" : [58, 126],
19 + "구로구" : [58, 125],
20 + "금천구" : [59, 124],
21 + "영등포구" : [58, 126],
22 + "동작구" : [59, 125],
23 + "관악구" : [59, 125],
24 + "서초구" : [61, 125],
25 + "강남구" : [61, 126],
26 + "송파구" : [62, 126],
27 + "강동구" : [62, 126]
28 + },
29 + "부산광역시" : {
30 + "중구" : [97, 74],
31 + "서구" : [97, 74],
32 + "동구" : [98, 75],
33 + "영도구" : [98, 74],
34 + "부산진구" : [97, 75],
35 + "동래구" : [98, 76],
36 + "남구" : [98, 75],
37 + "북구" : [96, 76],
38 + "해운대구" : [99, 75],
39 + "사하구" : [96, 74],
40 + "금정구" : [98, 77],
41 + "강서구" : [96, 76],
42 + "연제구" : [98, 76],
43 + "수영구" : [99, 75],
44 + "사상구" : [96, 75],
45 + "기장군" : [100, 77]
46 + },
47 + "대구광역시" : {
48 + "중구" : [89, 90],
49 + "동구" : [90, 91],
50 + "서구" : [88, 90],
51 + "남구" : [89, 90],
52 + "북구" : [89, 91],
53 + "수성구" : [89, 90],
54 + "달서구" : [88, 90],
55 + "달성군" : [86, 88]
56 + },
57 + "인천광역시" : {
58 + "중구" : [54, 125],
59 + "동구" : [54, 125],
60 + "미추홀구" : [54, 124],
61 + "연수구" : [55, 123],
62 + "남동구" : [56, 124],
63 + "부평구" : [55, 125],
64 + "계양구" : [56, 126],
65 + "서구" : [55, 126],
66 + "강화군" : [51, 130],
67 + "옹진군" : [54, 124]
68 + },
69 + "광주광역시" : {
70 + "동구" : [60, 74],
71 + "서구" : [59, 74],
72 + "남구" : [59, 73],
73 + "북구" : [59, 75],
74 + "광산구" : [57, 74]
75 + },
76 + "대전광역시" : {
77 + "동구" : [68, 100],
78 + "중구" : [68, 100],
79 + "서구" : [67, 100],
80 + "유성구" : [67, 101],
81 + "대덕구" : [68, 100]
82 + },
83 + "울산광역시" : {
84 + "중구" : [102, 84],
85 + "남구" : [102, 84],
86 + "동구" : [104, 83],
87 + "북구" : [103, 85],
88 + "울주군" : [101, 84]
89 + },
90 + "세종특별자치시" : {
91 + "세종특별자치시": [66, 103]
92 + },
93 + "경기도" : {
94 + "수원시" : [61, 120],
95 + "성남시" : [63, 124],
96 + "의정부시" : [61, 130],
97 + "안양시" : [59, 123],
98 + "부천시" : [56, 125],
99 + "광명시" : [58, 125],
100 + "평택시" : [62, 114],
101 + "동두천시" : [61, 134],
102 + "안산시" : [58, 121],
103 + "고양시" : [57, 128],
104 + "과천시" : [60, 124],
105 + "구리시" : [62, 127],
106 + "남양주시" : [64, 128],
107 + "오산시" : [62, 118],
108 + "시흥시" : [57, 123],
109 + "군포시" : [59, 122],
110 + "의왕시" : [60, 122],
111 + "하남시" : [64, 126],
112 + "용인시" : [64, 119],
113 + "파주시" : [56, 131],
114 + "이천시" : [68, 121],
115 + "안성시" : [65, 115],
116 + "김포시" : [55, 128],
117 + "화성시" : [57, 119],
118 + "광주시" : [65, 123],
119 + "양주시" : [61, 131],
120 + "포천시" : [64, 134],
121 + "여주시" : [71, 121],
122 + "연천군" : [61, 138],
123 + "가평군" : [69, 133],
124 + "양평군" : [69, 125]
125 + },
126 + "강원도" : {
127 + "춘천시" : [73, 134],
128 + "원주시" : [76, 122],
129 + "강릉시" : [92, 131],
130 + "동해시" : [97, 127],
131 + "태백시" : [95, 119],
132 + "속초시" : [87, 141],
133 + "삼척시" : [98, 125],
134 + "홍천군" : [75, 130],
135 + "횡성군" : [77, 125],
136 + "영월군" : [86, 119],
137 + "평창군" : [84, 123],
138 + "정선군" : [89, 123],
139 + "철원군" : [65, 139],
140 + "화천군" : [72, 139],
141 + "양구군" : [77, 139],
142 + "인제군" : [80, 138],
143 + "고성군" : [85, 145],
144 + "양양군" : [88, 138]
145 + },
146 + "충청북도" : {
147 + "청주시" : [69, 106],
148 + "충주시" : [76, 114],
149 + "제천시" : [81, 118],
150 + "보은군" : [73, 103],
151 + "옥천군" : [71, 99],
152 + "영동군" : [74, 97],
153 + "증평군" : [71, 110],
154 + "진천군" : [68, 111],
155 + "괴산군" : [74, 111],
156 + "음성군" : [72, 113],
157 + "단양군" : [84, 115]
158 + },
159 + "충청남도" : {
160 + "천안시" : [63, 110],
161 + "공주시" : [63, 102],
162 + "보령시" : [54, 100],
163 + "아산시" : [60, 110],
164 + "서산시" : [51, 110],
165 + "논산시" : [62, 97],
166 + "계룡시" : [65, 99],
167 + "당진시" : [54, 112],
168 + "금산군" : [69, 95],
169 + "부여군" : [59, 99],
170 + "서천군" : [55, 94],
171 + "청양군" : [57, 103],
172 + "홍성군" : [55, 106],
173 + "예산군" : [58, 107],
174 + "태안군" : [48, 109]
175 + },
176 + "전라북도" : {
177 + "전주시" : [63, 89],
178 + "군산시" : [56, 92],
179 + "익산시" : [60, 91],
180 + "정읍시" : [58, 83],
181 + "남원시" : [68, 80],
182 + "김제시" : [59, 88],
183 + "완주군" : [63, 89],
184 + "진안군" : [68, 88],
185 + "무주군" : [72, 93],
186 + "장수군" : [70, 85],
187 + "임실군" : [66, 84],
188 + "순창군" : [63, 79],
189 + "고창군" : [56, 80],
190 + "부안군" : [56, 87]
191 + },
192 + "전라남도" : {
193 + "목포시" : [50, 67],
194 + "여수시" : [73, 66],
195 + "순천시" : [70, 70],
196 + "나주시" : [56, 71],
197 + "광양시" : [73, 70],
198 + "담양군" : [61, 78],
199 + "곡성군" : [66, 77],
200 + "구례군" : [69, 75],
201 + "고흥군" : [66, 62],
202 + "보성군" : [62, 66],
203 + "화순군" : [61, 72],
204 + "장흥군" : [59, 64],
205 + "강진군" : [57, 63],
206 + "해남군" : [54, 61],
207 + "영암군" : [56, 66],
208 + "무안군" : [52, 71],
209 + "함평군" : [52, 72],
210 + "영광군" : [52, 77],
211 + "장성군" : [57, 77],
212 + "완도군" : [57, 56],
213 + "진도군" : [48, 59],
214 + "신안군" : [50, 66]
215 + },
216 + "경상북도" : {
217 + "포항시" : [102, 94],
218 + "경주시" : [100, 91],
219 + "김천시" : [80, 96],
220 + "안동시" : [91, 106],
221 + "구미시" : [84, 96],
222 + "영주시" : [89, 111],
223 + "영천시" : [95, 93],
224 + "상주시" : [81, 102],
225 + "문경시" : [81, 106],
226 + "경산시" : [91, 90],
227 + "군위군" : [88, 99],
228 + "의성군" : [90, 101],
229 + "청송군" : [96, 103],
230 + "영양군" : [97, 108],
231 + "영덕군" : [102, 103],
232 + "청도군" : [91, 86],
233 + "고령군" : [83, 87],
234 + "성주군" : [83, 91],
235 + "칠곡군" : [85, 93],
236 + "예천군" : [86, 107],
237 + "봉화군" : [90, 113],
238 + "울진군" : [102, 115],
239 + "울릉군" : [127, 127]
240 + },
241 + "경상남도" : {
242 + "창원시" : [90, 77],
243 + "진주시" : [81, 75],
244 + "통영시" : [87, 68],
245 + "사천시" : [80, 71],
246 + "김해시" : [95, 77],
247 + "밀양시" : [92, 83],
248 + "거제시" : [90, 69],
249 + "양산시" : [97, 79],
250 + "의령군" : [83, 78],
251 + "함안군" : [86, 77],
252 + "창녕군" : [87, 83],
253 + "고성군" : [85, 71],
254 + "남해군" : [77, 68],
255 + "하동군" : [74, 73],
256 + "산청군" : [76, 80],
257 + "함양군" : [74, 82],
258 + "거창군" : [77, 86],
259 + "합천군" : [81, 84]
260 + },
261 + "제주특별자치도" : {
262 + "제주시" : [53, 38],
263 + "서귀포시" : [52, 33]
264 + }
265 +}
...\ No newline at end of file ...\ No newline at end of file
1 +const mongoose =require('mongoose');
2 +const { Schema } =mongoose;
3 +
4 +const festivalSchema = new Schema({
5 + title: String,
6 + addr: String,
7 + tel: String,
8 + contentid : Number,
9 + mapx : Number,
10 + mapy : Number,
11 + eventstartdate : String,
12 + eventenddate : String,
13 + overview : String,
14 + firstimage : String,
15 + homepage : String,
16 + weathers : String
17 + // weather : {
18 + // date1: { weather : String, temp : Number},
19 + // date2: { weather : String, temp : Number},
20 + // date3: { weather : String, temp : Number},
21 + // }
22 +},
23 +{
24 + versionKey: false
25 +});
26 +
27 +
28 +module.exports = mongoose.model('Festival',festivalSchema);
This diff is collapsed. Click to expand it.
1 +{
2 + "name": "REST-API",
3 + "version": "1.0.0",
4 + "description": "",
5 + "main": "index.js",
6 + "scripts": {
7 + "test": "echo \"Error: no test specified\" && exit 1"
8 + },
9 + "keywords": [],
10 + "author": "",
11 + "license": "ISC",
12 + "dependencies": {
13 + "dotenv": "^10.0.0",
14 + "mongoose": "^6.0.13",
15 + "request": "^2.88.2",
16 + "request-promise-native": "^1.0.9"
17 + }
18 +}
1 +const mongoose = require('mongoose');
2 +// const db = require('mongodb');
3 +const Festival = require('./models/Festival');
4 +const request = require('request-promise-native');
5 +
6 +const url = 'mongodb://mongo:27017';
7 +
8 +const ServiceKey = '3zrQDvoNwUV9Se%2BHZv8DjCCNWRGJisQ7jjHP6LsbJqoRQ2cJpQKrHUGC4uslgXSVO9Dzb06BSC3kp9BunvIPSw%3D%3D';
9 +const ServiceKey2 ='%2FGjtI8kwZeJTzJm%2BxUxz%2Bjh15wnmV3rwFuRvrq3oRSqyklfiZfbUaqmsG0McVPJMdXSUYetGaCXl0ZkbfMI0BQ%3D%3D'
10 +const ServiceKey3 ='%2FsBWti235XX%2Fg1%2FqBZfiNQ6A%2BJmF3WL%2FboaNqJH4v3eWic59SiHc6W5vgZKU7Hjocj%2BAntIqHfhXOpmE5CpAFw%3D%3D'
11 +
12 +const WeatherServiceKey = '2lFkvQJYgzOOhwUKiUt8aZVNpd1PpBOf%2FfMNW17cl25DE0GUEDddeR9iGnuSUpggjUoIUgamfhcvnKQ3eH1dAw%3D%3D';
13 +const COORDINATES = require('./coordinates')['COORDINATES'];
14 +const DISTRICT = [
15 + "서울특별시", "부산광역시", "울산광역시", "대구광역시", "대전광역시",
16 + "인천광역시", "광주광역시", "세종특별자치시", "제주특별자치도",
17 + "경기도", "강원도", "충청북도", "충청남도", "경상북도",
18 + "경상남도", "전라북도", "전라남도"
19 +]
20 +const WEATHERTYPE = [
21 + '맑음', '비', '비/눈', '눈', '소나기'
22 +];
23 +
24 +function parseDistrict(addr) {
25 + const words = addr.split(" ");
26 + if( DISTRICT.includes(words[0]) ) {
27 + return [words[0], words[1]];
28 + } else {
29 + return [];
30 + }
31 +}
32 +function leftPad(value) { if (value >= 10) { return value; } return `0${value}`; }
33 +
34 +writeDB()
35 +setInterval(() => {
36 + writeDB();
37 +}, 86400000);
38 +
39 +function writeDB() {
40 +
41 +var today = new Date();
42 +var yesterday = new Date();
43 +yesterday.setDate(yesterday.getDate() - 1);
44 +let todayString = "" + (today.getFullYear())+leftPad(today.getMonth()+1)+leftPad(today.getDate());
45 +let yesterdayString = "" + (yesterday.getFullYear())+leftPad(yesterday.getMonth()+1)+leftPad(yesterday.getDate()-1);
46 +var todayTime = leftPad(today.getHours()) + "00";
47 +
48 +mongoose.connect(url,(err)=>{
49 + if(err) {
50 + console.log(err);
51 + } else {
52 + mongoose.connection.db.dropCollection('festivals',function(err, result) {
53 + if(err) {
54 + console.log(err + "Reset Failed!");
55 + } else {
56 + console.log(result + "Reset Success!");
57 +
58 + for(let i = 1; i <= 5; i++) {
59 + let options = {
60 + 'method': 'GET',
61 + 'url' : 'http://api.visitkorea.or.kr/openapi/service/rest/KorService/areaBasedList'
62 + + '?ServiceKey=' + ServiceKey2
63 + + '&contentTypeId=15&areaCode=&sigunguCode=&cat1=&cat2=&cat3=&listYN=Y&MobileOS=ETC&MobileApp=TourAPI3.0_Guide&arrange=C&numOfRows=12'
64 + + '&pageNo='+ i
65 + + '&_type=json',
66 +
67 + 'headers': {}
68 + };
69 +
70 + request(options, async function (error, response, body) {
71 + if (error) {
72 + throw new Error(error);
73 + }
74 + let info = JSON.parse(body);
75 +
76 + let items = info['response']['body']['items']['item'];
77 + for(item of items) {
78 + let Info = {
79 + 'public': {
80 + 'method': 'GET',
81 + 'url': 'http://api.visitkorea.or.kr/openapi/service/rest/KorService/detailCommon?'
82 + + 'ServiceKey=' + ServiceKey2
83 + + '&contentTypeId=' + '15'
84 + + '&contentId=' + item['contentid']
85 + + '&MobileOS=ETC&MobileApp=TourAPI3.0_Guide&defaultYN=Y&firstImageYN=Y&areacodeYN=Y&catcodeYN=Y&addrinfoYN=Y&mapinfoYN=Y&overviewYN=Y&transGuideYN=Y&_type=json',
86 + 'headers': {}
87 + },
88 + 'detail': {
89 + 'method': 'GET',
90 + 'url': 'http://api.visitkorea.or.kr/openapi/service/rest/KorService/detailIntro?'
91 + + 'ServiceKey=' + ServiceKey2
92 + + '&contentTypeId=' + '15'
93 + + '&contentId=' + item['contentid']
94 + + '&MobileOS=ETC&MobileApp=TourAPI3.0_Guide&introYN=Y&_type=json',
95 + 'headers': {}
96 + },
97 + 'weather': {
98 + 'method': 'GET',
99 + 'url': '',
100 + 'headers': {}
101 + }
102 + };
103 + await request(Info.public, async function (error, response, body) {
104 + if (error) {
105 + throw new Error(error);
106 + }
107 +
108 + let toSave = true;
109 + let pinfo = JSON.parse(body);
110 + let distriction = parseDistrict(pinfo['response']['body']['items']['item']['addr1']);
111 + if (distriction.length == 0) toSave = false;
112 +
113 + const newFestival = new Festival();
114 + newFestival.title = pinfo['response']['body']['items']['item']['title'];
115 + newFestival.contentid = pinfo['response']['body']['items']['item']['contentid'];
116 + newFestival.addr = pinfo['response']['body']['items']['item']['addr1'];
117 + newFestival.tel = pinfo['response']['body']['items']['item']['tel'];
118 + newFestival.mapx = pinfo['response']['body']['items']['item']['mapx'];
119 + newFestival.mapy = pinfo['response']['body']['items']['item']['mapy'];
120 + newFestival.overview= pinfo['response']['body']['items']['item']['overview'];
121 + newFestival.firstimage = pinfo['response']['body']['items']['item']['firstimage'];
122 + newFestival.homepage = pinfo ['response']['body']['items']['item']['homepage'];
123 +
124 +
125 + await request(Info.detail, function (error, response, body) {
126 + if (error) {
127 + throw new Error(error);
128 + }
129 + let dinfo = JSON.parse(body);
130 + newFestival.eventstartdate = dinfo['response']['body']['items']['item']['eventstartdate'];
131 + newFestival.eventenddate = dinfo['response']['body']['items']['item']['eventenddate'];
132 +
133 + if (newFestival.eventenddate < todayString) toSave = false;
134 + });
135 +
136 + let [nx, ny] = COORDINATES[distriction[0]][distriction[1]];
137 + let curDate = ('0500' < todayTime ? todayString : yesterdayString);
138 +
139 + Info.weather.url = 'http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getVilageFcst?'
140 + + 'serviceKey=' + WeatherServiceKey
141 + + '&pageNo=' + '1'
142 + + '&numOfRows=' + '2000'
143 + + '&dataType=' + 'JSON'
144 + + '&base_date=' + curDate
145 + + '&base_time=' + '0500'
146 + + '&nx=' + nx
147 + + '&ny=' + ny;
148 +
149 + await request(Info.weather, function (error, response, body) {
150 + if (error) {
151 + throw new Error(error);
152 + }
153 + let winfo = JSON.parse(body);
154 +
155 + let weathers = {};
156 + for( let item of winfo['response']['body']['items']['item'] ) {
157 + if(item['fcstTime'] === '1200') { // 최고기온 + 날씨
158 + let fcstDate = item['fcstDate'];
159 + if(!weathers[fcstDate]) weathers[fcstDate] = {};
160 + if(item['category']=='TMP') {
161 + weathers[fcstDate]['temp'] = item['fcstValue'];
162 + } else if(item['category']=='PTY') {
163 + weathers[fcstDate]['weather'] = WEATHERTYPE[item['fcstValue']];
164 + }
165 + }
166 + }
167 + newFestival.weathers = JSON.stringify(weathers);
168 + });
169 +
170 + if (toSave)
171 + await newFestival.save().then((festival) => {
172 + console.log(festival, "Save success!");
173 + });
174 + })
175 + }
176 + });
177 + }
178 + }
179 + });
180 + }
181 + });
182 +}
1 +node_modules
2 +npm-debug.log
...\ No newline at end of file ...\ No newline at end of file
1 FROM node:14 1 FROM node:14
2 2
3 LABEL title="TFT-Webserver" 3 LABEL title="TFT-Webserver"
4 -LABEL version="1.01" 4 +LABEL version="1.00"
5 5
6 # set working directory 6 # set working directory
7 WORKDIR /app 7 WORKDIR /app
......
...@@ -21,4 +21,4 @@ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ...@@ -21,4 +21,4 @@ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 OTHER DEALINGS IN THE SOFTWARE. 22 OTHER DEALINGS IN THE SOFTWARE.
23 23
24 -For more information, please refer to <https://unlicense.org> 24 +For more information, please refer to <https://unlicense.org>
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -42,6 +42,20 @@ ...@@ -42,6 +42,20 @@
42 "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.7.tgz", 42 "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.7.tgz",
43 "integrity": "sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw==" 43 "integrity": "sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw=="
44 }, 44 },
45 + "@types/webidl-conversions": {
46 + "version": "6.1.1",
47 + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz",
48 + "integrity": "sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q=="
49 + },
50 + "@types/whatwg-url": {
51 + "version": "8.2.1",
52 + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.1.tgz",
53 + "integrity": "sha512-2YubE1sjj5ifxievI5Ge1sckb9k/Er66HyR2c+3+I6VDUUg1TLPdYYTEbQ+DjRkS4nTxMJhgWfSfMRD2sl2EYQ==",
54 + "requires": {
55 + "@types/node": "*",
56 + "@types/webidl-conversions": "*"
57 + }
58 + },
45 "@webassemblyjs/ast": { 59 "@webassemblyjs/ast": {
46 "version": "1.9.0", 60 "version": "1.9.0",
47 "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", 61 "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
...@@ -505,8 +519,7 @@ ...@@ -505,8 +519,7 @@
505 "base64-js": { 519 "base64-js": {
506 "version": "1.3.1", 520 "version": "1.3.1",
507 "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", 521 "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
508 - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", 522 + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
509 - "dev": true
510 }, 523 },
511 "base64id": { 524 "base64id": {
512 "version": "2.0.0", 525 "version": "2.0.0",
...@@ -776,6 +789,25 @@ ...@@ -776,6 +789,25 @@
776 "pako": "~1.0.5" 789 "pako": "~1.0.5"
777 } 790 }
778 }, 791 },
792 + "bson": {
793 + "version": "4.6.0",
794 + "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.0.tgz",
795 + "integrity": "sha512-8jw1NU1hglS+Da1jDOUYuNcBJ4cNHCFIqzlwoFNnsTOg2R/ox0aTYcTiBN4dzRa9q7Cvy6XErh3L8ReTEb9AQQ==",
796 + "requires": {
797 + "buffer": "^5.6.0"
798 + },
799 + "dependencies": {
800 + "buffer": {
801 + "version": "5.7.1",
802 + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
803 + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
804 + "requires": {
805 + "base64-js": "^1.3.1",
806 + "ieee754": "^1.1.13"
807 + }
808 + }
809 + }
810 + },
779 "buffer": { 811 "buffer": {
780 "version": "4.9.2", 812 "version": "4.9.2",
781 "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", 813 "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
...@@ -1375,6 +1407,11 @@ ...@@ -1375,6 +1407,11 @@
1375 } 1407 }
1376 } 1408 }
1377 }, 1409 },
1410 + "denque": {
1411 + "version": "2.0.1",
1412 + "resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz",
1413 + "integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ=="
1414 + },
1378 "depd": { 1415 "depd": {
1379 "version": "1.1.2", 1416 "version": "1.1.2",
1380 "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 1417 "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
...@@ -2326,8 +2363,7 @@ ...@@ -2326,8 +2363,7 @@
2326 "ieee754": { 2363 "ieee754": {
2327 "version": "1.1.13", 2364 "version": "1.1.13",
2328 "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", 2365 "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
2329 - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", 2366 + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
2330 - "dev": true
2331 }, 2367 },
2332 "iferr": { 2368 "iferr": {
2333 "version": "0.1.5", 2369 "version": "0.1.5",
...@@ -2796,6 +2832,12 @@ ...@@ -2796,6 +2832,12 @@
2796 "readable-stream": "^2.0.1" 2832 "readable-stream": "^2.0.1"
2797 } 2833 }
2798 }, 2834 },
2835 + "memory-pager": {
2836 + "version": "1.5.0",
2837 + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
2838 + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
2839 + "optional": true
2840 + },
2799 "merge-descriptors": { 2841 "merge-descriptors": {
2800 "version": "1.0.1", 2842 "version": "1.0.1",
2801 "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 2843 "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
...@@ -2939,6 +2981,26 @@ ...@@ -2939,6 +2981,26 @@
2939 "minimist": "^1.2.5" 2981 "minimist": "^1.2.5"
2940 } 2982 }
2941 }, 2983 },
2984 + "mongodb": {
2985 + "version": "4.2.0",
2986 + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.2.0.tgz",
2987 + "integrity": "sha512-lg3MJ9dAKxhogRnIB6/j63gfD7JryZwRC0nNzZ82RhENw4nCmscZVqRfOmNzTvSNndJx9ZhxZpm9JvnKuH/GTA==",
2988 + "requires": {
2989 + "bson": "^4.5.4",
2990 + "denque": "^2.0.1",
2991 + "mongodb-connection-string-url": "^2.2.0",
2992 + "saslprep": "^1.0.3"
2993 + }
2994 + },
2995 + "mongodb-connection-string-url": {
2996 + "version": "2.2.0",
2997 + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.2.0.tgz",
2998 + "integrity": "sha512-U0cDxLUrQrl7DZA828CA+o69EuWPWEJTwdMPozyd7cy/dbtncUZczMw7wRHcwMD7oKOn0NM2tF9jdf5FFVW9CA==",
2999 + "requires": {
3000 + "@types/whatwg-url": "^8.2.1",
3001 + "whatwg-url": "^11.0.0"
3002 + }
3003 + },
2942 "move-concurrently": { 3004 "move-concurrently": {
2943 "version": "1.0.1", 3005 "version": "1.0.1",
2944 "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", 3006 "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
...@@ -3557,8 +3619,7 @@ ...@@ -3557,8 +3619,7 @@
3557 "punycode": { 3619 "punycode": {
3558 "version": "2.1.1", 3620 "version": "2.1.1",
3559 "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 3621 "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
3560 - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 3622 + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
3561 - "dev": true
3562 }, 3623 },
3563 "pupa": { 3624 "pupa": {
3564 "version": "2.1.1", 3625 "version": "2.1.1",
...@@ -3816,6 +3877,15 @@ ...@@ -3816,6 +3877,15 @@
3816 "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 3877 "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
3817 "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 3878 "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
3818 }, 3879 },
3880 + "saslprep": {
3881 + "version": "1.0.3",
3882 + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
3883 + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
3884 + "optional": true,
3885 + "requires": {
3886 + "sparse-bitfield": "^3.0.3"
3887 + }
3888 + },
3819 "schema-utils": { 3889 "schema-utils": {
3820 "version": "2.6.5", 3890 "version": "2.6.5",
3821 "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.5.tgz", 3891 "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.5.tgz",
...@@ -4205,6 +4275,15 @@ ...@@ -4205,6 +4275,15 @@
4205 "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", 4275 "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
4206 "dev": true 4276 "dev": true
4207 }, 4277 },
4278 + "sparse-bitfield": {
4279 + "version": "3.0.3",
4280 + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
4281 + "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
4282 + "optional": true,
4283 + "requires": {
4284 + "memory-pager": "^1.0.2"
4285 + }
4286 + },
4208 "split-string": { 4287 "split-string": {
4209 "version": "3.1.0", 4288 "version": "3.1.0",
4210 "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", 4289 "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
...@@ -4501,6 +4580,14 @@ ...@@ -4501,6 +4580,14 @@
4501 "nopt": "~1.0.10" 4580 "nopt": "~1.0.10"
4502 } 4581 }
4503 }, 4582 },
4583 + "tr46": {
4584 + "version": "3.0.0",
4585 + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
4586 + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
4587 + "requires": {
4588 + "punycode": "^2.1.1"
4589 + }
4590 + },
4504 "tslib": { 4591 "tslib": {
4505 "version": "1.11.1", 4592 "version": "1.11.1",
4506 "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", 4593 "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
...@@ -4940,6 +5027,11 @@ ...@@ -4940,6 +5027,11 @@
4940 } 5027 }
4941 } 5028 }
4942 }, 5029 },
5030 + "webidl-conversions": {
5031 + "version": "7.0.0",
5032 + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
5033 + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g=="
5034 + },
4943 "webpack": { 5035 "webpack": {
4944 "version": "4.42.1", 5036 "version": "4.42.1",
4945 "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.42.1.tgz", 5037 "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.42.1.tgz",
...@@ -5092,6 +5184,15 @@ ...@@ -5092,6 +5184,15 @@
5092 "source-map": "~0.6.1" 5184 "source-map": "~0.6.1"
5093 } 5185 }
5094 }, 5186 },
5187 + "whatwg-url": {
5188 + "version": "11.0.0",
5189 + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz",
5190 + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
5191 + "requires": {
5192 + "tr46": "^3.0.0",
5193 + "webidl-conversions": "^7.0.0"
5194 + }
5195 + },
5095 "which": { 5196 "which": {
5096 "version": "2.0.2", 5197 "version": "2.0.2",
5097 "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 5198 "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
23 "dependencies": { 23 "dependencies": {
24 "express": "^4.17.1", 24 "express": "^4.17.1",
25 "jquery": "^3.6.0", 25 "jquery": "^3.6.0",
26 + "mongodb": "^4.2.0",
26 "nodemon": "^2.0.15", 27 "nodemon": "^2.0.15",
27 "socket.io": "^4.3.2", 28 "socket.io": "^4.3.2",
28 "socket.io-client": "^4.3.2" 29 "socket.io-client": "^4.3.2"
......
This diff could not be displayed because it is too large.
...@@ -5,29 +5,29 @@ const MongoClient = mongodb.MongoClient; ...@@ -5,29 +5,29 @@ const MongoClient = mongodb.MongoClient;
5 5
6 var app = express() 6 var app = express()
7 7
8 -const PORT = 1697; 8 +const PORT = 8484;
9 const url = 'mongodb://mongo:27017'; 9 const url = 'mongodb://mongo:27017';
10 var db; 10 var db;
11 app.use(express.urlencoded({ extended: true })); 11 app.use(express.urlencoded({ extended: true }));
12 12
13 app.use("/public", express.static('./public')); 13 app.use("/public", express.static('./public'));
14 14
15 +app.get('/festivalList', (req, res) => { // localhost:3000/festivalList 입력하면 list.ejs에 저장한 형식대로 정보 불러와짐
16 + //디비에 저장된 festivals 라는 collection안의 데이터(제목 또는 내용 등)를 꺼내기
17 + db.collection('festivals').find().toArray((err, rslt) => { //DB에서 데이터를 찾음 festivals라는 collection안의 데이터를 꺼내게 됨
18 + if (err) throw err;
19 + res.json(rslt); // 찾은 데이터를 json으로 전송
20 + });
21 +});
22 +
15 app.get("/*", (req, res) => { 23 app.get("/*", (req, res) => {
16 res.sendFile(path.join(__dirname, "./public/index.html")) 24 res.sendFile(path.join(__dirname, "./public/index.html"))
17 }) 25 })
18 26
19 -app.get('/festivalList', (req, res) => { // localhost:3000/festivalList 입력하면 list.ejs에 저장한 형식대로 정보 불러와짐
20 - //디비에 저장된 festivals 라는 collection안의 데이터(제목 또는 내용 등)를 꺼내기
21 - db.collection('festivals').find().toArray((err, rslt) => { //DB에서 데이터를 찾음 festivals라는 collection안의 데이터를 꺼내게 됨
22 - if (err) throw err;
23 - console.log(rslt);
24 - res.render('list.ejs', { posts: rslt }); // 찾은 데이터를 ejs 파일에 넣음
25 - });
26 -});
27 27
28 MongoClient.connect(url, (error, client) => { // 서버열때 url 사용 mongoDB와 연결시키기 28 MongoClient.connect(url, (error, client) => { // 서버열때 url 사용 mongoDB와 연결시키기
29 if (error) return console.log(error); 29 if (error) return console.log(error);
30 - db = client.db('myFirstDatabase'); 30 + db = client.db('test');
31 app.listen(PORT, () => { 31 app.listen(PORT, () => {
32 console.log(`Server lauched on port ${PORT}`); 32 console.log(`Server lauched on port ${PORT}`);
33 }); 33 });
......
...@@ -9,8 +9,14 @@ ...@@ -9,8 +9,14 @@
9 function LoadFestas() { 9 function LoadFestas() {
10 let url = "/festivalList"; 10 let url = "/festivalList";
11 jQuery.getJSON(url, (json) => { 11 jQuery.getJSON(url, (json) => {
12 - AllFestas.set(json.response.body.items.item); 12 + AllFestas.set(json);
13 + // console.log(json);
13 }); 14 });
15 + // let url = "http://api.visitkorea.or.kr/openapi/service/rest/KorService/areaBasedList?ServiceKey=2lFkvQJYgzOOhwUKiUt8aZVNpd1PpBOf%2FfMNW17cl25DE0GUEDddeR9iGnuSUpggjUoIUgamfhcvnKQ3eH1dAw%3D%3D&contentTypeId=15&areaCode=&sigunguCode=&cat1=&cat2=&cat3=&listYN=Y&MobileOS=ETC&MobileApp=TourAPI3.0_Guide&arrange=A&numOfRows=12&pageNo=1&_type=json";
16 + // jQuery.getJSON(url, (json) => {
17 + // AllFestas.set(json.response.body.items.item);
18 + // console.log(json.response.body.items.item);
19 + // });
14 } 20 }
15 </script> 21 </script>
16 22
......
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,7 @@
80 return function() { 80 return function() {
81 Festa = festa; 81 Festa = festa;
82 ShowInfo = true; 82 ShowInfo = true;
83 - console.log(Festa); 83 + // console.log(Festa);
84 } 84 }
85 }; 85 };
86 kakao.maps.event.addListener(marker, 'click', showInfo(data[i])); 86 kakao.maps.event.addListener(marker, 'click', showInfo(data[i]));
......
...@@ -23,9 +23,9 @@ ...@@ -23,9 +23,9 @@
23 23
24 let festaChecked = []; 24 let festaChecked = [];
25 $: festaList = $AllFestas.filter( v => { 25 $: festaList = $AllFestas.filter( v => {
26 - if(v.addr1) { 26 + if(v.addr) {
27 - let district = v.addr1.split(" ")[0]; 27 + let district = v.addr.split(" ")[0];
28 - let city = v.addr1.split(" ")[1]; 28 + let city = v.addr.split(" ")[1];
29 return ($District === "" || district === $District) && 29 return ($District === "" || district === $District) &&
30 ($City === "" || city === $City); 30 ($City === "" || city === $City);
31 } else { 31 } else {
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
33 } 33 }
34 }); 34 });
35 $: festaParsed = festaList.map( (v, i) => { 35 $: festaParsed = festaList.map( (v, i) => {
36 - return { "id" : i, "title" : v.title, "addr1" : v.addr1, "contentid" : v.contentid, "checked" : false } 36 + return { "id" : i, "title" : v.title, "addr" : v.addr, "contentid" : v.contentid, "checked" : false }
37 }); 37 });
38 $: if ($Changed) { 38 $: if ($Changed) {
39 let len = festaList.length >= 9 ? 9 : festaList.length; 39 let len = festaList.length >= 9 ? 9 : festaList.length;
...@@ -142,7 +142,7 @@ ...@@ -142,7 +142,7 @@
142 <div class="{festa.checked ? "selected" : "festa"}" 142 <div class="{festa.checked ? "selected" : "festa"}"
143 on:click={() => {check(festa.id)}}> 143 on:click={() => {check(festa.id)}}>
144 <div class="title">{festa.title}</div> 144 <div class="title">{festa.title}</div>
145 - <div class="addr"><img alt="pin" src="/public/map-pin.png"><div>{festa.addr1}</div></div> 145 + <div class="addr"><img alt="pin" src="/public/map-pin.png"><div>{festa.addr}</div></div>
146 </div> 146 </div>
147 {/each} 147 {/each}
148 {:else} 148 {:else}
......
1 +<script>
2 + import SideBar from "./SideBar.svelte"
3 +
4 + export let festa;
5 + export let sidebar_show = false;
6 + var side = "right";
7 + var weatherData, weathers;
8 +
9 + const WEATHERIMG = {
10 + "맑음" : "./public/sunny.png",
11 + "비" : "./public/rain.png",
12 + "비/눈" : "./public/rainsnow.png",
13 + "눈" : "./public/snow.png"
14 + }
15 +
16 + function hide() {
17 + if (window.scrollY > 400) {
18 + sidebar_show = false;
19 + }
20 + }
21 +
22 + $: if(festa.weathers) weatherData = JSON.parse(festa.weathers);
23 + $: if(festa.weathers) weathers = Array.from(Object.keys(weatherData)).map((v) => {
24 + return { "date" : v.slice(4), "temp" : weatherData[v].temp, "weather" : weatherData[v].weather };
25 + });
26 +
27 +</script>
28 +
29 +<style>
30 + .info {
31 + display: flex;
32 + flex-direction: column;
33 + align-items: center;
34 + }
35 +
36 + .title {
37 + font-size: 18pt;
38 + font-weight: bold;
39 + }
40 +
41 + .content {
42 + padding: 0.5rem 0.5rem 0.5rem;
43 + text-align: left;
44 + }
45 +
46 + .festaimg {
47 + max-width: 560px;
48 + }
49 +
50 + .locpin, .telpin, .calpin {
51 + width: 20px;
52 + height: 20px;
53 + }
54 +
55 + .weather {
56 + /* border: 1px solid #999999; */
57 + border-collapse: collapse;
58 + }
59 +
60 + .weather td {
61 + padding: 0.3rem;
62 + border: 1px solid #cccccc;
63 + }
64 +
65 + .weatherimg {
66 + width : 100px;
67 + }
68 +
69 +
70 +</style>
71 +
72 +<svelte:window on:scroll={hide}></svelte:window>
73 +<SideBar bind:show={sidebar_show} {side}>
74 + <div class="info">
75 + <div class="title">{festa.title}</div>
76 + <img class="festaimg" alt="festaimg" src={festa.firstimage}><br>
77 + {#if weathers}
78 + <table class="weather"><tr>
79 + {#each weathers as weather}
80 + <td class="weathercell">
81 + <img class="weatherimg" alt="weather" src={WEATHERIMG[weather.weather]}><br>
82 + {weather.date.slice(0, 2) + '/' + weather.date.slice(2, 4)}<br>
83 + {weather.temp}℃<br>
84 + </td>
85 + {/each}
86 + </tr></table>
87 + {/if}
88 + <div class="content">
89 + <img class="locpin" alt="pin" src="/public/map-pin.png"> 개최지 : {festa.addr}<br>
90 + <img class="telpin" alt="pin" src="/public/tel-pin.jpeg"> 전화번호 : {festa.tel}<br>
91 + <img class="calpin" alt="pin" src="/public/cal-pin.png"> 행사일 : {festa.eventstartdate} - {festa.eventenddate}<br>
92 + </div>
93 + </div>
94 +
95 +
96 +
97 +</SideBar>
This diff could not be displayed because it is too large.
1 -<script>
2 - import SideBar from "./SideBar.svelte"
3 -
4 - export let festa;
5 - export let sidebar_show = false;
6 - let side = "right";
7 -
8 - function hide() {
9 - if (window.scrollY > 400) {
10 - sidebar_show = false;
11 - }
12 - }
13 -</script>
14 -
15 -<style>
16 - .title {
17 - font-size: 18pt;
18 - font-weight: bold;
19 - text-align: center;
20 - }
21 -
22 - .content {
23 - padding: 0.5rem 0.5rem 0.5rem;
24 - text-align: center;
25 - }
26 -
27 - .info img {
28 - max-height: 20rem;
29 - }
30 -
31 -</style>
32 -
33 -<svelte:window on:scroll={hide}></svelte:window>
34 -<SideBar bind:show={sidebar_show} {side}>
35 - <div class="info">
36 - <div class="title">{festa.title}</div>
37 - <img alt="festaImg" src={festa.firstimage}><br>
38 - <div class="content">
39 - 개최지 : {festa.addr1}<br>
40 - 전화번호 : {festa.tel}<br>
41 - <!-- 행사 시작일 : {festa.startdate}<br>
42 - 행사 시작일 : {festa.enddate}<br>
43 - 날씨 : {festa.weather 어쩌구} -->
44 - </div>
45 - </div>
46 -
47 -
48 -
49 -</SideBar>
1 -<!DOCTYPE html>
2 -<html>
3 -
4 -<head>
5 - <meta charset="UTF-8">
6 - <meta http-equiv="X-UA-Compatible" content="IE=edge">
7 - <meta name="viewport" content="width=device-width, initial-scale=1.0">
8 - <title>Festival Information</title>
9 -</head>
10 -
11 -<body>
12 - <% for(let i=0; i < posts.length ; i++){ %>
13 - <h4>제목 : <%= posts[i].title %>
14 - </h4>
15 - <h4>주소 : <%= posts[i].addr %>
16 - </h4>
17 - <h4>전화번호 : <%= posts[i].tel %>
18 - </h4>
19 - <h4>mapx : <%= posts[i].mapx %>
20 - </h4>
21 - <h4>mapy : <%= posts[i].mapy %>
22 - </h4>
23 - <h4>갱신일 : <%= posts[i].updatedAt %>
24 - </h4>
25 - <h4> ------------------- </h4>
26 - <% } %>
27 -</body>
28 -
29 -</html>
...\ No newline at end of file ...\ No newline at end of file