From 5274a11d9fb9c511a3a9823e06424bb626a5a714 Mon Sep 17 00:00:00 2001 From: saehun Date: Sat, 29 Jun 2024 19:29:29 +0900 Subject: [PATCH] impl --- .../__fixtures__/search-retaurent-01.json | 142 + .../__fixtures__/search-retaurent-02.json | 142 + .../search-retaurent-detail-01.json | 2647 +++++++++++++++++ src/search/kakao-map.helper.ts | 62 + src/search/kakao-map.types.ts | 202 ++ src/search/search.controller.ts | 66 +- src/search/search.module.ts | 3 +- src/search/search.service.spec.ts | 191 +- src/search/search.service.ts | 132 +- src/utils/index.ts | 11 + 10 files changed, 3525 insertions(+), 73 deletions(-) create mode 100644 src/search/__fixtures__/search-retaurent-01.json create mode 100644 src/search/__fixtures__/search-retaurent-02.json create mode 100644 src/search/__fixtures__/search-retaurent-detail-01.json create mode 100644 src/search/kakao-map.helper.ts create mode 100644 src/search/kakao-map.types.ts create mode 100644 src/utils/index.ts diff --git a/src/search/__fixtures__/search-retaurent-01.json b/src/search/__fixtures__/search-retaurent-01.json new file mode 100644 index 0000000..34677ac --- /dev/null +++ b/src/search/__fixtures__/search-retaurent-01.json @@ -0,0 +1,142 @@ +[ + { + "scope": "https://dapi.kakao.com:443", + "method": "GET", + "path": "/v2/local/geo/transcoord.json?x=504945&y=1111188.125&input_coord=WCONGNAMUL&output_coord=WGS84", + "body": "", + "status": 200, + "response": "1f8b08000000000000030dc8410a80201005d0bbfcb5888de6a45789882877a98b2628c4bbd75bbe869c64436c902adbb9eef52e82387485a3ee774e452ec4b9e1f993581b22eb8371139327aff0225ad62e04b6ccd6d03406ea4bff001bb54c6f57000000", + "rawHeaders": [ + "Date", + "Sat, 29 Jun 2024 09:55:58 GMT", + "Content-Type", + "application/json;charset=UTF-8", + "Transfer-Encoding", + "chunked", + "Connection", + "keep-alive", + "Vary", + "Accept-Encoding", + "X-Request-Id", + "6e979bb14e53b77453cb97f9c60197bb", + "X-Call-Info", + "1092383|1694|122", + "Access-Control-Allow-Origin", + "*", + "Access-Control-Allow-Methods", + "GET, OPTIONS", + "Access-Control-Allow-Headers", + "Authorization, KA, Origin, X-Requested-With, Content-Type, Accept", + "Content-Encoding", + "gzip" + ], + "responseIsBinary": true + }, + { + "scope": "https://dapi.kakao.com:443", + "method": "GET", + "path": "/v2/local/geo/transcoord.json?x=506025&y=1111753.125&input_coord=WCONGNAMUL&output_coord=WGS84", + "body": "", + "status": 200, + "response": "1f8b08000000000000030dc8410a80201005d0bbfc75844eeaa45789083177a58b2628c4bbd75bbe86334b4468902af1d852bd8b20e83e60afe93e73910b616978fe241e1531594b863c39e306bc08138f566966f2cc7632b3ee6bff001590a7e657000000", + "rawHeaders": [ + "Date", + "Sat, 29 Jun 2024 09:55:58 GMT", + "Content-Type", + "application/json;charset=UTF-8", + "Transfer-Encoding", + "chunked", + "Connection", + "keep-alive", + "Vary", + "Accept-Encoding", + "X-Request-Id", + "383f680fdd844d24532ca10653bc09dc", + "X-Call-Info", + "1092383|1694|122", + "Access-Control-Allow-Origin", + "*", + "Access-Control-Allow-Methods", + "GET, OPTIONS", + "Access-Control-Allow-Headers", + "Authorization, KA, Origin, X-Requested-With, Content-Type, Accept", + "Content-Encoding", + "gzip" + ], + "responseIsBinary": true + }, + { + "scope": "https://dapi.kakao.com:443", + "method": "GET", + "path": "/v2/local/search/keyword.json?rect=127.02236904872626,37.49973773028592,127.02725524292646,37.50177297753481&query=%EA%B3%B1%EC%B0%BD&category_group_code=CE7", + "body": "", + "status": 200, + "response": { + "documents": [], + "meta": { + "is_end": true, + "pageable_count": 0, + "same_name": { + "keyword": "곱창", + "region": [], + "selected_region": "" + }, + "total_count": 0 + } + }, + "rawHeaders": [ + "Date", + "Sat, 29 Jun 2024 09:55:58 GMT", + "Content-Type", + "application/json; charset=utf-8", + "Content-Length", + "140", + "Connection", + "keep-alive", + "X-Request-Id", + "12ecb166fc7cdae81c5f8507411f6708", + "X-Call-Info", + "1092383|1695|122", + "Access-Control-Allow-Origin", + "*", + "Access-Control-Allow-Methods", + "GET, OPTIONS", + "Access-Control-Allow-Headers", + "Authorization, KA, Origin, X-Requested-With, Content-Type, Accept" + ], + "responseIsBinary": false + }, + { + "scope": "https://dapi.kakao.com:443", + "method": "GET", + "path": "/v2/local/search/keyword.json?rect=127.02236904872626,37.49973773028592,127.02725524292646,37.50177297753481&query=%EA%B3%B1%EC%B0%BD&category_group_code=FD6", + "body": "", + "status": 200, + "response": "1f8b0800000000000003d596dd6a1a4114c75f45e65acd7ceecc785dfa126d91ad3b18f163655d6983086df0226d52d240a54d30c580a95ea460485abce90bb99b77e859bfea6a0a51283457b3738efb3f67ce6fcf191bc87173f5b2a9f8359479d640b6e378a656cb56ecb2411914b63ae1d928112db707e31f57b3a7e0f83441185629ca5012e56cdfe45d6f2f9bf7dc7a359b739de8d5a74fac75df5cf6fc283c3c0fbb1f977fb1ea4b3caf63cc4ce2aedd01c37c17762e82cb2fc9f14d773c1ace8de39beb70f82b19f4dfc1029a4ea1e6db955c2407bb82032b611667d8c25c83a5baeb562227a629c1588a313cb196ec9c59a4d16fc179a7c20b5fdd2b816bd7f7ab999d9d89295db6abe9a25db4dd74ce2defc4a278aeed641f58d0a337c145478af168946012de7d1da54c651a53aeb0144a812a98f7c0cc645a60b031f04bac186a2637e646f063e14609e7586bb64e4d094d57a9051f3e4dc5c2f7bdc478d80ef607c1cd689af003112e05dc1ca0bc07a0c08c2922e1818a1842a5b9605253caf8560ce96361282d0a55159ac72132ae284c9049b9e2bdd76d073f5b41ab17f64ec2f6e934c2963897636fcb53c4793206c4a4c52861719e5862690168a5b6024ad563014a1415ca5272b529458a7362ad3565ffe0eef82a8a7c36dc78a0fe89b4393d16d1e3343e4eb91696e0dce2cbec0813025b5c4a4ab76ac57be8fca7e4081696a4122fa15b6bbfe9e15abdf1f530f8b6f91db814e241cc668d3d61664dae40b2c24c522284262cc60c0bac95e484926d90897f4f2c3ce886fd93c5eeb017ecdf4223845f2fa123c2e1e07e42826a26e5f4ac7f25f47610090d07b3da859fbf6f341497636c3914398b23d2984acdb4b6e26da5e0ea230a2668f34512958d6fa34c03156a595381b3fa5edd40ce76ded82f4b06ea5faff8286325510dd298e5d24045b3f7caf5a2d22cbe44cfe40b6e05feb08268cd944cce374e766e44f03920dff5edd242b1d9fc0d390aa1e8e80a0000", + "rawHeaders": [ + "Date", + "Sat, 29 Jun 2024 09:55:58 GMT", + "Content-Type", + "application/json; charset=utf-8", + "Transfer-Encoding", + "chunked", + "Connection", + "keep-alive", + "Vary", + "Accept-Encoding", + "X-Request-Id", + "904afae9b05f766a7c60d8e1f039cd1b", + "X-Call-Info", + "1092383|1695|122", + "Access-Control-Allow-Origin", + "*", + "Access-Control-Allow-Methods", + "GET, OPTIONS", + "Access-Control-Allow-Headers", + "Authorization, KA, Origin, X-Requested-With, Content-Type, Accept", + "Content-Encoding", + "gzip" + ], + "responseIsBinary": true + } +] diff --git a/src/search/__fixtures__/search-retaurent-02.json b/src/search/__fixtures__/search-retaurent-02.json new file mode 100644 index 0000000..24ca914 --- /dev/null +++ b/src/search/__fixtures__/search-retaurent-02.json @@ -0,0 +1,142 @@ +[ + { + "scope": "https://dapi.kakao.com:443", + "method": "GET", + "path": "/v2/local/geo/transcoord.json?x=504945&y=1111188.125&input_coord=WCONGNAMUL&output_coord=WGS84", + "body": "", + "status": 200, + "response": "1f8b08000000000000030dc8410a80201005d0bbfcb5888de6a45789882877a98b2628c4bbd75bbe869c64436c902adbb9eef52e82387485a3ee774e452ec4b9e1f993581b22eb8371139327aff0225ad62e04b6ccd6d03406ea4bff001bb54c6f57000000", + "rawHeaders": [ + "Date", + "Sat, 29 Jun 2024 09:57:18 GMT", + "Content-Type", + "application/json;charset=UTF-8", + "Transfer-Encoding", + "chunked", + "Connection", + "keep-alive", + "Vary", + "Accept-Encoding", + "X-Request-Id", + "bf755c00828965645282e784f5968f38", + "X-Call-Info", + "1092383|1694|122", + "Access-Control-Allow-Origin", + "*", + "Access-Control-Allow-Methods", + "GET, OPTIONS", + "Access-Control-Allow-Headers", + "Authorization, KA, Origin, X-Requested-With, Content-Type, Accept", + "Content-Encoding", + "gzip" + ], + "responseIsBinary": true + }, + { + "scope": "https://dapi.kakao.com:443", + "method": "GET", + "path": "/v2/local/geo/transcoord.json?x=506025&y=1111753.125&input_coord=WCONGNAMUL&output_coord=WGS84", + "body": "", + "status": 200, + "response": "1f8b08000000000000030dc8410a80201005d0bbfc75844eeaa45789083177a58b2628c4bbd75bbe86334b4468902af1d852bd8b20e83e60afe93e73910b616978fe241e1531594b863c39e306bc08138f566966f2cc7632b3ee6bff001590a7e657000000", + "rawHeaders": [ + "Date", + "Sat, 29 Jun 2024 09:57:18 GMT", + "Content-Type", + "application/json;charset=UTF-8", + "Transfer-Encoding", + "chunked", + "Connection", + "keep-alive", + "Vary", + "Accept-Encoding", + "X-Request-Id", + "8fa86494005fe254c3737bcbfaea8ab0", + "X-Call-Info", + "1092383|1694|122", + "Access-Control-Allow-Origin", + "*", + "Access-Control-Allow-Methods", + "GET, OPTIONS", + "Access-Control-Allow-Headers", + "Authorization, KA, Origin, X-Requested-With, Content-Type, Accept", + "Content-Encoding", + "gzip" + ], + "responseIsBinary": true + }, + { + "scope": "https://dapi.kakao.com:443", + "method": "GET", + "path": "/v2/local/search/keyword.json?rect=127.02236904872626,37.49973773028592,127.02725524292646,37.50177297753481&query=%ED%99%9C%EC%96%B4%ED%9A%8C&category_group_code=FD6", + "body": "", + "status": 200, + "response": "1f8b0800000000000003dd98ed6e1a4714866f05ed6fd69eef99c3efaa379156680b5bc732060bb05acbb294102772654b71d4103b2944447193547254ab261595a87a3fec720f3d0bfed8018c609322d43f7cccc09cdd7de63de73db3ebe44bb9ed4dbf58ad38997bbb8e97cf97fd4a255bf4367d27e384fb8df0552715bdb50f7a9fceaf3e054f5fa62827c6a5c4493b39afeaaf95ca3bd9b572697b2b9b2be5a3bf7efd951a9fbb5eb679141e36c3d671fc17a373a96fb609e17eaa5f6fe0c0edb77670de4d878f9ae17eeb66f0d511ae945faf54bd622e5a04bfade7f19d1a2138658c4b1cd9ba5f2a5e4d6e15bc9c7f1d31787f14fe721c1e9c86b58b9bb9ed7201a7ee57ab5b99d5d5c1d0caa6b7b5b2e16d78a5955c6973d55aba5cf2f2d9199fddd183e04d43eb5ea793e21afffb63749d4caf102629139c3102d193dbc161ae572421000498e242397be9f90989ff9e50d8ecc60845d12f7e4d076fce2633d1446945a4861812c25c09cc1560cc289db0f9a0ffe2a7dee58754efa21ed43e84271f87973523a778b8f931c901263182491ba1a410d2c2243533c210c19260920ba074d00adf3f8b310b2e3bd12fde76870b4c948fc1edc8994d4a81642ee0ce1f47f52cac778387dde0e97ef0ee7c1e2dddc449a824c12d440294a20c19e93822ca8d16d124d1f333d22e35cb0a491a2a08552382e2dcc5a7304150edf0f571f8571b59a57a979f7a17c709a565459e09dc30ce109c1a686b240372cea8324a524b5a4ca3b6248b0225d0d60232e0e7d428c51868dc9963f950baa0051bc3f7b61bd44ee7ad56f1204925266d89194cac5469664b4c728db74b04f029a886db601006b75cad1ba152149656611c08d112f3de082245dd68738e21fae36370d88e74f6e8615269c5434e0176fb24fb8f8ffa2767c1eb08181df062162f4d05056a9812122c629453c21570a009b2a271d9c2fdc5e01b32bc03960443158055b5c62c1f2ae8e438fcfbf91c44e2eb263412a31292dae00b9a3bb04524144183c189623291e75b04936932ba193e6c60069ccc4948c685617a9a33bff9ff8c8ce26b26b5e43622c9349798d314fa06ab24a103d41ca78024433401c3321525a3d1316b0a62b428816bb0f31907d5c2553160ffb41eb61ac1cf67b3438b874a6822a89dea840666b00881a0762735e00608804cab4e77a7ba05404b509ef076b4510a4c9c958c0cab20ca65d8404e487fc1e34ebf7e8a1f6607158f33bfbaf8849a24b0e86346d5562345d15428060a442248cb7e240146600dd63066f7c0c52a3c6ef75eb4c3da79f86723384d6ad3e311bfd44185324208f4e91638ec7d193a5660898c04a54ba9ae416f2a8726efae328580fe6905cd2e7ab0c8f59d3cbfce51b8fa9c0dd575aca447156a0414054d8012cb5f10cd901460f14a7056018b38abf81c8109accc10b9aaf1765872316ed6073717ee777add73f41b73988d589c84e950123b1d125429d5c65615b6c31a1d221a91ff51cda28247a79a8c9b29bac29b082e7e433f1159fe41c39bb49b8a47fb42a58b73cd09e7dc76eed1112005226832584bc90a04b63dd890906929b0deedd7cefa4f5ac13b6c459f44c930f8bd33478d8ac5f852cd157a08865642d8ad15302c548a6ae5ec7d9b7636fdaae764769df54ad62fe2cd7eef152a3e5eb5b7e67bdf157c7cfcdbc5aa93a13aed54f04aae2e67d7d9f0777e2895a3a7d37fd9c01a3dcc46657f6dbd547432f770e58a5ff073553f9fbd1e74704738d552d52bdcaebab7f72f325b4f5681190000", + "rawHeaders": [ + "Date", + "Sat, 29 Jun 2024 09:57:18 GMT", + "Content-Type", + "application/json; charset=utf-8", + "Transfer-Encoding", + "chunked", + "Connection", + "keep-alive", + "Vary", + "Accept-Encoding", + "X-Request-Id", + "08bbc74e6cea8a2d7f3e557aeb61ec03", + "X-Call-Info", + "1092383|1695|122", + "Access-Control-Allow-Origin", + "*", + "Access-Control-Allow-Methods", + "GET, OPTIONS", + "Access-Control-Allow-Headers", + "Authorization, KA, Origin, X-Requested-With, Content-Type, Accept", + "Content-Encoding", + "gzip" + ], + "responseIsBinary": true + }, + { + "scope": "https://dapi.kakao.com:443", + "method": "GET", + "path": "/v2/local/search/keyword.json?rect=127.02236904872626,37.49973773028592,127.02725524292646,37.50177297753481&query=%ED%99%9C%EC%96%B4%ED%9A%8C&category_group_code=CE7", + "body": "", + "status": 200, + "response": { + "documents": [], + "meta": { + "is_end": true, + "pageable_count": 0, + "same_name": { + "keyword": "활어회", + "region": [], + "selected_region": "" + }, + "total_count": 0 + } + }, + "rawHeaders": [ + "Date", + "Sat, 29 Jun 2024 09:57:18 GMT", + "Content-Type", + "application/json; charset=utf-8", + "Content-Length", + "143", + "Connection", + "keep-alive", + "X-Request-Id", + "2d938aca4332c9410d346c3c59dda2c2", + "X-Call-Info", + "1092383|1695|122", + "Access-Control-Allow-Origin", + "*", + "Access-Control-Allow-Methods", + "GET, OPTIONS", + "Access-Control-Allow-Headers", + "Authorization, KA, Origin, X-Requested-With, Content-Type, Accept" + ], + "responseIsBinary": false + } +] diff --git a/src/search/__fixtures__/search-retaurent-detail-01.json b/src/search/__fixtures__/search-retaurent-detail-01.json new file mode 100644 index 0000000..90dc1a2 --- /dev/null +++ b/src/search/__fixtures__/search-retaurent-detail-01.json @@ -0,0 +1,2647 @@ +[ + { + "scope": "https://place.map.kakao.com:443", + "method": "GET", + "path": "/m/main/v/762214594", + "body": "", + "status": 200, + "response": { + "isMapUser": "ERROR", + "isExist": true, + "basicInfo": { + "cid": 762214594, + "placenamefull": "정분네중앙곱창 강남본점", + "mainphotourl": "http://t1.daumcdn.net/place/6DCE4A7D51924FE3A4437B8C91C553D4", + "phonenum": "02-3482-2337", + "address": { + "newaddr": { + "newaddrfull": "서초대로77길 35", + "bsizonno": "06612" + }, + "region": { + "name3": "서초동", + "fullname": "서울 서초구 서초동", + "newaddrfullname": "서울 서초구" + }, + "addrbunho": "1308-12", + "addrdetail": "1층" + }, + "wpointx": 505600, + "wpointy": 1111485, + "roadview": { + "panoid": 1171334557, + "tilt": 0, + "pan": 223.363, + "wphotox": 505617, + "wphotoy": 1111503, + "rvlevel": 2 + }, + "category": { + "cateid": "727", + "catename": "곱창,막창", + "cate1name": "음식점", + "fullCateIds": "9|124|18165|727" + }, + "feedback": { + "allphotocnt": 335, + "blogrvwcnt": 38, + "comntcnt": 14, + "scoresum": 32, + "scorecnt": 14, + "reviewphotocnt": 1 + }, + "openHour": { + "periodList": [ + { + "periodName": "영업기간", + "timeList": [ + { + "timeName": "영업시간", + "timeSE": "16:00 ~ 05:00", + "dayOfWeek": "매일" + } + ] + } + ], + "realtime": { + "holiday": "N", + "breaktime": "N", + "open": "Y", + "moreOpenOffInfoExists": "N", + "datetime": "20240629190601", + "currentPeriod": { + "periodName": "영업기간", + "timeList": [ + { + "timeName": "영업시간", + "timeSE": "16:00 ~ 05:00", + "dayOfWeek": "매일" + } + ] + }, + "closedToday": "N" + } + }, + "payments": [ + { + "imgUrl": "https://t1.kakaocdn.net/kakaomap_mobile/android/ico_zeropay.png", + "landingUrl": "https://www.zeropay.or.kr" + } + ], + "tags": ["노포", "제로페이"], + "source": { + "date": "2024.01.26." + }, + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "isStation": false + }, + "blogReview": { + "placenamefull": "정분네중앙곱창 강남본점", + "blogrvwcnt": 38, + "list": [ + { + "blogname": "Hola-ah", + "blogurl": "http://blog.naver.com/lee_ah10", + "contents": "정분네중앙곱창 강남본점 강남역 곱이 가득한 곱창맛집 요즘 곱창이 너무 땡겨서 노래를 부르고 다녔는데 드디어 먹었답니당 ㅎㅎㅎ✌?✌? 강남 근방에서 일하는 친구들 만나서 오랜만에 같이 저녁 먹었어요 ? 정분네중앙곱창 강남본점 서울특별시 서초구 서초대로77길 35 영업시간 월~토 15:30-05:00 일 15:30-02:00 양념막창도 엄청 많이들 드시더라구요!! 고민 했지만 소곱창으로 주문했어요 ? 소곱창모듬 2인분 46,000원 소곱창구이 1인분 21,000원 볶음밥 1인분 3,000원 초벌이 되어 나옵니다! (그래서 그런지 조금 오래 기다렸어요?) 배고픔에 이성 잃을뻥,,했지만 살짝만 더 익혀서 바로 먹으면 되서 좋았어요ㅎ휴 비주얼 미쳤죠 여기 곱창이 진짜 통통하고 냄새도 안나고 곱이 가득 들어있", + "outlink": "http://blog.naver.com/lee_ah10/223481056509", + "date": "2024.06.16.", + "reviewid": "64080430", + "title": "[강남] 강남역 곱창맛집 ‘왕십리 정분네 중앙곱창’", + "photoList": [ + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDA2MTJfNzQg/MDAxNzE4MTQ3ODA5OTMw.zeLbX5XZ9nkUSuo38EpVkuEo7IXMWg9C4lIWASeTVB0g.q2QQTpKvHlOMQQk9osA0wYHWd2_qy6u0wiaWi1YlqNIg.JPEG/IMG_0736.jpg?type=w773" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDA2MTJfMTYz/MDAxNzE4MTQ3ODEwNDYx.9jbrAdZUrbm3BVcHFYaL-Bk9h_r2Xo6ihtey3SoEbkog.CMUZEwzFLuR8xAd3c8n0RhfIXNF8GMoDUpUlRt4iM9cg.JPEG/IMG_0733.jpg?type=w386" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDA2MTJfMjYx/MDAxNzE4MTQ3ODEwNTg0.m2Fx82ajhf4NgnEc4vr2K1AVBfxP8ngJqSEv6Dl-WvMg.XCJrEYl5bM2tL0n0O-X6a7g_ljwdLuUuWX2GWpfCP1Eg.JPEG/IMG_0734.jpg?type=w386" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDA2MTJfNSAg/MDAxNzE4MTQ3ODEwMDk5.voYlL89jdBC-KJcOJvlxnw50Z1PhXnvFzVGiGTvJ7uog.9YamtqTDoKSllY7O1oFp79OITlxJikpQ331VWhSSi40g.JPEG/IMG_0737.jpg?type=w773" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDA2MTJfODkg/MDAxNzE4MTQ3ODEwNDY0.AiFcsRwxG3jmRyPMphZp_L9fc7VsTL4geTCNyCtTTO0g.rFLDw3vZAnsH2SZvXFSFgERxqFsB1BqbpZGZowiBVgsg.JPEG/IMG_0740.jpg?type=w773" + } + ], + "isMy": false + }, + { + "blogname": "현재올림", + "blogurl": "http://blog.naver.com/hyunjae_-", + "contents": "#내돈내산 #솔직후기 #강남맛집 #신논현역맛집 #강남막창맛집 #왕십리정분네중앙곱창 #정분네중앙곱창 #정분네중앙곱창강남본점 #강남역곱창볶음 #강남역맛집 #소금구이막창 #순대곱창볶음 #야곱 . . . 어쩌다 보니 야근이 일상인 요즘, 배가 너무 고파서 저녁 먹으러 나왔고 저녁 약속도 취소되고 아쉬운 마음에 댈이님이랑 맛난 걸 먹으러 가기로 했네요. 정분네중앙곱창 강남본점 서울특별시 서초구 서초대로77길 35 출퇴근길에 매번 눈길이 갔던 정분네중앙곱창 강남본점을 방문했고 약간 2차로 오기 좋은 너낌인데 평일 저녁시간인지라 사람이 많이 없어서 고민 없이 바로 입장해 줬네요. 내부는 넓은 편은 아니지만 2층에도 자리가 있고 나름 알차고롱 자리가 마련되어 있던. 돼지곱창, 돼지 막창, 소 곱창, 삼겹살 등 염통에 껍데", + "outlink": "http://blog.naver.com/hyunjae_-/223476364164", + "date": "2024.06.11.", + "reviewid": "63782962", + "title": "[신논현역/강남 맛집] 곱창볶음•막창 맛집, “정분네중앙곱창 강남본점” 솔직후기", + "photoList": [ + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDA2MTFfMzMg/MDAxNzE4MTA3OTM2NTcy.eVbfZxXq7xzi2yCnTK4v_sxdDFw4RT59GqDJn5g3Idwg.kKOLACm-svcFzV5xeR6Gd873Oc4OpS6xSoFggOiYjuIg.JPEG/output_1117231311.jpg?type=w386" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDA2MTFfMTMz/MDAxNzE4MTE0MTUyOTIx.FXVg0EY2Mnt4cRR8gZejSjiZhf6WKC1BGfG45bNsp2kg.MHm3rvkyINkd4DlUcOP4wQ2w8cc7WzhRcyjYuY39UqQg.JPEG/IMG_1050.jpg?type=w773" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDA2MTFfMjg3/MDAxNzE4MTA3OTM2OTA4.RFjv-GEcP0Ap8EvU_jwynX9zwmzOzJ3TWvaA5CDfcBMg._Ac81mu0DzXSczG870whuCA-i-pqt84t738DVFRmrM4g.JPEG/output_12558760.jpg?type=w773" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDA2MTFfMjA1/MDAxNzE4MTA3OTM1Mzgz.XVT9p3HA60oGRvXJpYvRHA69g5eT-YrDOTgNgBH74Gsg.z3NIhJJROJVmhL4GgsVRQHOw9cCbp1zBD_qlsUSif7Eg.JPEG/output_1003421442.jpg?type=w773" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDA2MTFfMTk4/MDAxNzE4MTA3OTM2Mjk3.CE46tjlObdObltvJ_3m3ah0lsrfwnk3N1Vbk7uJ9wW4g.I_wvdqOIkkTJzesLmNUb286bQ0VO60eT_ITVB1xaUcYg.JPEG/output_3373080855.jpg?type=w773" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDA2MTFfMTM4/MDAxNzE4MTA3OTM3MjM4.vZlnYhOjkOp3I2w1emwAMmzpPPtrRNESrHH45x84-Qog.yLJthijngd_KxXyoGYdfK2zkbiZ3c5l1s55VzXEFtC8g.JPEG/output_119321672.jpg?type=w773" + }, + { + "orgurl": "https://storep-phinf.pstatic.net/ogq_603f1989ec94a/original_14.png?type=p100_100" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDA2MTFfODQg/MDAxNzE4MTA3OTM2NjE2.mxV6BawJ_jPAvXxQ4yI4EPucx4l1OE_Pyb9GN1snBEwg.y4OfP2eZ4v_aJIjXo6FJu3WOtnWfW0qMmzDtPJDzvDwg.JPEG/output_155347460.jpg?type=w773" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDA2MTFfNjIg/MDAxNzE4MTA3OTM2MTkz.aOwaD6u0L-eNO0HRLu9odX8XrbVnJRECmqQ522uPWZQg.3d53rJYamFKu05wRmlUhcODDGFrBLGY8qWldTd_IWV8g.JPEG/output_1918516516.jpg?type=w386" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDA2MTFfOTMg/MDAxNzE4MTA3OTM1MDAw.uwfNGatI3ddgmdTZjrcNvcRDVECveZNYBgzT8_XZHo8g.8tJCoBpa_PqdYDICN7Uupvaj2iTPj0M_cdX1DlWAFOQg.JPEG/output_1237732777.jpg?type=w386" + } + ], + "isMy": false + }, + { + "blogname": "새땅지마", + "blogurl": "http://blog.naver.com/matilddang", + "contents": "강남에서 곱창이 땡길 때, 강남역 곱창맛집 정분네중앙곱창 강남본점 ?정분네중앙곱창 강남본점 서울 서초구 서초대로77길 35 영업시간 15:30 - 05:00 전화번호 02-3482-2337 남/녀 화장실 구분, 포장, 단체 이용 가능, 배달, 예약 ✔️3번의 초벌구이를 한다고 해요 ✔️26년 전통이 있는 집이라고 해요 간만에 (?) 야채곱창이 떙겨서! 회사 끝나고 회사칭구들이랑 함께 방문한 곳!! 강남역에서 야채곱창집 찾으려니 은근 많지가 않았다 그러다가 졍이의 폭풍검색으로 찾아온 이 곳 정분네중앙곱창 강남본점! 26년 전통의 곱창집이라고 한다!! 강남 마니 싸돌아 다녔는데 왜 여태껏 못가봤징? ㅎㅁㅎ왕십리에서 이사를 오신건가..? 메뉴판 및 기본반찬 돼지 막창/곱창도 있고 소곱창 종류도 있다!", + "outlink": "http://blog.naver.com/matilddang/223397946563", + "date": "2024.03.28.", + "reviewid": "58272972", + "title": "[왕십리정분네중앙곱창] - 강남역 야채곱창맛집. 강남에서 곱창이 땡길때 정분네중앙곱창 강남본점", + "photoList": [ + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjhfMjkx/MDAxNzExNTg5NzAyMzA5.sxCUpWRquMXxlMeLnfRvA2fqGdjvu4YQTqo37zs7qKgg.g0CV1JN7vFo-ed-rmR80PhR0GYcVta1zN1jAhDPFa8Mg.JPEG/SE-30D39568-03DF-486B-B1C8-64819E9997FD.jpg?type=w966" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjhfMTEx/MDAxNzExNTg5ODg5NjYz.N9ZHm5yWckuGdeEaYD6XXI9K3mJvIlliBuKwqJPngC8g.abNxzQneazHIp3jvBIYaEUei9xaJl1nv3yEApb26xB4g.JPEG/SE-73D9F913-B14F-4606-B8DC-9E1299154F05.jpg?type=w466" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjhfNDgg/MDAxNzExNTg5Nzc0MzQ4.IPWqlaQad0B8JUD-hl6_XGtQBgM0gBlbJ-zyTP6MWbwg.CuFz_ZbTsUR_BIYR_Ei2GHKR2ADYytVoSw-2DT4-accg.JPEG/SE-CE68910D-CAEC-482D-9775-1F51754DB12E.jpg?type=w466" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjhfMzQg/MDAxNzExNTg5NzMzODAy.yJq4rrmmdAlw1Nwsj7eYJVQQNie_Cte7Kxh5994r4isg._AaZSwMGXCx-LAQAlHlDxc8Eqz5CewOvlyCS-ZF4DCwg.JPEG/SE-A0E0CC9E-24D7-4BFB-9B7C-64A6D93ADFFE.jpg?type=w966" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMTlfMjEz/MDAxNzEwODA4NTQzMTg1.Gf_TfGTrYRa1jj4dMXbFtjPfo90mlQ-8940PVioL3NQg.VMXFG3DjbChdkA1ECwt7XXngl2uknH7HH7q30vmLs0Ag.JPEG/IMG_0693.jpg?type=w966" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjhfNDgg/MDAxNzExNTg5Nzc0MzQ4.IPWqlaQad0B8JUD-hl6_XGtQBgM0gBlbJ-zyTP6MWbwg.CuFz_ZbTsUR_BIYR_Ei2GHKR2ADYytVoSw-2DT4-accg.JPEG/SE-CE68910D-CAEC-482D-9775-1F51754DB12E.jpg?type=w966" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjhfMTE4/MDAxNzExNTg5Nzk5NDA5.DaZYC86i85QBfDNp0rNnF7F7Uc_kaLiPRs0MYvl0K3Ig.VlLyTDxwI9vVKrD76_WMO5xVUaWq8lvov6NCj5HQA2og.JPEG/SE-09B45F00-E4F5-4331-9D0A-9C4DC7888382.jpg?type=w966" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjhfMTM5/MDAxNzExNTg5ODQ5MjU2.u6Rn16nb_jKYm3cxo-5afZBzPrhlqwwAK9aMTLl_E0Ug.H7ScXqRcdGjvZrSy0lX_0h16gVTKqe7PH1R-BQJuwJwg.JPEG/SE-04A756C4-4733-457D-994B-2DA95647ED3F.jpg?type=w966" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjhfMjA4/MDAxNzExNTg5ODczNDMz.ghqlytBVDxD-Z4CF8civShjDVkS4Da0m2RIhvmVgK1Ug.N4uIDb4plY7ncvXqcbbnP8eS4kNXN73z4f-Crd62lGcg.JPEG/SE-37B206E4-531F-44A9-9B42-5F57A40EC925.jpg?type=w966" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjhfMTEx/MDAxNzExNTg5ODg5NjYz.N9ZHm5yWckuGdeEaYD6XXI9K3mJvIlliBuKwqJPngC8g.abNxzQneazHIp3jvBIYaEUei9xaJl1nv3yEApb26xB4g.JPEG/SE-73D9F913-B14F-4606-B8DC-9E1299154F05.jpg?type=w966" + } + ], + "isMy": false + }, + { + "blogname": "RA", + "blogurl": "http://blog.naver.com/daily_choi", + "contents": "이제 이사가면 강남에서 만나는 일 거의 없지 않을까? 어쨌든 오랜만에 용혜림 모였다.! 소리미 생일쯤 집들이 하자고 하면서 그 전에 셋이 만날 일 없을듯! 했는데 어쩌다 보니 만나게 되었다. 사실 내가 만나자고 했다. 요즘 일주일에 한 번 정도만 술 먹어서 그런가 한 번 먹을 때 엄청 많이 먹는 듯 크크. 어제도 과음했다 크윽. #곱창 #강남역곱창 #정분네중앙곱창 #강남곱창 #강남친구모임 정분네중앙곱창 강남본점 서울특별시 서초구 서초대로77길 35 10번 출구에서 쭉 들어가면 된다. 인생네컷 많고 .. 그쯤에 있는 골목! 곱창볶음 3인분, 염통구이 시킴. 계란찜 먹고 싶다고 496번 말했는데 안 들어주더라구.. 볶음밥도 먹고 싶었다. 3명이 앉기엔 살짝 비좁음. ㅠㅠ 기본 반찬~! 당면 개 맛도리. 헠헠", + "outlink": "http://blog.naver.com/daily_choi/223389185070", + "date": "2024.03.20.", + "reviewid": "57655858", + "title": "[서울/강남역/신논현역] 돼지곱창에 소맥 잘 들어간다! '왕십리정분네중앙곱창'", + "photoList": [ + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjBfMTEg/MDAxNzEwODk0NDUwMDE1.eRZxI4HeT8VCx6_kFdlmBQ9IvwzkHWguSolzrGN9_jUg.8a5NYb47_CEWMEivmaTXolBI0B2jE0rNTzYMBwXY4ZYg.JPEG/SE-C0D71494-DB54-4CA4-978F-C2CFF6D441E2.jpg?type=w966" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjBfMjc3/MDAxNzEwODkyOTk4NDY5.iZ_TrGJ5nXPW2uzPVRkhM0f_tBM2Fc_t5eI7-Wvu-oAg.Re0UIfUSjcj29FCGOgCsGO6AjC_sKTNTqurIi3hbqrkg.JPEG/IMG_3360.JPG?type=w966" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjBfMzYg/MDAxNzEwODkzMDAyMjMy.eQOGE2ChOUcdEHJgx4_H00JqV4zBF6nkQwY8-GmriNgg.WuvRixRCndoN68-wsEoNVHUDqmoAKHebW1DPpPCXnQ0g.JPEG/IMG_3361.JPG?type=w966" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjBfMTgy/MDAxNzEwODkzMDAzMTk4.papQSILlopQOlGyQL35Nui1ENqsL-f3KoLJHzzyLJsEg.sQEe09lw7Jv4SrE7P-I1NpH5PhelZX3MXctLiCSwXTcg.JPEG/IMG_3362.JPG?type=w966" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjBfMTQx/MDAxNzEwODkyOTk0MDg4.rTqnPEdPDG27U9E0V_HwrzO9LmKjFHdJJYSzGadBeeQg.zx70x4gjnVk0SMEnxTsUrzgghTMDme6XdCFrhHJ_8fog.JPEG/IMG_3363.JPG?type=w966" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjBfMjY0/MDAxNzEwODkyOTk2NjY4.9l7LuwnqgbG9oyz-MwyGCoSn0XHx54GC-kEDKuv_Y3cg.nzsROy_6PV04E2LpXpISGRi6i5YhBi6QNozX6FCpJoog.JPEG/IMG_3366.JPG?type=w966" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjBfMTk0/MDAxNzEwODkzMDAxNjcx.jdkwBV91gwuqk3GyvNiz8mHwzy6FJOR3HCdUT_eUWUcg.3O7mb7iIGBElE-9r_Nc4b_e5Y8RpAqcXk6kgDuZ6X0Eg.JPEG/IMG_3367.JPG?type=w966" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjBfMTY0/MDAxNzEwODkyOTk5OTQ5.cQZISscdA9-2uPZ7japjAymzZT8gVl_Wpn5vpZwEpzUg.QEKXwTimN3dRIRwwAWhL0wgVl8vH4pln5obOl6QpLRkg.JPEG/IMG_3370.JPG?type=w966" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjBfMTcz/MDAxNzEwODkzMDAwMDI5.gVQMXSwFx-Q7QIAoEOqQNXkEIFdbrLzufmPwNJPZEjcg.A_62OQVd48KXH0cEs4RZkABDLEXhQelS5q5H5vs8y9Ig.JPEG/IMG_3368.JPG?type=w966" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjBfNTUg/MDAxNzEwODkzMDAzMzkw.f6GXv73Sk18Vs_kGDt_WOlQ82H4okFeg59qPWkakPGwg.f29iEiKZ_dcGKn_hf2PuyqS93LxJpCU96TwOQjlVHaIg.JPEG/IMG_3369.JPG?type=w966" + } + ], + "isMy": false + }, + { + "blogname": "율슐랭 가이드", + "blogurl": "http://blog.naver.com/playyul", + "contents": "주차 불가능 영업시간 : 월 화 수 목 금 토 15:30 - 05:00 일 15:30 - 02:00 전화번호 : 02-3482-2337 강남역에 위치한 24년 전통의 강남역 원조 곱창 & 막창 맛집 3번의 초벌구이로 냄새 없이 맛있는 곱창이랑 막창을 푸짐하게 즐길 수 있는 곳 메인 거리에서 제일 눈에 띄며 접근성이 굉장히 좋다 배도 부르고 2차로 어디 갈까 하다가 자리가 있길래 바로 들어옴 Since 1998이라니 무려 26년째 운영 중 매장은 꽤 넓고 복층구조로 되어있다 역시 소주를 부르는 안주라 다들 꽤나 거하게 한 잔씩 하는 분위기 복층으로 올라가면 다락방 같은 공간이 나오는데 분위기는 편할 것 같으나 난 좌식을 못하기에 패스 메뉴판 돼지막창, 곱창 구이양념막창 14,0 소금구", + "outlink": "http://blog.naver.com/playyul/223338827485", + "date": "2024.01.30.", + "reviewid": "54050726", + "title": "왕십리정분네중앙곱창 강남본점 : 강남역 술집 26년 된 돼지곱창볶음 맛집", + "photoList": [ + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAxMzBfMjcy/MDAxNzA2NjEzMjc3NTk3.ib1o16dmIQho_fOEjTgwvItEiskNVwzApnzasJh_vnYg.Q763JctNv1jnvxYU6EHIOOfJibtkWi2qzUNJ9J32_Rcg.JPEG.playyul/IMG_3908.JPG?type=w773" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAxMzBfMTky/MDAxNzA2NjEzMjc3MDk0.6dnWmNIlbcN0FYvX0heUf0XHEoNulsGgId9S-CaAAY8g.1Drx-Axt68Ofp0VxTmvX1sGyTpdVYCCmgtyBjATNwjog.JPEG.playyul/IMG_3909.JPG?type=w773" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAxMzBfMTUg/MDAxNzA2NjE5MTkzODgz.dWmlIgusXWJgPP7HJptkyQDx5Wz2ENkvKW0RPmu5sGgg.lHcXRTZuazI1SdOyVsC9fIZPP3NsbMzAC8hO2NAluEQg.JPEG.playyul/output_1920464245.jpg?type=w773" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAxMzBfNzQg/MDAxNzA2NjE1MDMzMTU0.PnuVZDfzFRE82JCv16eGa0r3d_tjFZ654iaaUTIfGmEg.tUGuybaLdGYOWz20W1yfbMio2_grLo6pG9wZXfZxH8og.JPEG.playyul/output_127044140.jpg?type=w773" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAxMzBfMTU1/MDAxNzA2NjEzMjc3NTMw.YvD0c95s9P0GaSPYdkFPSZglGeg2nnI2eWukLrKjNXog.RdUsjmQaL9j9HAJ7h9-shmt55n10g1gH0u7GE8NHkN4g.JPEG.playyul/IMG_3915.JPG?type=w773" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAxMzBfMTMw/MDAxNzA2NjEzMjc1ODc1.xkzukGfyZwEnP_ECJP06fgXjLUreUUURCfKspQWX8XIg.zSCl0ZgbiKlfiEk5zqIRS9e-2W60l07Vnz3fuc52daAg.JPEG.playyul/IMG_3916.JPG?type=w773" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAxMzBfMTk4/MDAxNzA2NjEzMjc2Njc4.Sh4QrGnzYfTqUpE7ybTxwCeUQyosOPGNAqpLEQmpqEgg.tnlwVL1dY_J992WbNMkWC4RUUqPc0QtOLWWCovEsq9gg.JPEG.playyul/IMG_3920.JPG?type=w773" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAxMzBfMjg0/MDAxNzA2NjEzMjc2ODU0.MObE5hztAumwNDIMZ6CW16vz81vhtl2ELgw8scSQBn0g.Zui7F5CXKLEaYAtzaSZRbzco-ENBuIRZWRMQg5KM4Kkg.JPEG.playyul/IMG_3922.JPG?type=w773" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAxMzBfNjUg/MDAxNzA2NjEzMjc1ODE1.zTbDIjCitfeq493H8i-muPcuyUlDW4b3xMqWCKBE9CEg.SyuPjmhV16AMUX11f8WZ_BW4y2qxJDYW2ondyTUp0HQg.JPEG.playyul/IMG_3929.JPG?type=w773" + }, + { + "orgurl": "https://postfiles.pstatic.net/MjAyNDAxMzBfMzAw/MDAxNzA2NjEzMjc1ODg4.UqRSfKN4zqEanZ3WLsNgaRg8MYk-BPuUlDVUyQEyGqkg.zqYtjBKTHACO6I_qTTcbcmMDe3ClkXUa7wr_DZHX69og.JPEG.playyul/IMG_3921.JPG?type=w773" + } + ], + "isMy": false + } + ] + }, + "comment": { + "placenamefull": "정분네중앙곱창 강남본점", + "kamapComntcnt": 14, + "scoresum": 32, + "scorecnt": 14, + "photocnt": 1, + "list": [ + { + "commentid": "9587247", + "contents": "굳이?", + "point": 2, + "username": "맛집추천좀", + "profile": "http://th-p.talk.kakao.co.kr/th/talkp/wk4S8XPrMq/XUXy6N6xWYurcodYB1RfE1/umbchu.jpg", + "profileStatus": "S", + "photoCnt": 0, + "likeCnt": 0, + "kakaoMapUserId": "301634904", + "photoList": [], + "ownerReply": {}, + "userCommentCount": 69, + "userCommentAverageScore": 3, + "myStorePick": false, + "level": { + "nowLevel": 24, + "badge": "02" + }, + "date": "2024.02.22.", + "isMy": false, + "isBlock": false, + "isEditable": false, + "isMyLike": false + }, + { + "commentid": "7704891", + "contents": "상추에서 빨간 벌레가 기어다녀 말씀 드리니, 사과도 없이 밖에서 날라 들어온것 같다며 위에 상추만 바꿔 주시려해서 됐다고 이야기 한 후 돼지곱창볶음 먹다가 딱딱한게 씹혀 휴지로 닦아 한참 동안 봐도 곱창에서 나올만한건 아닌 것 같아 말씀 드리니 “잘 모르겠다 곱창 받는 곳에서 딸려온 것 같다” 고 하시고 죄송하다고 음료수 서비스.. 다신 가고싶지 않네요", + "point": 1, + "username": "땅콩빵", + "profile": "http://t1.daumcdn.net/local/kakaomapPhoto/profile/79bcacd58b1c2be74f212d9f23a11401f285f093?original", + "profileStatus": "S", + "photoCnt": 1, + "likeCnt": 2, + "thumbnail": "http://t1.daumcdn.net/local/kakaomapPhoto/review/c776cb2be9156f9a4f806e9dc23e619716c00be5?original", + "kakaoMapUserId": "816718917", + "photoList": [ + { + "url": "http://t1.daumcdn.net/local/kakaomapPhoto/review/c776cb2be9156f9a4f806e9dc23e619716c00be5?original", + "near": true + } + ], + "ownerReply": {}, + "userCommentCount": 2, + "userCommentAverageScore": 3, + "myStorePick": false, + "level": { + "nowLevel": 4, + "badge": "01" + }, + "date": "2023.05.23.", + "isMy": false, + "isBlock": false, + "isEditable": false, + "isMyLike": false + }, + { + "commentid": "6879411", + "contents": "야곱에 라면", + "point": 3, + "username": "cercle", + "profile": "http://k.kakaocdn.net/dn/kAt3n/btquXyT19Pt/BolBjX0iQfcsttkudsKpyK/img_640x640.jpg", + "profileStatus": "S", + "photoCnt": 0, + "likeCnt": 0, + "kakaoMapUserId": "1224921053", + "photoList": [], + "ownerReply": {}, + "userCommentCount": 719, + "userCommentAverageScore": 3.6, + "myStorePick": false, + "level": { + "nowLevel": 36, + "badge": "03" + }, + "date": "2023.01.19.", + "isMy": false, + "isBlock": false, + "isEditable": false, + "isMyLike": false + } + ], + "commentPhotos": [ + { + "photoid": 702370, + "url": "http://t1.daumcdn.net/local/kakaomapPhoto/review/ed7aa0ecafdfb578c6b394f6f1e76d1dfca5d99e?original", + "near": false, + "modDate": "2020.08.22." + } + ], + "strengthCounts": [ + { + "id": 5, + "name": "맛", + "count": 1 + }, + { + "id": 1, + "name": "가성비", + "count": 0 + }, + { + "id": 2, + "name": "친절", + "count": 1 + }, + { + "id": 3, + "name": "분위기", + "count": 0 + }, + { + "id": 4, + "name": "주차", + "count": 0 + } + ], + "reviewWriteBlocked": "NOT_LOGIN_USER" + }, + "findway": { + "x": 505600, + "y": 1111485, + "subway": [ + { + "stationSimpleName": "강남역", + "stationId": "SES0222", + "exitNum": "10", + "toExitDistance": 331, + "subwayList": [ + { + "subwayId": "SES2", + "subwayName": "2호선" + }, + { + "subwayId": "SES34", + "subwayName": "신분당선" + } + ], + "toExitMinute": 5 + }, + { + "stationSimpleName": "신논현역", + "stationId": "SES0925", + "exitNum": "6", + "toExitDistance": 368, + "subwayList": [ + { + "subwayId": "SES9", + "subwayName": "9호선" + }, + { + "subwayId": "SES34", + "subwayName": "신분당선" + } + ], + "toExitMinute": 6 + } + ], + "busstop": [ + { + "busStopId": "BS110240", + "busStopName": "신논현역.주류성빌딩", + "busStopDisplayId": "22406", + "toBusstopDistance": 54, + "wpointx": 505710, + "wpointy": 1111563, + "busInfo": [ + { + "busType": "광역", + "busTypeCode": "RED", + "busList": [ + { + "busId": "B2300", + "busName": "M4403" + } + ], + "busNames": "M4403" + }, + { + "busType": "급행", + "busTypeCode": "EXPRESS", + "busList": [ + { + "busId": "B78766", + "busName": "5001-1", + "busTextName": "(급행)" + } + ], + "busNames": "5001-1" + }, + { + "busType": "직행", + "busTypeCode": "DIRECT", + "busList": [ + { + "busId": "B2451", + "busName": "1551" + }, + { + "busId": "B13646", + "busName": "1551B" + }, + { + "busId": "B71636", + "busName": "3401" + }, + { + "busId": "B50970", + "busName": "4403" + }, + { + "busId": "B75968", + "busName": "5001", + "busTextName": "(예약)" + }, + { + "busId": "B75966", + "busName": "5001-1", + "busTextName": "(예약)" + }, + { + "busId": "B75964", + "busName": "5003", + "busTextName": "(예약)" + }, + { + "busId": "B63898", + "busName": "8502" + } + ], + "busNames": "1551, 1551B, 3401, 4403, 5001, 5001-1, 5003, 8502" + } + ] + }, + { + "busStopId": "BS70019", + "busStopName": "신논현역.BSX빌딩", + "busStopDisplayId": "22407", + "toBusstopDistance": 68, + "wpointx": 505688, + "wpointy": 1111631, + "busInfo": [ + { + "busType": "광역", + "busTypeCode": "RED", + "busList": [ + { + "busId": "B15280", + "busName": "M5422" + } + ], + "busNames": "M5422" + }, + { + "busType": "직행", + "busTypeCode": "DIRECT", + "busList": [ + { + "busId": "B1052", + "busName": "1560A" + }, + { + "busId": "B52052", + "busName": "3008" + }, + { + "busId": "B62328", + "busName": "5002A" + } + ], + "busNames": "1560A, 3008, 5002A" + } + ] + }, + { + "busStopId": "11230521026", + "busStopName": "지하철2호선강남역(중)", + "busStopDisplayId": "22012", + "toBusstopDistance": 86, + "wpointx": 505813, + "wpointy": 1111496, + "busInfo": [ + { + "busType": "간선", + "busTypeCode": "BLUE", + "busList": [ + { + "busId": "1100061509", + "busName": "140" + }, + { + "busId": "1100061521", + "busName": "144" + }, + { + "busId": "1100061524", + "busName": "145" + }, + { + "busId": "1100061542", + "busName": "360" + }, + { + "busId": "B15890", + "busName": "400" + }, + { + "busId": "1100061452", + "busName": "402" + }, + { + "busId": "1100061453", + "busName": "420" + }, + { + "busId": "1100071851", + "busName": "421" + }, + { + "busId": "1100071709", + "busName": "440" + }, + { + "busId": "1100071661", + "busName": "441" + }, + { + "busId": "B53285", + "busName": "452" + }, + { + "busId": "1100061463", + "busName": "470" + }, + { + "busId": "B25185", + "busName": "542" + }, + { + "busId": "B1026", + "busName": "643" + }, + { + "busId": "B54774", + "busName": "741" + }, + { + "busId": "B24208", + "busName": "N13", + "busTextName": "(심야)" + }, + { + "busId": "B72083", + "busName": "N31", + "busTextName": "(심야)" + }, + { + "busId": "B16184", + "busName": "N37", + "busTextName": "(심야)" + }, + { + "busId": "B72054", + "busName": "N75", + "busTextName": "(심야)" + } + ], + "busNames": "140, 144, 145, 360, 400, 402, 420, 421, 440, 441, 452, 470, 542, 643, 741, N13, N31, N37, N75" + }, + { + "busType": "광역", + "busTypeCode": "RED", + "busList": [ + { + "busId": "1100091033", + "busName": "9404" + }, + { + "busId": "1100091009", + "busName": "9408" + }, + { + "busId": "B70511", + "busName": "9409" + }, + { + "busId": "B76650", + "busName": "서울01", + "busTextName": "(평일)(출근)" + }, + { + "busId": "B77049", + "busName": "서울06", + "busTextName": "(평일)(출근)" + } + ], + "busNames": "9404, 9408, 9409, 서울01, 서울06" + }, + { + "busType": "공항", + "busTypeCode": "AIRPORT", + "busList": [ + { + "busId": "1100092019", + "busName": "6009" + } + ], + "busNames": "6009" + }, + { + "busType": "직행", + "busTypeCode": "DIRECT", + "busList": [ + { + "busId": "B1922", + "busName": "1100" + }, + { + "busId": "3134091003", + "busName": "1550" + }, + { + "busId": "B9567", + "busName": "1570" + }, + { + "busId": "200004", + "busName": "3030" + }, + { + "busId": "200057", + "busName": "3100" + }, + { + "busId": "B73015", + "busName": "3100N" + }, + { + "busId": "B29216", + "busName": "3600" + }, + { + "busId": "B2458", + "busName": "8001" + }, + { + "busId": "B39151", + "busName": "9202" + }, + { + "busId": "B61715", + "busName": "9400" + }, + { + "busId": "B62652", + "busName": "9800" + }, + { + "busId": "B25180", + "busName": "G7426" + }, + { + "busId": "B64130", + "busName": "P9201", + "busTextName": "(출근)" + } + ], + "busNames": "1100, 1550, 1570, 3030, 3100, 3100N, 3600, 8001, 9202, 9400, 9800, G7426, P9201" + } + ] + }, + { + "busStopId": "BS70021", + "busStopName": "신논현역.유화빌딩", + "busStopDisplayId": "22408", + "toBusstopDistance": 97, + "wpointx": 505651, + "wpointy": 1111721, + "busInfo": [ + { + "busType": "광역", + "busTypeCode": "RED", + "busList": [ + { + "busId": "B63890", + "busName": "M4448" + }, + { + "busId": "B67932", + "busName": "M4449" + }, + { + "busId": "B78909", + "busName": "서울01", + "busTextName": "(평일)(퇴근)" + } + ], + "busNames": "M4448, M4449, 서울01" + }, + { + "busType": "직행", + "busTypeCode": "DIRECT", + "busList": [ + { + "busId": "B1042", + "busName": "1101" + }, + { + "busId": "B73279", + "busName": "1101N" + }, + { + "busId": "B9621", + "busName": "1241" + }, + { + "busId": "B31189", + "busName": "6001" + }, + { + "busId": "B33317", + "busName": "6002" + }, + { + "busId": "B35372", + "busName": "6002-1" + }, + { + "busId": "B1871", + "busName": "9004" + } + ], + "busNames": "1101, 1101N, 1241, 6001, 6002, 6002-1, 9004" + } + ] + }, + { + "busStopId": "BS70020", + "busStopName": "신논현역.금강빌딩", + "busStopDisplayId": "22409", + "toBusstopDistance": 105, + "wpointx": 505642, + "wpointy": 1111743, + "busInfo": [ + { + "busType": "광역", + "busTypeCode": "RED", + "busList": [ + { + "busId": "B51085", + "busName": "M4434" + }, + { + "busId": "B53913", + "busName": "M5438" + } + ], + "busNames": "M4434, M5438" + }, + { + "busType": "직행", + "busTypeCode": "DIRECT", + "busList": [ + { + "busId": "10049", + "busName": "1550-1" + }, + { + "busId": "B67929", + "busName": "1552" + }, + { + "busId": "B2406", + "busName": "5006" + }, + { + "busId": "9564", + "busName": "5100" + }, + { + "busId": "B62246", + "busName": "5100", + "busTextName": "(예약)" + }, + { + "busId": "B76153", + "busName": "5401" + }, + { + "busId": "B2493", + "busName": "6004" + }, + { + "busId": "B63411", + "busName": "6600" + }, + { + "busId": "B39150", + "busName": "G5100" + } + ], + "busNames": "1550-1, 1552, 5006, 5100, 5401, 6004, 6600, G5100" + } + ] + }, + { + "busStopId": "11220571018", + "busStopName": "지하철2호선강남역(중)", + "busStopDisplayId": "22011", + "toBusstopDistance": 108, + "wpointx": 505697, + "wpointy": 1111736, + "busInfo": [ + { + "busType": "간선", + "busTypeCode": "BLUE", + "busList": [ + { + "busId": "1100061509", + "busName": "140" + }, + { + "busId": "1100061521", + "busName": "144" + }, + { + "busId": "1100061524", + "busName": "145" + }, + { + "busId": "1100061542", + "busName": "360" + }, + { + "busId": "B15890", + "busName": "400" + }, + { + "busId": "1100061452", + "busName": "402" + }, + { + "busId": "1100061453", + "busName": "420" + }, + { + "busId": "1100071851", + "busName": "421" + }, + { + "busId": "1100071709", + "busName": "440" + }, + { + "busId": "1100071661", + "busName": "441" + }, + { + "busId": "B53285", + "busName": "452" + }, + { + "busId": "1100061463", + "busName": "470" + }, + { + "busId": "B25185", + "busName": "542" + }, + { + "busId": "B54774", + "busName": "741" + }, + { + "busId": "B24208", + "busName": "N13", + "busTextName": "(심야)" + }, + { + "busId": "B72083", + "busName": "N31", + "busTextName": "(심야)" + }, + { + "busId": "B16184", + "busName": "N37", + "busTextName": "(심야)" + }, + { + "busId": "B72054", + "busName": "N75", + "busTextName": "(심야)" + } + ], + "busNames": "140, 144, 145, 360, 400, 402, 420, 421, 440, 441, 452, 470, 542, 741, N13, N31, N37, N75" + }, + { + "busType": "광역", + "busTypeCode": "RED", + "busList": [ + { + "busId": "1100091033", + "busName": "9404" + }, + { + "busId": "1100091009", + "busName": "9408" + }, + { + "busId": "B70511", + "busName": "9409" + }, + { + "busId": "B26199", + "busName": "M6427" + }, + { + "busId": "B78908", + "busName": "서울06", + "busTextName": "(평일)(퇴근)" + } + ], + "busNames": "9404, 9408, 9409, M6427, 서울06" + }, + { + "busType": "공항", + "busTypeCode": "AIRPORT", + "busList": [ + { + "busId": "1100092019", + "busName": "6009" + } + ], + "busNames": "6009" + }, + { + "busType": "직행", + "busTypeCode": "DIRECT", + "busList": [ + { + "busId": "5078", + "busName": "1005" + }, + { + "busId": "B1922", + "busName": "1100" + }, + { + "busId": "B31570", + "busName": "1151" + }, + { + "busId": "B73015", + "busName": "3100N" + }, + { + "busId": "B32203", + "busName": "6427" + }, + { + "busId": "B2458", + "busName": "8001" + }, + { + "busId": "B39151", + "busName": "9202" + }, + { + "busId": "B64128", + "busName": "P9201", + "busTextName": "(퇴근)" + }, + { + "busId": "B60725", + "busName": "이음2", + "busTextName": "(심야)" + } + ], + "busNames": "1005, 1100, 1151, 3100N, 6427, 8001, 9202, P9201, 이음2" + } + ] + }, + { + "busStopId": "BS127554", + "busStopName": "신논현역", + "busStopDisplayId": "23641", + "toBusstopDistance": 110, + "wpointx": 505875, + "wpointy": 1111474, + "busInfo": [ + { + "busType": "광역", + "busTypeCode": "RED", + "busList": [ + { + "busId": "B28423", + "busName": "9711" + }, + { + "busId": "B3166", + "busName": "M7412" + } + ], + "busNames": "9711, M7412" + }, + { + "busType": "직행", + "busTypeCode": "DIRECT", + "busList": [ + { + "busId": "11016", + "busName": "5001-1B" + }, + { + "busId": "11017", + "busName": "5001B" + }, + { + "busId": "11019", + "busName": "5002B" + }, + { + "busId": "11030", + "busName": "5003B" + }, + { + "busId": "B3346", + "busName": "9600" + }, + { + "busId": "3110091001", + "busName": "9700" + } + ], + "busNames": "5001-1B, 5001B, 5002B, 5003B, 9600, 9700" + } + ] + }, + { + "busStopId": "11220541012", + "busStopName": "강남역", + "busStopDisplayId": "22173", + "toBusstopDistance": 119, + "wpointx": 505819, + "wpointy": 1111286, + "busInfo": [ + { + "busType": "간선", + "busTypeCode": "BLUE", + "busList": [ + { + "busId": "1100061470", + "busName": "640" + } + ], + "busNames": "640" + }, + { + "busType": "지선", + "busTypeCode": "GREEN", + "busList": [ + { + "busId": "1100071626", + "busName": "4312" + } + ], + "busNames": "4312" + }, + { + "busType": "광역", + "busTypeCode": "RED", + "busList": [ + { + "busId": "B28423", + "busName": "9711" + } + ], + "busNames": "9711" + } + ] + }, + { + "busStopId": "BS110819", + "busStopName": "신논현역.우신빌딩", + "busStopDisplayId": "22410", + "toBusstopDistance": 138, + "wpointx": 505610, + "wpointy": 1111830, + "busInfo": [ + { + "busType": "광역", + "busTypeCode": "RED", + "busList": [ + { + "busId": "B25202", + "busName": "9500" + }, + { + "busId": "B6954", + "busName": "9501" + }, + { + "busId": "B25206", + "busName": "9802" + }, + { + "busId": "B78745", + "busName": "M6457" + } + ], + "busNames": "9500, 9501, 9802, M6457" + }, + { + "busType": "직행", + "busTypeCode": "DIRECT", + "busList": [ + { + "busId": "B1929", + "busName": "1700" + }, + { + "busId": "B1930", + "busName": "2000" + }, + { + "busId": "B25291", + "busName": "2000-1" + }, + { + "busId": "B1934", + "busName": "7007" + }, + { + "busId": "B38590", + "busName": "9303" + } + ], + "busNames": "1700, 2000, 2000-1, 7007, 9303" + } + ] + }, + { + "busStopId": "BS470212", + "busStopName": "신논현역", + "busStopDisplayId": "32055", + "toBusstopDistance": 144, + "wpointx": 505742, + "wpointy": 1111814, + "busInfo": [ + { + "busType": "광역", + "busTypeCode": "RED", + "busList": [ + { + "busId": "B25202", + "busName": "9500" + }, + { + "busId": "B6954", + "busName": "9501" + }, + { + "busId": "B25206", + "busName": "9802" + }, + { + "busId": "B26199", + "busName": "M6427" + }, + { + "busId": "B78745", + "busName": "M6457" + } + ], + "busNames": "9500, 9501, 9802, M6427, M6457" + }, + { + "busType": "직행", + "busTypeCode": "DIRECT", + "busList": [ + { + "busId": "B32203", + "busName": "6427" + }, + { + "busId": "B60725", + "busName": "이음2", + "busTextName": "(심야)" + } + ], + "busNames": "6427, 이음2" + } + ] + }, + { + "busStopId": "BS70016", + "busStopName": "신논현역.인터파크", + "busStopDisplayId": "22411", + "toBusstopDistance": 154, + "wpointx": 505595, + "wpointy": 1111870, + "busInfo": [ + { + "busType": "직행", + "busTypeCode": "DIRECT", + "busList": [ + { + "busId": "B8674", + "busName": "1311" + }, + { + "busId": "B61708", + "busName": "1311B" + }, + { + "busId": "200004", + "busName": "3030" + }, + { + "busId": "B62354", + "busName": "5200" + }, + { + "busId": "B3348", + "busName": "5300" + }, + { + "busId": "B78619", + "busName": "5300", + "busTextName": "(예약)" + } + ], + "busNames": "1311, 1311B, 3030, 5200, 5300" + } + ] + }, + { + "busStopId": "BS115323", + "busStopName": "강남역.서초초교앞", + "busStopDisplayId": "22850", + "toBusstopDistance": 163, + "wpointx": 505859, + "wpointy": 1111171, + "busInfo": [ + { + "busType": "마을", + "busTypeCode": "MAUL", + "busList": [ + { + "busId": "B9989", + "busName": "서초03" + } + ], + "busNames": "서초03" + } + ] + }, + { + "busStopId": "11230641041", + "busStopName": "신논현역6번출구", + "busStopDisplayId": "23286", + "toBusstopDistance": 174, + "wpointx": 505711, + "wpointy": 1111905, + "busInfo": [ + { + "busType": "지선", + "busTypeCode": "GREEN", + "busList": [ + { + "busId": "1100071684", + "busName": "3412" + }, + { + "busId": "1100071626", + "busName": "4312" + } + ], + "busNames": "3412, 4312" + }, + { + "busType": "광역", + "busTypeCode": "RED", + "busList": [ + { + "busId": "B28423", + "busName": "9711" + } + ], + "busNames": "9711" + }, + { + "busType": "마을", + "busTypeCode": "MAUL", + "busList": [ + { + "busId": "B9989", + "busName": "서초03" + } + ], + "busNames": "서초03" + } + ] + }, + { + "busStopId": "BS114621", + "busStopName": "강남역10번출구", + "busStopDisplayId": "22885", + "toBusstopDistance": 195, + "wpointx": 505818, + "wpointy": 1111048, + "busInfo": [ + { + "busType": "마을", + "busTypeCode": "MAUL", + "busList": [ + { + "busId": "B9992", + "busName": "서초09" + } + ], + "busNames": "서초09" + } + ] + }, + { + "busStopId": "11220541003", + "busStopName": "신논현역.구교보타워사거리/신논현역.씨티은행", + "busStopDisplayId": "22172", + "toBusstopDistance": 210, + "wpointx": 505543, + "wpointy": 1112006, + "busInfo": [ + { + "busType": "간선", + "busTypeCode": "BLUE", + "busList": [ + { + "busId": "1100061528", + "busName": "146" + }, + { + "busId": "B75134", + "busName": "8146", + "busTextName": "(평일)" + } + ], + "busNames": "146, 8146" + }, + { + "busType": "지선", + "busTypeCode": "GREEN", + "busList": [ + { + "busId": "1100071626", + "busName": "4312" + } + ], + "busNames": "4312" + }, + { + "busType": "광역", + "busTypeCode": "RED", + "busList": [ + { + "busId": "B28423", + "busName": "9711" + }, + { + "busId": "B3166", + "busName": "M7412" + } + ], + "busNames": "9711, M7412" + }, + { + "busType": "직행", + "busTypeCode": "DIRECT", + "busList": [ + { + "busId": "200057", + "busName": "3100" + }, + { + "busId": "3110091001", + "busName": "9700" + }, + { + "busId": "B25180", + "busName": "G7426" + } + ], + "busNames": "3100, 9700, G7426" + } + ] + }, + { + "busStopId": "BS115528", + "busStopName": "교보타워앞", + "busStopDisplayId": "22838", + "toBusstopDistance": 225, + "wpointx": 505530, + "wpointy": 1112042, + "busInfo": [ + { + "busType": "마을", + "busTypeCode": "MAUL", + "busList": [ + { + "busId": "B9989", + "busName": "서초03" + } + ], + "busNames": "서초03" + } + ] + }, + { + "busStopId": "BS12049", + "busStopName": "강남역11번출구", + "busStopDisplayId": "23285", + "toBusstopDistance": 229, + "wpointx": 506015, + "wpointy": 1111092, + "busInfo": [ + { + "busType": "지선", + "busTypeCode": "GREEN", + "busList": [ + { + "busId": "1100071684", + "busName": "3412" + }, + { + "busId": "1100071626", + "busName": "4312" + }, + { + "busId": "B1027", + "busName": "8541", + "busTextName": "(맞춤버스)(공휴일제외)" + } + ], + "busNames": "3412, 4312, 8541" + }, + { + "busType": "마을", + "busTypeCode": "MAUL", + "busList": [ + { + "busId": "B9989", + "busName": "서초03" + } + ], + "busNames": "서초03" + } + ] + }, + { + "busStopId": "BS114573", + "busStopName": "롯데캐슬클래식.사랑의교회", + "busStopDisplayId": "22554", + "toBusstopDistance": 236, + "wpointx": 505080, + "wpointy": 1111205, + "busInfo": [ + { + "busType": "마을", + "busTypeCode": "MAUL", + "busList": [ + { + "busId": "B9990", + "busName": "서초11" + } + ], + "busNames": "서초11" + } + ] + }, + { + "busStopId": "BS115848", + "busStopName": "롯데캐슬클래식", + "busStopDisplayId": "22596", + "toBusstopDistance": 259, + "wpointx": 504965, + "wpointy": 1111362, + "busInfo": [ + { + "busType": "마을", + "busTypeCode": "MAUL", + "busList": [ + { + "busId": "B9990", + "busName": "서초11" + } + ], + "busNames": "서초11" + } + ] + }, + { + "busStopId": "BS110799", + "busStopName": "서초푸르지오써밋.롯데캐슬클래식", + "busStopDisplayId": "22164", + "toBusstopDistance": 291, + "wpointx": 504901, + "wpointy": 1111687, + "busInfo": [ + { + "busType": "간선", + "busTypeCode": "BLUE", + "busList": [ + { + "busId": "1100061528", + "busName": "146" + }, + { + "busId": "1100061470", + "busName": "640" + }, + { + "busId": "B75134", + "busName": "8146", + "busTextName": "(평일)" + } + ], + "busNames": "146, 640, 8146" + }, + { + "busType": "마을", + "busTypeCode": "MAUL", + "busList": [ + { + "busId": "B9990", + "busName": "서초11" + } + ], + "busNames": "서초11" + }, + { + "busType": "직행", + "busTypeCode": "DIRECT", + "busList": [ + { + "busId": "B1929", + "busName": "1700" + }, + { + "busId": "B1930", + "busName": "2000" + }, + { + "busId": "B25291", + "busName": "2000-1" + }, + { + "busId": "B1934", + "busName": "7007" + }, + { + "busId": "B38590", + "busName": "9303" + } + ], + "busNames": "1700, 2000, 2000-1, 7007, 9303" + } + ] + } + ], + "busDirectionCheck": true + }, + "placeOwnerInfos": { + "status": "READY_TO_REGISTER", + "loginUserRelation": "OTHER" + }, + "trendRank": { + "meta": { + "category_or_menus": [ + { + "value": "category_all", + "name": "전체", + "description": "전체 (디폴트)" + }, + { + "value": "menu_finedining", + "name": "파인다이닝", + "description": "파인다이닝" + }, + { + "value": "category_korean", + "name": "한식", + "description": "한식" + }, + { + "value": "category_western", + "name": "양식", + "description": "양식" + }, + { + "value": "category_japanese", + "name": "일식", + "description": "일식" + }, + { + "value": "category_chinese", + "name": "중식", + "description": "중식" + }, + { + "value": "category_asian", + "name": "아시안", + "description": "아시안" + }, + { + "value": "category_cafe", + "name": "카페", + "description": "카페" + }, + { + "value": "menu_katsu", + "name": "돈가스", + "description": "돈가스" + }, + { + "value": "menu_kalguksu", + "name": "칼국수", + "description": "칼국수" + }, + { + "value": "menu_sushi", + "name": "초밥", + "description": "초밥" + }, + { + "value": "menu_tteokbokki", + "name": "떡볶이", + "description": "떡볶이" + }, + { + "value": "menu_pizza", + "name": "피자", + "description": "피자" + }, + { + "value": "menu_burger", + "name": "햄버거", + "description": "햄버거(수제버거)" + }, + { + "value": "menu_dumpling", + "name": "만두", + "description": "만두" + }, + { + "value": "menu_champon", + "name": "짬뽕", + "description": "짬뽕" + }, + { + "value": "menu_ricenoodle", + "name": "쌀국수", + "description": "쌀국수" + }, + { + "value": "menu_hotpot", + "name": "마라탕", + "description": "마라탕" + }, + { + "value": "menu_lambskewer", + "name": "양꼬치", + "description": "양꼬치" + }, + { + "value": "menu_sashimi", + "name": "회", + "description": "회" + }, + { + "value": "menu_bread", + "name": "빵", + "description": "빵" + }, + { + "value": "menu_chicken", + "name": "치킨", + "description": "치킨" + }, + { + "value": "menu_eel", + "name": "장어", + "description": "장어" + }, + { + "value": "menu_gukbap", + "name": "국밥", + "description": "국밥" + }, + { + "value": "menu_dakgalbi", + "name": "닭갈비", + "description": "닭갈비" + }, + { + "value": "menu_porkbelly", + "name": "삼겹살", + "description": "삼겹살" + } + ], + "depth1_regions_for_show_depth3_region": ["B", "I", "K", "N"] + }, + "groups": [ + { + "type": "favorite", + "analyzed_at": 1719645974, + "items": [ + { + "rank": 1, + "confirm_id": 25038356, + "name": "임병주 산동칼국수", + "lat": 37.48456954956055, + "lon": 127.030029296875, + "category_name": "칼국수", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NORMAL", + "review_count": 344, + "review_rating": 3.29, + "thumbnail": "http://t1.kakaocdn.net/fiy_reboot/place/BDFB642B94DC469980ABFC6BE5CE33B6", + "analyzed_info": { + "rank_change": 0, + "click_count_increase_rate": 20, + "dest_count_increase_rate": 14, + "hot_rank": false + } + }, + { + "rank": 2, + "confirm_id": 26455895, + "name": "루엘드파리", + "lat": 37.48395919799805, + "lon": 127.01727294921875, + "category_name": "제과,베이커리", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NORMAL", + "review_count": 189, + "review_rating": 4.13, + "thumbnail": "http://t1.daumcdn.net/localfiy/0F78D1F0B529479B8D9E05BB4222B3E2", + "analyzed_info": { + "rank_change": 0, + "click_count_increase_rate": 1, + "dest_count_increase_rate": -2, + "hot_rank": false + } + }, + { + "rank": 3, + "confirm_id": 34321780, + "name": "서관면옥 교대본점", + "lat": 37.493980407714844, + "lon": 127.01725769042969, + "category_name": "냉면", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NORMAL", + "review_count": 275, + "review_rating": 4.04, + "thumbnail": "http://t1.daumcdn.net/localfiy/BE1E1B4899254A49998307B96C333FE5", + "analyzed_info": { + "rank_change": 0, + "click_count_increase_rate": -4, + "dest_count_increase_rate": -7, + "hot_rank": false + } + }, + { + "rank": 4, + "confirm_id": 554364299, + "name": "프릳츠 양재점", + "lat": 37.4853515625, + "lon": 127.0322036743164, + "category_name": "커피전문점", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NORMAL", + "review_count": 212, + "review_rating": 3.97, + "thumbnail": "http://t1.kakaocdn.net/mystore/F8DF8E4E278F4DFF93EDBAEE6F72934A", + "analyzed_info": { + "rank_change": 0, + "click_count_increase_rate": 3, + "dest_count_increase_rate": 9, + "hot_rank": false + } + }, + { + "rank": 5, + "confirm_id": 1372079546, + "name": "하이디라오 강남점", + "lat": 37.5025634765625, + "lon": 127.0248031616211, + "category_name": "샤브샤브", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NORMAL", + "review_count": 321, + "review_rating": 4.15, + "thumbnail": "http://t1.kakaocdn.net/mystore/99107DD42F7541328648134DCAC62183", + "analyzed_info": { + "rank_change": 0, + "click_count_increase_rate": 20, + "dest_count_increase_rate": 20, + "hot_rank": false + } + } + ] + }, + { + "type": "search", + "analyzed_at": 1719645971, + "items": [ + { + "rank": 1, + "confirm_id": 25782422, + "name": "일점사", + "lat": 37.49118423461914, + "lon": 127.01329040527344, + "category_name": "육류,고기", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NORMAL", + "review_count": 36, + "review_rating": 3.16, + "thumbnail": "http://t1.kakaocdn.net/fiy_reboot/place/3B092AD991314C1A939113C01A3EA5CB", + "analyzed_info": { + "rank_change": 0, + "click_count_increase_rate": 0, + "dest_count_increase_rate": 34, + "hot_rank": false + } + }, + { + "rank": 2, + "confirm_id": 1967338071, + "name": "3대삼계장인", + "lat": 37.491355895996094, + "lon": 127.01155853271484, + "category_name": "삼계탕", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NOT_PROVIDED", + "thumbnail": "http://t1.kakaocdn.net/mystore/82E2ABCE5A1F4A33AAC5F30860FD8AC9", + "analyzed_info": { + "rank_change": 0, + "click_count_increase_rate": 114, + "dest_count_increase_rate": 72, + "hot_rank": false + } + }, + { + "rank": 3, + "confirm_id": 1170134658, + "name": "신북집", + "lat": 37.49188232421875, + "lon": 127.02523803710938, + "category_name": "칼국수", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NORMAL", + "review_count": 5, + "review_rating": 2.6, + "thumbnail": "http://t1.daumcdn.net/place/D1EF2FF1A7914AEA844AEAD5CE01F655", + "analyzed_info": { + "rank_change": 0, + "click_count_increase_rate": -5, + "dest_count_increase_rate": -30, + "hot_rank": false + } + }, + { + "rank": 4, + "confirm_id": 1128680382, + "name": "큐리오", + "lat": 37.50309371948242, + "lon": 127.02173614501953, + "category_name": "양식", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NORMAL", + "review_count": 20, + "review_rating": 4.6, + "thumbnail": "http://t1.kakaocdn.net/fiy_reboot/place/AF343DE1B1504B22BC16B026C1E89746", + "analyzed_info": { + "rank_change": 0, + "click_count_increase_rate": -15, + "dest_count_increase_rate": 11, + "hot_rank": false + } + }, + { + "rank": 5, + "confirm_id": 622973879, + "name": "주나수산", + "lat": 37.50153732299805, + "lon": 127.0248031616211, + "category_name": "회", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NORMAL", + "review_count": 27, + "review_rating": 2.81, + "thumbnail": "http://t1.daumcdn.net/place/B5C30E4B4DFC4E489C0C8353CDC6BD4A", + "analyzed_info": { + "rank_change": 0, + "click_count_increase_rate": 35, + "dest_count_increase_rate": -2, + "hot_rank": false + } + } + ] + }, + { + "type": "path", + "analyzed_at": 1719645976, + "items": [ + { + "rank": 1, + "confirm_id": 1967338071, + "name": "3대삼계장인", + "lat": 37.491355895996094, + "lon": 127.01155853271484, + "category_name": "삼계탕", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NOT_PROVIDED", + "thumbnail": "http://t1.kakaocdn.net/mystore/82E2ABCE5A1F4A33AAC5F30860FD8AC9", + "analyzed_info": { + "rank_change": 0, + "click_count_increase_rate": 114, + "dest_count_increase_rate": 72, + "hot_rank": false + } + }, + { + "rank": 2, + "confirm_id": 25782422, + "name": "일점사", + "lat": 37.49118423461914, + "lon": 127.01329040527344, + "category_name": "육류,고기", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NORMAL", + "review_count": 36, + "review_rating": 3.16, + "thumbnail": "http://t1.kakaocdn.net/fiy_reboot/place/3B092AD991314C1A939113C01A3EA5CB", + "analyzed_info": { + "rank_change": -4, + "click_count_increase_rate": 0, + "dest_count_increase_rate": 34, + "hot_rank": false + } + }, + { + "rank": 3, + "confirm_id": 1372079546, + "name": "하이디라오 강남점", + "lat": 37.5025634765625, + "lon": 127.0248031616211, + "category_name": "샤브샤브", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NORMAL", + "review_count": 321, + "review_rating": 4.15, + "thumbnail": "http://t1.kakaocdn.net/mystore/99107DD42F7541328648134DCAC62183", + "analyzed_info": { + "rank_change": 1, + "click_count_increase_rate": 20, + "dest_count_increase_rate": 20, + "hot_rank": false + } + }, + { + "rank": 4, + "confirm_id": 1725176424, + "name": "파이브가이즈 강남", + "lat": 37.50116729736328, + "lon": 127.02568054199219, + "category_name": "햄버거", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NORMAL", + "review_count": 392, + "review_rating": 3.21, + "thumbnail": "http://t1.kakaocdn.net/fiy_reboot/place/12701D5E78B4454188EB19080B392AC2", + "analyzed_info": { + "rank_change": 1, + "click_count_increase_rate": 20, + "dest_count_increase_rate": 21, + "hot_rank": false + } + }, + { + "rank": 5, + "confirm_id": 25038356, + "name": "임병주 산동칼국수", + "lat": 37.48456954956055, + "lon": 127.030029296875, + "category_name": "칼국수", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NORMAL", + "review_count": 344, + "review_rating": 3.29, + "thumbnail": "http://t1.kakaocdn.net/fiy_reboot/place/BDFB642B94DC469980ABFC6BE5CE33B6", + "analyzed_info": { + "rank_change": 1, + "click_count_increase_rate": 20, + "dest_count_increase_rate": 14, + "hot_rank": false + } + } + ] + }, + { + "type": "share", + "analyzed_at": 1719645972, + "items": [ + { + "rank": 1, + "confirm_id": 1372079546, + "name": "하이디라오 강남점", + "lat": 37.5025634765625, + "lon": 127.0248031616211, + "category_name": "샤브샤브", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NORMAL", + "review_count": 321, + "review_rating": 4.15, + "thumbnail": "http://t1.kakaocdn.net/mystore/99107DD42F7541328648134DCAC62183", + "analyzed_info": { + "rank_change": 0, + "click_count_increase_rate": 20, + "dest_count_increase_rate": 20, + "hot_rank": false + } + }, + { + "rank": 2, + "confirm_id": 8279464, + "name": "딘타이펑 강남점", + "lat": 37.49851989746094, + "lon": 127.02561950683594, + "category_name": "중국요리", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NOT_PROVIDED", + "thumbnail": "http://t1.daumcdn.net/cfile/134F1D4A4F22084C32", + "analyzed_info": { + "rank_change": 0, + "click_count_increase_rate": 10, + "dest_count_increase_rate": 0, + "hot_rank": false + } + }, + { + "rank": 3, + "confirm_id": 1752978029, + "name": "낙원타코 강남역점", + "lat": 37.498130798339844, + "lon": 127.02527618408203, + "category_name": "멕시칸,브라질", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NOT_PROVIDED", + "thumbnail": "http://t1.daumcdn.net/localfiy/searchregister_1553022645", + "analyzed_info": { + "rank_change": 0, + "click_count_increase_rate": 7, + "dest_count_increase_rate": 24, + "hot_rank": false + } + }, + { + "rank": 4, + "confirm_id": 18356174, + "name": "요멘야고에몬 강남점", + "lat": 37.498451232910156, + "lon": 127.02635955810547, + "category_name": "퓨전일식", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NORMAL", + "review_count": 276, + "review_rating": 3.39, + "thumbnail": "http://t1.daumcdn.net/place/DB5C59C895664D04B7121DC72D8A68A4", + "analyzed_info": { + "rank_change": 0, + "click_count_increase_rate": 5, + "dest_count_increase_rate": 31, + "hot_rank": false + } + }, + { + "rank": 5, + "confirm_id": 34321780, + "name": "서관면옥 교대본점", + "lat": 37.493980407714844, + "lon": 127.01725769042969, + "category_name": "냉면", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울" + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구" + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동" + } + ], + "review_status": "NORMAL", + "review_count": 275, + "review_rating": 4.04, + "thumbnail": "http://t1.daumcdn.net/localfiy/BE1E1B4899254A49998307B96C333FE5", + "analyzed_info": { + "rank_change": 0, + "click_count_increase_rate": -4, + "dest_count_increase_rate": -7, + "hot_rank": false + } + } + ] + } + ] + }, + "menuInfo": { + "moreyn": "Y", + "menuList": [ + { + "price": "14,000", + "recommend": false, + "menu": "구이양념막창" + }, + { + "price": "14,000", + "recommend": false, + "menu": "소금구이막창" + }, + { + "price": "15,000", + "recommend": false, + "menu": "야채곱창볶음" + }, + { + "price": "17,000", + "recommend": false, + "menu": "순대곱창볶음" + } + ], + "productyn": "N", + "menuboardphotourl": "https://postfiles.pstatic.net/MjAyNDA2MTJfNzQg/MDAxNzE4MTQ3ODA5OTMw.zeLbX5XZ9nkUSuo38EpVkuEo7IXMWg9C4lIWASeTVB0g.q2QQTpKvHlOMQQk9osA0wYHWd2_qy6u0wiaWi1YlqNIg.JPEG/IMG_0736.jpg?type=w773", + "menuboardphotocount": 30, + "timeexp": "2024.01.25." + }, + "photo": { + "photoCount": 335, + "photoList": [ + { + "photoid": "M", + "orgurl": "http://t1.daumcdn.net/place/6DCE4A7D51924FE3A4437B8C91C553D4" + }, + { + "photoid": "VN702370", + "orgurl": "http://t1.daumcdn.net/local/kakaomapPhoto/review/ed7aa0ecafdfb578c6b394f6f1e76d1dfca5d99e?original" + }, + { + "photoid": "OP1", + "orgurl": "http://t1.daumcdn.net/place/43DED6A3FD2B4C94BD8F026D63831324" + }, + { + "photoid": "OP2", + "orgurl": "http://t1.daumcdn.net/place/7DC4FBA4E5B84E8FB2C1914740566D49" + }, + { + "photoid": "OP3", + "orgurl": "http://t1.daumcdn.net/place/2DA7437E0A7744AEA142DD52EAA13CF1" + } + ], + "sortedPhotoList": [ + { + "photoid": "Tfood935698273", + "orgurl": "https://postfiles.pstatic.net/MjAyNDAzMjBfOTAg/MDAxNzEwODkzMDAxNjQw.zqZaIHYTcWW3eQhusMhZEjwPfZDlbyztLXc-G_WOedUg.Z2QvhMnLfJahDnC5cquqpbfewKiLR_Wnb3NLmvy21skg.JPEG/IMG_3371.JPG?type=w966", + "categoryName": "음식" + }, + { + "photoid": "Tmenu1023851687", + "orgurl": "https://postfiles.pstatic.net/MjAyNDA2MTJfNzQg/MDAxNzE4MTQ3ODA5OTMw.zeLbX5XZ9nkUSuo38EpVkuEo7IXMWg9C4lIWASeTVB0g.q2QQTpKvHlOMQQk9osA0wYHWd2_qy6u0wiaWi1YlqNIg.JPEG/IMG_0736.jpg?type=w773", + "categoryName": "메뉴판" + } + ] + }, + "placeSubscribeInfo": { + "cnt": 0, + "isSubscriber": false + } + }, + "rawHeaders": [ + "Date", + "Sat, 29 Jun 2024 10:06:01 GMT", + "Content-Type", + "application/json", + "Transfer-Encoding", + "chunked", + "Connection", + "keep-alive", + "X-Content-Type-Options", + "nosniff", + "X-XSS-Protection", + "1; mode=block", + "Cache-Control", + "no-cache, no-store, max-age=0, must-revalidate", + "Pragma", + "no-cache", + "Expires", + "0", + "Strict-Transport-Security", + "max-age=15724800; includeSubDomains" + ], + "responseIsBinary": false + } +] diff --git a/src/search/kakao-map.helper.ts b/src/search/kakao-map.helper.ts new file mode 100644 index 0000000..a123a03 --- /dev/null +++ b/src/search/kakao-map.helper.ts @@ -0,0 +1,62 @@ +import { HttpService } from '@nestjs/axios'; +import { Injectable } from '@nestjs/common'; + +import { + KakaoCoordinateConversionParams, + KakaoCoordinateSystem, +} from './kakao-map.types'; + +@Injectable() +export class KakaoMapHelper { + constructor(private readonly httpService: HttpService) {} + + async congNamulRectToLongLatRect(rect: string): Promise { + const [x1, y1, x2, y2] = rect.split(','); + + const [leftTop, rightBottom] = await Promise.all([ + this.congnamulToLongLat(x1, y1), + this.congnamulToLongLat(x2, y2), + ]); + + return `${leftTop.x},${leftTop.y},${rightBottom.x},${rightBottom.y}`; + } + + async congnamulToLongLat( + x: string | number, + y: string | number, + ): Promise<{ x: number; y: number }> { + const queryParams: KakaoCoordinateConversionParams = { + x: Number(x), + y: Number(y), + input_coord: KakaoCoordinateSystem.WCONGNAMUL, + output_coord: KakaoCoordinateSystem.WGS84, + }; + + const response = await this.httpService.axiosRef.get( + 'https://dapi.kakao.com/v2/local/geo/transcoord.json', + { + params: queryParams, + responseType: 'json', + headers: { + Authorization: `KakaoAK ${process.env.KAKAO_REST_API_KEY}`, + }, + }, + ); + + return response.data.documents[0]; + } +} + +export const KAKAO_SCRAPING_HEADERS = { + Accept: 'application/json, text/javascript, */*; q=0.01', + 'Accept-Language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7,ja;q=0.6', + 'Cache-Control': 'no-cache', + Pragma: 'no-cache', + Priority: 'u=1, i', + 'Sec-Fetch-Dest': 'empty', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Site': 'same-origin', + 'User-Agent': + 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1', + 'X-Requested-With': 'XMLHttpRequest', +}; diff --git a/src/search/kakao-map.types.ts b/src/search/kakao-map.types.ts new file mode 100644 index 0000000..c4e6a57 --- /dev/null +++ b/src/search/kakao-map.types.ts @@ -0,0 +1,202 @@ +// 좌표계 enum 정의 +export enum KakaoCoordinateSystem { + WGS84 = 'WGS84', // 위경도 좌표계 + WCONGNAMUL = 'WCONGNAMUL', + CONGNAMUL = 'CONGNAMUL', // 카카오 좌표계 (카카오맵 rect로 나옴) + WTM = 'WTM', + TM = 'TM', + KTM = 'KTM', + UTM = 'UTM', + BESSEL = 'BESSEL', + WKTM = 'WKTM', + WUTM = 'WUTM', +} + +// 인터페이스 정의 +export interface KakaoCoordinateConversionParams { + x: number; // X 좌표값, 경위도인 경우 longitude(경도) + y: number; // Y 좌표값, 경위도인 경우 latitude(위도) + input_coord?: KakaoCoordinateSystem; // x, y 값의 좌표계 (기본값: WGS84) + output_coord: KakaoCoordinateSystem; // 변환할 좌표계 (기본값: WGS84) +} + +export enum KakaoCategoryGroupCode { + '대형마트' = 'MT1', + '편의점' = 'CS2', + '어린이집, 유치원' = 'PS3', + '학교' = 'SC4', + '학원' = 'AC5', + '주차장' = 'PK6', + '주유소, 충전소' = 'OL7', + '지하철역' = 'SW8', + '은행' = 'BK9', + '문화시설' = 'CT1', + '중개업소' = 'AG2', + '공공기관' = 'PO3', + '관광명소' = 'AT4', + '숙박' = 'AD5', + '음식점' = 'FD6', + '카페' = 'CE7', + '병원' = 'HP8', + '약국' = 'PM9', +} + +export interface KakaoKeywordSearchParams { + query: string; // 검색을 원하는 질의어 + category_group_code?: KakaoCategoryGroupCode; // 카테고리 그룹 코드, 카테고리로 결과 필터링을 원하는 경우 사용 + x?: string; // 중심 좌표의 X 혹은 경도(longitude) 값 + y?: string; // 중심 좌표의 Y 혹은 위도(latitude) 값 + radius?: number; // 중심 좌표부터의 반경거리 (미터(m), 최소: 0, 최대: 20000). 특정 지역을 중심으로 검색하려면 x, y와 함께 사용 + rect?: string; // 사각형의 지정 범위 내 제한 검색을 위한 좌표 (좌측 X 좌표, 좌측 Y 좌표, 우측 X 좌표, 우측 Y 좌표 형식) + page?: number; // 결과 페이지 번호 (최소: 1, 최대: 45, 기본값: 1) + size?: number; // 한 페이지에 보여질 문서의 개수 (최소: 1, 최대: 15, 기본값: 15) + sort?: 'distance' | 'accuracy'; // 결과 정렬 순서 (distance 정렬을 원할 때는 기준 좌표로 쓰일 x, y와 함께 사용, 기본값: accuracy) +} + +export type KakaoPlaceItem = { + address_name: string; // "서울 강남구 역삼동 669-17" + category_group_code: string; // "FD6" + category_group_name: string; // "음식점" + category_name: string; // "음식점 > 한식 > 육류,고기 > 곱창,막창" + distance: string; // "" + id: string; // "1261894710" + phone: string; // "02-555-7364" + place_name: string; // "세광양대창 역삼GS타워점" + place_url: string; // "http://place.map.kakao.com/1261894710" + road_address_name: string; // "서울 강남구 논현로94길 13" + x: string; // "127.037366122263" + y: string; // "37.5026329250425" +}; + +export type KakaoPlaceDetailRaw = { + isMapUser: string; // "ERROR" + isExist: boolean; // true + basicInfo: { + cid: number; // 762214594 + placenamefull: string; // "정분네중앙곱창 강남본점" + mainphotourl: string; // "http://t1.daumcdn.net/place/6DCE4A7D51924FE3A4437B8C91C553D4" + phonenum: string; // "02-3482-2337" + address: { + newaddr: { + newaddrfull: string; // "서초대로77길 35" + bsizonno: string; // "06612" + }; + region: { + name3: string; // "서초동" + fullname: string; // "서울 서초구 서초동" + newaddrfullname: string; // "서울 서초구" + }; + addrbunho: string; // "1308-12" + addrdetail: string; // "1층" + }; + wpointx: number; // 505600 + wpointy: number; // 1111485 + roadview: { + panoid: number; // 1171334557 + tilt: number; // 0 + pan: number; // 223.363 + wphotox: number; // 505617 + wphotoy: number; // 1111503 + rvlevel: number; // 2 + }; + category: { + cateid: string; // "727" + catename: string; // "곱창,막창" + cate1name: string; // "음식점" + fullCateIds: string; // "9|124|18165|727" + }; + feedback: { + allphotocnt: number; // 335 + blogrvwcnt: number; // 38 + comntcnt: number; // 14 + scoresum: number; // 32 + scorecnt: number; // 14 + reviewphotocnt: number; // 1 + }; + openHour: { + periodList: { + '0': { + periodName: string; // "영업기간" + timeList: { + '0': { + timeName: string; // "영업시간" + timeSE: string; // "16:00 ~ 05:00" + dayOfWeek: string; // "매일" + }; + }; + }; + }; + realtime: { + holiday: string; // "N" + breaktime: string; // "N" + open: string; // "Y" + moreOpenOffInfoExists: string; // "N" + datetime: string; // "20240629185922" + currentPeriod: { + periodName: string; // "영업기간" + timeList: { + '0': { + timeName: string; // "영업시간" + timeSE: string; // "16:00 ~ 05:00" + dayOfWeek: string; // "매일" + }; + }; + }; + closedToday: string; // "N" + }; + }; + payments: { + imgUrl: string; // "https://t1.kakaocdn.net/kakaomap_mobile/android/ico_zeropay.png" + landingUrl: string; // "https://www.zeropay.or.kr" + }[]; + tags: string[]; + source: { + date: string; // "2024.01.26." + }; + }; + menuInfo: { + moreyn: string; // "Y" + menuList: { + '0': { + price: string; // "14,000" + recommend: boolean; // false + menu: string; // "구이양념막창" + }; + '1': { + price: string; // "14,000" + recommend: boolean; // false + menu: string; // "소금구이막창" + }; + '2': { + price: string; // "15,000" + recommend: boolean; // false + menu: string; // "야채곱창볶음" + }; + '3': { + price: string; // "17,000" + recommend: boolean; // false + menu: string; // "순대곱창볶음" + }; + }; + productyn: string; // "N" + menuboardphotourl: string; // "https://postfiles.pstatic.net/MjAyNDA2MTJfNzQg/MDAxNzE4MTQ3ODA5OTMw.zeLbX5XZ9nkUSuo38EpVkuEo7IXMWg9C4lIWASeTVB0g.q2QQTpKvHlOMQQk9osA0wYHWd2_qy6u0wiaWi1YlqNIg.JPEG/IMG_0736.jpg?type=w773" + menuboardphotocount: number; // 30 + timeexp: string; // "2024.01.25." + }; + photo: { + photoCount: number; // 335 + photoList: { + photoid: string; // "M" + orgurl: string; // "http://t1.daumcdn.net/place/6DCE4A7D51924FE3A4437B8C91C553D4" + }[]; + sortedPhotoList: { + photoid: string; // "Tfood935698273" + orgurl: string; // "https://postfiles.pstatic.net/MjAyNDAzMjBfOTAg/MDAxNzEwODkzMDAxNjQw.zqZaIHYTcWW3eQhusMhZEjwPfZDlbyztLXc-G_WOedUg.Z2QvhMnLfJahDnC5cquqpbfewKiLR_Wnb3NLmvy21skg.JPEG/IMG_3371.JPG?type=w966" + categoryName: string; // "음식" + }[]; + }; + placeSubscribeInfo: { + cnt: number; // 0 + isSubscriber: boolean; // false + }; +}; diff --git a/src/search/search.controller.ts b/src/search/search.controller.ts index dc1964f..9490659 100644 --- a/src/search/search.controller.ts +++ b/src/search/search.controller.ts @@ -1,5 +1,5 @@ -import { Controller, Get, Query } from '@nestjs/common'; -import { ApiQuery, ApiTags } from '@nestjs/swagger'; +import { Controller, Get, Param, Query } from '@nestjs/common'; +import { ApiBody, ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger'; import { SearchService } from './search.service'; @@ -9,8 +9,70 @@ export class SearchController { constructor(private readonly searchService: SearchService) {} @ApiQuery({ type: String, name: 'q', description: '검색을 원하는 질의어' }) + @ApiOperation({ summary: 'q= 에 해당하는 검색어 자동완성 목록' }) @Get('suggest') async searchPlace(@Query('q') q: string) { return await this.searchService.suggest(q); } + + // 위도 경도 좌표계 쿼리 + @ApiQuery({ type: String, name: 'q', description: '검색을 원하는 질의어' }) + @ApiQuery({ + type: String, + name: 'rect', + description: '위도경도 "x1,y1,x2,y2"', + }) + @ApiOperation({ summary: '위도 경도 좌표계 쿼리' }) + @Get('places') + async searchPlacesByCoord( + @Query('q') q: string, + @Query('rect') rect: string, + ) { + return await this.searchService.searchPlaceList(q, rect); + } + + // 카카오 좌표계(wcongnamul) 쿼리 + @ApiQuery({ type: String, name: 'q', description: '검색을 원하는 질의어' }) + @ApiQuery({ + type: String, + name: 'rect', + description: '카카오 좌표계 위도경도 "x1,x2,y1,y2"', + }) + @ApiOperation({ summary: '카카오 좌표계(wcongnamul) 쿼리' }) + @Get('places/kakao') + async searchPlacesByKakaoCoord( + @Query('q') q: string, + @Query('rect') rect: string, + ) { + return await this.searchService.searchPlaceList(q, rect, { + isKakaoCoord: true, + }); + } + + @ApiOperation({ summary: '카카오 place에서 보내주는 장소 디테일 검색' }) + @Get('places/kakao/:id') + async searchPlaceDetail(@Param('id') id: string) { + return await this.searchService.searchPlaceDetail(id); + } + + // 카카오 좌표계(wcongnamul) 쿼리 + @ApiQuery({ + type: String, + name: 'url', + description: '쿼리에 (q와 rect)를 포함한 카카오맵 URL)', + example: + 'https://m.map.kakao.com/actions/searchView?q=%EA%B3%B1%EC%B0%BD&wxEnc=MOSQTP&wyEnc=QNOLPRNINRR&lvl=1&rect=504945,1111188.125,506025,1111753.125&viewmap=true#!/all/list/place', + }) + @ApiOperation({ + summary: '검색시스템 테스트용 라우트. url에 카카오맵 URL을 입력해주세요', + }) + @Get('places/kakao-test') + async searchPlacesByKakaoURL(@Query('url') kakaoURL: string) { + const searchParams = new URL(decodeURIComponent(kakaoURL)).searchParams; + const rect = searchParams.get('rect'); + const q = decodeURIComponent(searchParams.get('q')); + return await this.searchService.searchPlaceList(q, rect, { + isKakaoCoord: true, + }); + } } diff --git a/src/search/search.module.ts b/src/search/search.module.ts index 781aaf3..27c488a 100644 --- a/src/search/search.module.ts +++ b/src/search/search.module.ts @@ -1,12 +1,13 @@ import { HttpModule } from '@nestjs/axios'; import { Module } from '@nestjs/common'; +import { KakaoMapHelper } from './kakao-map.helper'; import { SearchController } from './search.controller'; import { SearchService } from './search.service'; @Module({ imports: [HttpModule], controllers: [SearchController], - providers: [SearchService], + providers: [SearchService, KakaoMapHelper], }) export class SearchModule {} diff --git a/src/search/search.service.spec.ts b/src/search/search.service.spec.ts index cb101b7..3cdc128 100644 --- a/src/search/search.service.spec.ts +++ b/src/search/search.service.spec.ts @@ -2,12 +2,16 @@ import { HttpService } from '@nestjs/axios'; import nock from 'nock'; +import { KakaoMapHelper } from './kakao-map.helper'; import { SearchService } from './search.service'; +require('dotenv').config({ path: '.development.env' }); + nock.back.fixtures = `${__dirname}/__fixtures__`; describe('search.service', () => { - const sut = new SearchService(new HttpService()); + const http = new HttpService(); + const sut = new SearchService(http, new KakaoMapHelper(http)); it('can suggest search keyword', async () => { nock.back.setMode('lockdown'); @@ -40,4 +44,189 @@ describe('search.service', () => { ] `); }); + + it('can search kakao retaurent data', async () => { + nock.back.setMode('lockdown'); + const { nockDone } = await nock.back('search-retaurent-01.json'); + + const result = await search( + 'https://m.map.kakao.com/actions/searchView?q=%EA%B3%B1%EC%B0%BD&wxEnc=MOSQTP&wyEnc=QNOLPRNINRR&lvl=1&rect=504945,1111188.125,506025,1111753.125&viewmap=true', + ); + + nockDone(); + + expect( + result.map((item) => `${item.place_name} -> ${item.road_address_name}`), + ).toMatchInlineSnapshot(` + [ + "마포한우곱창 -> 서울 서초구 서초대로73길 42", + "더막창스 강남본점 -> 서울 서초구 서초대로77길 37", + "서초네거리곱창 -> 서울 서초구 강남대로65길 12", + "쁨포차 강남역점 -> 서울 서초구 서초대로77길 43", + "정분네중앙곱창 강남본점 -> 서울 서초구 서초대로77길 35", + "진구곱창 -> 서울 서초구 서초대로75길 37", + ] + `); + }); + + it('can search kakao retaurent data', async () => { + nock.back.setMode('lockdown'); + const { nockDone } = await nock.back('search-retaurent-02.json'); + + const result = await search( + `https://m.map.kakao.com/actions/searchView?q=${encodeURIComponent( + '활어회', + )}&wxEnc=MOSQTP&wyEnc=QNOLPRNINRR&lvl=1&rect=504945,1111188.125,506025,1111753.125&viewmap=true`, + ); + + nockDone(); + + expect( + result.map((item) => `${item.place_name} -> ${item.road_address_name}`), + ).toMatchInlineSnapshot(` + [ + "응야끼도리 -> 서울 서초구 서초대로77길 43", + "사쿠라테이엔 강남본점 -> 서울 서초구 서초대로75길 36", + "나노하나 -> 서울 서초구 서초대로73길 42", + "서초세꼬시 -> 서울 서초구 서초대로73길 50", + "시선 -> 서울 서초구 서초대로77길 35", + "주나수산 -> 서울 서초구 서초대로77길 45", + "은행골 강남역점 -> 서울 서초구 서초대로75길 34", + "신선한형제들 -> 서울 서초구 강남대로65길 12", + "야키토리 토라미 -> 서울 서초구 서초대로75길 45", + "어사출또 강남역점 -> 서울 서초구 서초대로77길 37", + "청담이상 강남역점 -> 서울 강남구 테헤란로1길 42", + "동방제일수산 강남역점 -> 서울 서초구 서초대로73길 42", + "나에코 -> 서울 서초구 서초대로75길 45", + "만원수산 -> 서울 서초구 서초대로77길 37", + "이자카야 공감 강남역점 -> 서울 서초구 강남대로65길 7", + ] + `); + }); + + it('can search place detail', async () => { + nock.back.setMode('lockdown'); + const { nockDone } = await nock.back('search-retaurent-detail-01.json'); + + const data = await sut.searchPlaceDetail('762214594'); + + nockDone(); + + expect(data.basicInfo).toMatchInlineSnapshot(` + { + "address": { + "addrbunho": "1308-12", + "addrdetail": "1층", + "newaddr": { + "bsizonno": "06612", + "newaddrfull": "서초대로77길 35", + }, + "region": { + "fullname": "서울 서초구 서초동", + "name3": "서초동", + "newaddrfullname": "서울 서초구", + }, + }, + "category": { + "cate1name": "음식점", + "cateid": "727", + "catename": "곱창,막창", + "fullCateIds": "9|124|18165|727", + }, + "cid": 762214594, + "feedback": { + "allphotocnt": 335, + "blogrvwcnt": 38, + "comntcnt": 14, + "reviewphotocnt": 1, + "scorecnt": 14, + "scoresum": 32, + }, + "isStation": false, + "mainphotourl": "http://t1.daumcdn.net/place/6DCE4A7D51924FE3A4437B8C91C553D4", + "openHour": { + "periodList": [ + { + "periodName": "영업기간", + "timeList": [ + { + "dayOfWeek": "매일", + "timeName": "영업시간", + "timeSE": "16:00 ~ 05:00", + }, + ], + }, + ], + "realtime": { + "breaktime": "N", + "closedToday": "N", + "currentPeriod": { + "periodName": "영업기간", + "timeList": [ + { + "dayOfWeek": "매일", + "timeName": "영업시간", + "timeSE": "16:00 ~ 05:00", + }, + ], + }, + "datetime": "20240629190601", + "holiday": "N", + "moreOpenOffInfoExists": "N", + "open": "Y", + }, + }, + "payments": [ + { + "imgUrl": "https://t1.kakaocdn.net/kakaomap_mobile/android/ico_zeropay.png", + "landingUrl": "https://www.zeropay.or.kr", + }, + ], + "phonenum": "02-3482-2337", + "placenamefull": "정분네중앙곱창 강남본점", + "regions": [ + { + "depth": 1, + "id": "I", + "name": "서울", + }, + { + "depth": 2, + "id": "I1014", + "name": "서초구", + }, + { + "depth": 3, + "id": "I10140300", + "name": "서초동", + }, + ], + "roadview": { + "pan": 223.363, + "panoid": 1171334557, + "rvlevel": 2, + "tilt": 0, + "wphotox": 505617, + "wphotoy": 1111503, + }, + "source": { + "date": "2024.01.26.", + }, + "tags": [ + "노포", + "제로페이", + ], + "wpointx": 505600, + "wpointy": 1111485, + } + `); + }); + + async function search(kakaoMapUrl: string) { + // https://m.map.kakao.com/actions/searchView?q=%EC%B9%B4%ED%8E%98&wxEnc=MOPNSP&wyEnc=QNOLRRLIM&lvl=3&rect=504215,1110542.5,508535,1112802.5&viewmap=true + const searchParams = new URL(kakaoMapUrl).searchParams; + const kakaoRect = searchParams.get('rect'); + const query = decodeURIComponent(searchParams.get('q')); + return await sut.searchPlaceList(query, kakaoRect, { isKakaoCoord: true }); + } }); diff --git a/src/search/search.service.ts b/src/search/search.service.ts index 1c44a2f..cd42c9d 100644 --- a/src/search/search.service.ts +++ b/src/search/search.service.ts @@ -1,87 +1,81 @@ import { HttpService } from '@nestjs/axios'; import { Injectable } from '@nestjs/common'; -export enum CategoryGroupCode { - '대형마트' = 'MT1', - '편의점' = 'CS2', - '어린이집, 유치원' = 'PS3', - '학교' = 'SC4', - '학원' = 'AC5', - '주차장' = 'PK6', - '주유소, 충전소' = 'OL7', - '지하철역' = 'SW8', - '은행' = 'BK9', - '문화시설' = 'CT1', - '중개업소' = 'AG2', - '공공기관' = 'PO3', - '관광명소' = 'AT4', - '숙박' = 'AD5', - '음식점' = 'FD6', - '카페' = 'CE7', - '병원' = 'HP8', - '약국' = 'PM9', -} - -export interface KakaoKeywordSearchParams { - query: string; // 검색을 원하는 질의어 - category_group_code?: CategoryGroupCode; // 카테고리 그룹 코드, 카테고리로 결과 필터링을 원하는 경우 사용 - x?: string; // 중심 좌표의 X 혹은 경도(longitude) 값 - y?: string; // 중심 좌표의 Y 혹은 위도(latitude) 값 - radius?: number; // 중심 좌표부터의 반경거리 (미터(m), 최소: 0, 최대: 20000). 특정 지역을 중심으로 검색하려면 x, y와 함께 사용 - rect?: string; // 사각형의 지정 범위 내 제한 검색을 위한 좌표 (좌측 X 좌표, 좌측 Y 좌표, 우측 X 좌표, 우측 Y 좌표 형식) - page?: number; // 결과 페이지 번호 (최소: 1, 최대: 45, 기본값: 1) - size?: number; // 한 페이지에 보여질 문서의 개수 (최소: 1, 최대: 15, 기본값: 15) - sort?: 'distance' | 'accuracy'; // 결과 정렬 순서 (distance 정렬을 원할 때는 기준 좌표로 쓰일 x, y와 함께 사용, 기본값: accuracy) -} +import { uniqueBy } from '../utils'; +import { KAKAO_SCRAPING_HEADERS, KakaoMapHelper } from './kakao-map.helper'; +import { + KakaoCategoryGroupCode, + KakaoKeywordSearchParams, + KakaoPlaceDetailRaw, + KakaoPlaceItem, +} from './kakao-map.types'; @Injectable() export class SearchService { - constructor(private readonly httpService: HttpService) {} - async search() { - return []; - } + constructor( + private readonly httpService: HttpService, + private readonly kakaoMapHelper: KakaoMapHelper, + ) {} async suggest(keyword: string): Promise { const response = await this.httpService.axiosRef.get<{ items: any[] }>( `https://m.map.kakao.com/actions/topSuggestV2Json?q=${encodeURIComponent(keyword)}`, { responseType: 'json', - headers: { - Accept: 'application/json, text/javascript, */*; q=0.01', - 'Accept-Language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7,ja;q=0.6', - 'Cache-Control': 'no-cache', - Pragma: 'no-cache', - Priority: 'u=1, i', - 'Sec-Fetch-Dest': 'empty', - 'Sec-Fetch-Mode': 'cors', - 'Sec-Fetch-Site': 'same-origin', - 'User-Agent': - 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1', - 'X-Requested-With': 'XMLHttpRequest', - }, + headers: KAKAO_SCRAPING_HEADERS, }, ); return response.data.items.map((place) => place.key); } -} -// (async () => { -// const axios = new HttpService().axiosRef; -// const queryParams = { -// query: '카페', -// category_group_code: CategoryGroupCode['카페'], -// rect: '504592.5,1112392.5,505567.5,1114282.5', -// } satisfies KakaoKeywordSearchParams; -// const response = await axios.get( -// 'https://dapi.kakao.com/v2/local/search/keyword.json?', -// { -// params: queryParams, -// responseType: 'json', -// headers: { -// Authorization: `KakaoAK ${process.env.KAKAO_REST_API_KEY}`, -// }, -// }, -// ); + async searchPlaceList( + query: string, + rect: string, + { isKakaoCoord = false }: { isKakaoCoord?: boolean } = {}, + ): Promise { + if (isKakaoCoord) { + rect = await this.kakaoMapHelper.congNamulRectToLongLatRect(rect); + } + + const [{ documents: list1 }, { documents: list2 }] = await Promise.all([ + this.searchPlace(query, rect, KakaoCategoryGroupCode['카페']), + this.searchPlace(query, rect, KakaoCategoryGroupCode['음식점']), + ]); + return uniqueBy([...list1, ...list2], (item) => item.id); + } + + async searchPlaceDetail(id: string): Promise { + const response = await this.httpService.axiosRef.get( + `https://place.map.kakao.com/m/main/v/${id}`, + { + responseType: 'json', + headers: KAKAO_SCRAPING_HEADERS, + }, + ); + return response.data; + } + + private async searchPlace( + query: string, + rect: string, + code: KakaoCategoryGroupCode, + ): Promise<{ documents: KakaoPlaceItem[]; meta: { total_count: number } }> { + const queryParams = { + rect, + query, + category_group_code: code, + } satisfies KakaoKeywordSearchParams; + const response = await this.httpService.axiosRef.get( + 'https://dapi.kakao.com/v2/local/search/keyword.json', + { + params: queryParams, + responseType: 'json', + headers: { + Authorization: `KakaoAK ${process.env.KAKAO_REST_API_KEY}`, + }, + }, + ); -// console.log(response.data); -// })(); + return response.data; + } +} diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..e9c9855 --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,11 @@ +export function uniqueBy(arr: T[], toKey: (item: T) => string): T[] { + return Object.values( + arr.reduce( + (acc, item) => { + acc[toKey(item)] = item; + return acc; + }, + {} as Record, + ), + ); +}