🍻 맥주로 가득한 글입니다
술을 잘 못드시는 분께는 죄송하게 생각합니다.. ㅜㅠ
전 맥주를 좋아합니다. 아니, 사랑합니다.
매일매일 맥주를 마실 수 있다면 너무 행복할 것 같은 사람이에요.
하지만 전 특별한 맥주를 좋아합니다. 바로 수제맥주, 크래프트 맥주죠.
우리나라에서 맥주는 어떤 이미지일까요?
편의점에서 파는 4캔에 만원 맥주들?, 소맥?
고든램지가 인정한 맥주인 CASS 와 같이 우리나라에서는 대부분 이런 맥주가 딱 떠오르죠.
하지만 카스도 좋아하지만(!) 그래도 더 좋아하는 거라면 수제맥주입니다.
크래프트맥주, 수제맥주등 여러 표현들이 있지만 일단 이 글에서는 수제맥주로 이야기하겠습니다.
수제맥주라고 하면 좀 낯선게 사실입니다.
우리나라에서는 기본적으로 카스나 테라 처럼 대기업 맥주가 대부분이기도 하구요.
하지만 우리나라에도 수제맥주를 만드는곳이 많답니다.
이 지도를 보면 어떤것이 떠오르시나요?
이 노란색 마크들은 지금까지 제가 저장해두었던 수제맥주집들입니다.
직접 만드는 곳도 있고, 아니면 다른 매장에서 만든 수제맥주들을 파는곳도 있었고,
아니면 수제맥주를 캔이나, 병으로 판매하는 곳도 있었어요.
이때 수집한 데이터만 해도 200개 이상이 되었어요.
하지만 이건 저만 알기에는 너무 아까웠죠.
그러던 어느날, 저는 어떤 프로젝트를 발견하게 됩니다.
Github를 탐방하다가 전세계의 맥주양조장을 수집하고, API로 제공하는 프로젝트를 보게됩니다.
하지만 한국 데이터가 없었습니다.
한국 데이터를 추가해서 기여할 수 있는 방법이 없을까? 해서 디스코드 서버에 참여했습니다.
외국 프로젝트는 처음이라 번역기를 돌리며 영어로 한국에 있는 멋진 맥주 양조장을 추가하고 싶다.
라고 이야기드렸습니다.
메인테이너님께서는 매우 만족해 하시며, 만약 데이터를 추가할때 궁금한게 있으면 언제든 물어봐달라고 하셨습니다.
그리고 저는 데이터를 추가하기 위해 지금까지 수집해놓은 데이터들을 모으고 있었는데..
문제가 생겼습니다.
obdb_id | name | brewery_type | street |
---|---|---|---|
10-barrel-brewing-co-bend-1 | 10 Barrel Brewing Co | large | 62970 18th St |
10-barrel-brewing-co-bend-2 | 10 Barrel Brewing Co | large | 1135 NW Galveston Ave Ste B |
10-barrel-brewing-co-bend-pub-bend | 10 Barrel Brewing Co - Bend Pub | large | 62950 NE 18th St |
https://github.com/openbrewerydb/openbrewerydb/blob/master/data/united-states/oregon.csv
이 데이터들은 미국 오하이오 주의 실제 데이터들입니다.
보시면 알겠지만, 기본적으로 영어로 되어있어, 한국어로 들어갈 수 있는 자리가 없었습니다.
그리고 주소도 영어 주소이기 때문에, 한국 주소를 미국식으로 하나하나 전부 바꿀 필요가 있었죠.
하지만 제일 문제였던건 한국 가게명을 영어로 바꾸어야한다는것이었는데, 이는 의외로 쉽게 해결되었습니다.
메인테이너님께서는 유니코드 지원을 확인하고 싶으니 꼭 추가해달라고 하셨습니다.
그래서 저는 한국명과 영어명을 동시에 넣어 데이터를 추가할 수 있었습니다.
obdb_id | name | brewery_type | street |
---|---|---|---|
304-brewery-304-seodaemun-gu | 브루어리304 (Brewery 304) | brewpub | 7, Tongil-ro 11-gil |
alecrew-brewing-mapo-gu | 에일크루브루잉 (Alecrew Brewing) | brewpub | 87, Moraenae-ro |
amazing-brewing-company-seongdong-gu | 어메이징브루잉컴퍼니 (Amazing Brewing Company) | brewpub | 4, Seongsuil-ro 4-gil |
and-craftbros-tap-house-and-bottle-shop-seocho-gu | 크래프트브로스 탭하우스 & 바틀샵 (Craftbros Tap House & Bottle Shop) | brewpub | 18 Sapyeong-daero 22-gil |
https://github.com/openbrewerydb/openbrewerydb/blob/master/data/south-korea/seoul.csv
실제로 미리 구축되어있었던 데이터 추가 프로세스에 따라, 저는 CSV 파일을 추가했고,
위의 모습 처럼 데이터가 추가되었습니다.
위 테이블은 id와 이름 만 있지만 실제로 주소, 위도, 경도 등에 대한 데이터들이 모두 추가되어있습니다.
그 과정에서 위경도 추출 (지오코딩)
, 한국 주소 미국식 주소로 변경
등을 하는 작업들이 있었지만,
일단 수집해둔 데이터들이 그리 많지 않아서,
하나 하나 직접 찾으며 채우는 식으로 진행했습니다.
이런 작업들을 진행하며, 알고있던 전국의 데이터를 추가할 수 있었습니다.
여담이지만, 이건 제 첫 오픈소스 기여였고, 처음으로 외국인분들과 이야기를 하며
프로젝트에 기여할 수 있어 너무나 기뻤습니다. 작지만 큰 경험이었던것 같습니다.
올해 초, 저는 AWESOME-BEER 라는 프로젝트를 시작했습니다.
OpenBreweryDB
프로젝트를 통해 모았던 한국 데이터를 이용해 만든것도 있지만, 무엇보다 저 혼자서 수제맥주집 데이터들을 수집하는것에는 한계가 있기도 해서, 많은 사람들에게 수제맥주를 알리고, 여러 데이터를 수집하고자 이 프로젝트를 시작하게 되었습니다.
가게의 종류, 타입은 세개로 잡게되었는데 수제맥주를 직접 만들면서 만든맥주를 판매하는 브루펍,맥주를 만들진 않지만, 수제맥주를 전문적으로 판매하는 탭룸 , 맥주를 병,캔 등으로만 판매하는 바틀샵 이렇게 세가지로 분류를 하였습니다.
참고했던 프로젝트에는 AWESOME-SUSHI 프로젝트를 참고하였으며,AWESOME
이라는 단어로 시작하는 프로젝트를 많이 보게되어 이름을 AWESOME-BEER
로 결정하였습니다.
타일러
- 주소 : 서울 동대문구 하정로 46
- 종류 : 탭룸
- 특징 : 낮술, 혼술 하기 좋은 곳, 국내 맥주 위주로 준비되어있다.
- 홈페이지
크게보면 이렇게 README.md
파일에 어떤 가게인지 작성하는 그런 프로젝트입니다.
데이터 자체는 제가 모은것도 있었지만, 정말 감사하게도 맥주를 좋아하시는 많은 개발자 분들께서
데이터를 추가해주신 덕분에 현재는 221건 의 데이터가 수집되었습니다.
이 프로젝트는 README.md
에 모든 데이터를 보여주는 간단한 프로젝트입니다.
README.md
파일에 데이터를 텍스트로 계속 추가하는 간단한 프로젝트로 라고 생각했고,
천천히 추가해 나가면서, 그렇게 어렵지 않을 꺼라고 생각은 했지만..
데이터가 생각보다 많았습니다.. 아니, 너무 길었습니다.
README.md
파일에서 하나하나 건드리기엔 너무 길고 힘들었습니다.
그래서 결국 DB
를 써서 자동화를 하자 라고 생각했고, 일단 로컬에 깔려있던 MySQL
로 해보기로 하였습니다.
가지고 있던 데이터들, 그리고 어떤 칼럼들이 필요한지 종합해서 테이블을 간단하게 만들었고,
약 200개 정도되는 데이터들을 DB에 넣었습니다.
그후에 DB 데이터들을 README.md
파일로 생성하는 간단한 코드를 구축했습니다.
fs.writeFileSync("README.md", context, { flag: "a+" });
connection.query(query,
function (error, results, fields) {
if (error) throw error;
results.map((data) => {
var name = data["name"];
var temp = `* [${name}](#${name})\n`;
if (title != data["sidoNm"]) {
title = data["sidoNm"];
titleTag = `* [${title}](#${title})\n`;
temp = titleTag + temp;
}
fs.writeFileSync("README.md", temp, { flag: "a+" });
});
fs.writeFileSync("README.md", "## 지역\n", { flag: "a+" });
var title = "";
results.map((data) => {
var temp = `#### [${data["name"]}](${data["naverUrl"]})
- 주소 : ${data["address"]}
- 종류 : ${data["beerType"]}
- 특징 : ${data["desc"]}
- [홈페이지](${data["homepage"]})
`;
temp = temp.replace(/null/g, "");
if (title != data["sidoNm"]) {
title = data["sidoNm"];
titleTag = `### ${data["sidoNm"]}`;
temp = titleTag + "\n" + temp;
}
fs.writeFileSync("README.md", temp, { flag: "a+" });
});
fs.writeFileSync("README.md", footer, { flag: "a+" });
}
);
간단하게 이런 코드를 작성해서, DB에 저장된 데이터들을 README.md
파일로 만들어
계속 업데이트하는 방식으로 진행하였습니다.
그리고 CSV
, JSON
파일로도 export 할 수 있어서, Table을 export해, 프로젝트에 추가했습니다.
현재 repo 의 data
폴더를 보시게되면 csv, json 두개 형식의 파일이 있습니다.
맥주집 데이터들을 Readme.md
파일로만 두기보단, 여러 형식의 데이터로 지원했음 좋겠다 라는 피드백도 있었고, openBreweryDB
에서도 전체 파일을 CSV
같은 정형화된 데이터로 관리하고 있었기에, 해당 파일들을 추가했습니다.
그러던 와중에 "위경도 좌표도 있으면 어떨까?" 라는 생각이 들었는데, 전의 openBreweryDB
때 처럼 수작업으로 하나하나 하기엔..
221개 라는 숫자는 꽤 컸습니다.
그리고 계속 데이터도 추가될텐데, 이렇게 계속 하나하나 추가하기엔 너무 비효율적이라는 생각이 들었죠.
그래서 제가 찾은건 KAKAO 로컬API 였습니다.
주소를 입력해서, 좌표를 추출하는 Geocoding을 위 API로 선택하였는데,
이유는 무료(일 300,000 요청)인 것이 제일 컸습니다.
이처럼 로컬 API를 이용해서 200개 정도의 데이터들의 지오코딩을 진행했고, x,y 좌표를 추가했습니다.
이렇게 어느정도 자동화를 완료는 했지만 문제가 있었습니다.
데이터를 추가하는데 DB에 직접 하나 하나 입력해야한다는 단점이있었죠.
그래서 데이터를 관리 웹페이지를 하나 만들기로 했습니다.
🤔 어떤 기술을 써야 좋을까..
제가 이 프로젝트를 하면서 가장 힘들었던게 이 부분이었습니다.
어떤 기술을 써서 시각화를 할까? 그리고 어떤 방식으로 하는게 좋을까? 라는 게 제일 고민이었죠.
일단 이번 기회에 해보고 싶었던 Next.js
를 도입하기로 했습니다.
Route API
, 내부 Routing
등 좋은 기능들이 많이 보여서 선택한것도 있습니다.
사실 CRA로도 가능한데 한번 만져 보고 싶어서 한 것 도 있지만
Next.js
와 빠른 개발을 위해서 ChakraUI 를 선택했습니다.
현재 등록된 페이지들을 볼 수 있는 페이지로, 테이블 형식으로 개발하여 한눈에 볼 수 있게 만들었습니다.
테이블로 조회된 가게들 중 하나를 클릭하면, 가게를 수정할 수 있는 페이지로 들어갈 수 있습니다.
useQuery
를 사용해서 isLoading
상태일때는 Spinning
을 띄우고, 데이터들을 불러오고나서 화면에 데이터를 보여주게 했습니다.메인페이지의 등록하기
를 클릭하면 이동하는 페이지입니다. 가게를 직접 등록할 수 있습니다.
시도명, 가게명,도로명주소, 네이버지도 url, 가게타입, 가게 설명, 홈페이지 등을 직접 입력하고 등록 버튼을 누르게 되면, 도로명 주소
를 기준으로, 지오코딩
을 실행해, 가게와 맞는 주소의 좌표를 가져옵니다.
지오코딩 특성상 여러 주소가 나올 수 있는데, 이를 대비해, 여러 데이터가 나와도 맞는 주소를 찾을 수 있도록 검색된 모든 데이터를 선택할 수 있게 하였습니다. 검색된 주소 중 맞는 장소를 클릭하게 되면 등록이 완료되는데, 이를 메인페이지에서 확인 할 수 있습니다.
useForm
을 활용해 Form
데이터를 핸들링 하였습니다.Route API
를 이용해 Kakao 로컬API를 요청후, 리턴한 값을 useQuery
를 통해 핸들링 하였습니다.ChakraUI
의 Modal
을 활용해, 위치 선택 페이지를 추가했습니다.추가한 데이터에 대한 추가 및 삭제를 할 수 있는 페이지입니다.
만약 주소가 변경되었다면, 좌표변경 버튼을 클릭해서, 해당 주소에 따른 좌표를 가져올 수 있습니다.
데이터를 지워야한다면, 삭제 버튼을 눌러 데이터를 삭제 할 수 있습니다.
Next.js Dynamic Routing
을 활용해서 클릭한 가게 정보를 가져옵니다.지금까지 크게 보면 이렇게 세 페이지를 개발했습니다.
이렇게 개발을 진행하면서, 이 데이터들을 지도로 보여주는게 어떨까? 라는 생각도 동시에 들었습니다.
사실 데이터를 모으기만 했지, 시각화까지는 생각을 못해본 것이죠.
데이터를 보여주려면 Front-End는 Vercel
이 있지만, DB는 따로 호스팅이 필요한데
그렇기엔 지금 로컬의 MySQL
을 호스팅 하기엔 비용이 만만치 않았습니다.
RDB
를 호스팅할 이유도 그렇게 보이진 않았구요.
이거에 대해서는 좀 생각이 많았습니다.
유력한 후보군
일단 곰곰히 생각해본 결과, 그래도 가장 잘 알았던건 Mongo
였기에, 일단은 데이터를 연결하는게 우선이었으니 Mongo
을 도입하기로 했습니다. DynamoDB
도 많이 이야기를 들었지만,
완전히 처음이었기 때문에 살짝 거부감이 있기도 했구요.
그리 큰 프로젝트가 될것 같진 않아서 선택한것도 있지만.. 대학생이라 돈이없기도 해서...
Next.js
에 mongodb
를 추가했고, lib
폴더에 데이터를 추가하고,
CURD
메소드들을 각각 하나씩 만들었습니다.
참고 사이트 : https://www.mongodb.com/developer/languages/javascript/nextjs-with-mongodb/
지금까지 진행한 OpenBreweryDB
프로젝트와 AWESOME-BEER
프로젝트를 간략하게 설명하고,
이 프로젝트를 어떻게 진행 했는지를 간략하게 적어보았습니다.
이 글, 그리고 시리즈로 나올 글들의 결론은 맥주로도, 취미로도 얼마든지 프로젝트가 가능하다는 것입니다.
뭔가 만들고 싶으면 직접 코드를 치며 만드는 것. 그게 개발자 아니겠습니까?
지금까지 이렇게 흘러왔는데 참 재미있었던것같네요.
그리고 세삼 느낀건, 개발을 하면서 새로운 것들이 많이 떠올랐다는것도 있습니다.
~~한 기능들이 추가되면 어떨까
라는 생각말이죠.
예를 들면, 맥주집들을 보여주는 서비스를 만들자! 라거나,
등록 페이지에서 지오코딩 기능을 modal
로 처리하는건 어떨까? 같은 생각 말이죠.
그런 의문점을 직접 해결하면서 꽤 많이 성장했던 것 같습니다.
아무튼 1년 정도? 그정도 개발했던 기록들을 적으니 꽤 길었습니다.
긴글 읽어주셔서 감사합니다.
useTable
도입?AWESOME-BEER
프로젝트는 BEER-WARE 라이센스에 따릅니다.
만약 당신이 이 프로젝트가 가치가 있고, 좋았다고 생각하신다면, 언젠가 술집에서 본다면 맥주 한잔 사주시면 됩니다.
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <saup1965@gmail.com> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return freerhein.
* ----------------------------------------------------------------------------
*/
제가 아마.. 추가한 맥주집중 가본 곳이..
서울, 제주 는 2/3 정도 다녀왔었고, 부산은 1/3 정도 다녀왔었네요.
한 20곳 이상 다녀봤는데 전부 재미있고 맛있었습니다.