[NEMONE PLANTS] AI 통해 초보 식물 집사의 성장을 함께 만들어 갑니다
왜 만들었나
식물 이름을 검색하면 정보는 많이 나옵니다. 학명, 물주기, 빛, 이 정도는 블로그 글 하나만 잘 찾아도 됩니다. 문제는 그다음이었습니다. 마음에 든 식물을 저장해둘 곳이 없고, 몇 달 뒤 "이거 지금 심어야 하나?" 싶을 때 다시 찾아볼 방법도 없습니다. 검색으로 끝나는 서비스와, 저장하고 다시 찾아오게 만드는 서비스는 다릅니다. 저는 후자를 만들기로 했습니다.
1. 처음 계획은 다른 API였다
가장 먼저 붙인 건 해외 식물 데이터 API(Perenual)였습니다. 종 목록과 사진은 무료로 잘 나왔는데, 정작 핵심인 물주기·빛·생육 주기 필드를 열어보니 전부 이런 값이 들어 있었습니다.
"Upgrade Plans To Premium/Supreme To View This Data"
유료 플랜을 올려야 볼 수 있는 자리표시자였던 겁니다. 몬스테라로 직접 테스트해서 재확인한 뒤, 이 API로는 케어 정보를 채울 수 없다고 판단했습니다. 사진만 먼저 채우고 데이터는 나중에 붙이는 절충안도 잠깐 검토했지만, 어차피 다시 갈아엎을 걸 두 번 하지 말자고 정리하고 통째로 방향을 틀었습니다.
2. 진짜 데이터는 정부에 있었다
다음으로 본 건 농촌진흥청이 운영하는 농사로(nongsaro.go.kr) 오픈API였습니다. 문서와 승인 절차는 있었지만, 실제 호출 방법은 순탄치 않았습니다.
데이터셋마다 받은 참고자료가 zip 파일이었는데, 안에 든 샘플 파일명이 전부 한글이라 macOS 기본 압축 해제 도구가 인코딩을 못 잡고 깨졌습니다("Illegal byte sequence"). 파이썬으로 직접 압축을 풀면서 파일명을 CP949로 재해석해야 겨우 열 수 있었습니다.
더 까다로웠던 건 API 이름 자체였습니다. 샘플 코드에 적힌 오퍼레이션명을 그대로 호출하면 되겠거니 했는데, 실제로는 그 이름이 부가 기능(코드값 조회용)이고 진짜 데이터를 주는 오퍼레이션은 따로 있는 경우가 있었습니다. "정원 스타일" 데이터셋 하나는 cateGardenMakeList, cateGardenMakeInfoList 등 그럴듯한 이름을 열 개 가까이 순서대로 직접 호출해보고 나서야 정답이 cateGardenMakeLst(List가 아니라 Lst)라는 걸 알았습니다. 문서만 봐서는 알 수 없고, 직접 두드려보는 수밖에 없었습니다.
3. "내가 놓친 데이터가 있다"
데이터를 다 채운 뒤, 같은 농사로 데이터를 쓰는 다른 사이트(모두의농업)를 보다가 이상한 걸 발견했습니다. 제 쪽보다 화면에 나오는 정보가 더 많았습니다. 잎 색깔, 꽃 색깔, 생육형태 같은 필터가 제 상세페이지엔 없었던 겁니다.
원본 API 응답을 다시 열어보니, 제 수집기가 케어 카드에 필요한 6개 필드만 뽑아 쓰고 나머지는 그냥 버리고 있었습니다. 원본에는 잎색·꽃색·열매색·생육형태·번식방법·병충해, 그리고 독성정보까지 이미 들어 있었습니다.
특히 독성정보는 그냥 지나칠 수 없었습니다. 필드를 추가해 217종을 다시 수집해보니 46종에서 실제 독성 값이 나왔고, 그중엔 "복용 시 치명적 독성" 같은 문구도 있었습니다. 반려동물이나 아이가 있는 집이라면 몰라선 안 되는 정보인데, 데이터는 이미 API 안에 있었고 제가 안 가져다 쓰고 있었을 뿐이었습니다. 바로 스키마를 늘리고 상세페이지 상단에 경고 배너로 노출했습니다.
4. 사소해 보이지만 사용자는 바로 알아채는 것들
광고 위치 계산 실수: "PC에서는 카드 2번째 줄, 모바일에서는 3번째 줄에 광고를 넣어달라"는 요청을 받고 처음엔 "PC 4열이니 8번째 카드 다음, 모바일 2열이니 6번째 카드 다음"이라고 계산했습니다. 실제로 화면에 나온 걸 보니 둘 다 한 줄씩 밀려 있었습니다. "카드 N개 다음에 넣는다"는 건 그 줄까지 다 채운 직후를 뜻하는데, 그러면 4장만 채워도 PC는 1줄(2번째 줄 시작), 모바일은 2줄(3번째 줄 시작)이 동시에 맞아떨어집니다. 처음 요청받은 숫자가 정답이었는데 괜히 다시 계산해서 틀렸던 셈입니다.
썸네일이 도표 이미지로 잡히는 문제: 텃밭 가이드 글은 재배 캘린더 같은 글자 위주 이미지가 맨 처음에 나오는 경우가 많아, 그걸 그대로 썸네일로 쓰면 카드에서 잘려 알아볼 수 없었습니다.
alt="~사진"이 붙은 이미지를 우선하도록 바꿨는데, 그중 한 글은 원본 HTML 자체가alt="<실내 식물 재배기 />처럼 이스케이프가 깨져 있어서 태그를 파싱하는 정규식이 엉뚱한 곳에서 잘려 있었습니다. 태그 단위로 파싱하는 대신src="..."자체를 문서 전체에서 찾는 방식으로 바꾸고 나서야 해결됐습니다.최신 글이 항상 1페이지를 독점하는 문제: 목록을 등록일 순으로 정렬해뒀더니, 새로 수집한 배치가 매번 1페이지를 다 채워버렸습니다. 날짜를 시드로 쓰는 셔플로 바꿔서, 하루 동안은 순서가 그대로 유지되면서도(페이지 넘길 때 항목이 겹치거나 빠지지 않도록) 매일 자연스럽게 섞이게 했습니다.
5. 정보 사이트에서 관리 도구로 — 마이가든
식물 227종, 가드닝팁 242건을 다 채운 뒤에도 마음에 걸리는 게 있었습니다. 결국 "보고 나가는" 사이트라는 점이었습니다. 그래서 저장 기능(마이가든)을 붙였습니다.
- 네모네 계정 하나로 별도 가입 없이 로그인됩니다. 다른 네모네 서비스에 이미 로그인돼 있으면 PLANTS에서도 바로 인식됩니다.
- 식물·가드닝팁 카드에 하트를 누르면 마이가든에 쌓입니다.
- 저장한 식물의 개화 시기·파종 시기를 매달 대조해서, 마이가든 상단에 "이번 달 챙겨야 할 식물"을 알려줍니다. 저장만 해두고 잊어버리는 문제를 이걸로 풀었습니다.
여기까지가 오픈 시점의 모습이었습니다. 오픈하고 나서 진짜 문제가 시작됐습니다 — 검색 유입이었습니다.
6. 검색이 안 되는 콘텐츠였다
농사로 데이터로 만든 글 제목은 "습지형 바닥 플랜터(대형) 정원 만들기"처럼 정확하지만, 사람이 실제로 검색창에 치는 말은 아니었습니다. 사람들은 "화분 물주기 시간대"나 "장마철 화분 관리"처럼 증상이나 상황으로 검색합니다. 정부 데이터를 아무리 잘 정리해도 이 간극은 못 메웁니다.
그래서 검색어를 그대로 제목으로 쓰는 글을 따로 쌓기로 했습니다. 다만 이걸 새 CMS로 만들 필요는 없었습니다. 기존 글과 똑같은 테이블에 "출처(원본 vs 자체제작)" 구분값 하나만 추가하면, 이 값에 따라 구조화데이터 타입(설명형 글 vs 만드는 법)이나 본문 스타일, 사이트맵 우선순위를 다르게 주는 식으로 나머지는 다 재사용할 수 있었습니다.
처음엔 이 글들을 직접 마크다운으로 썼습니다. 표를 넣어야 하는 비교 콘텐츠(계절별 물주기 차이 같은)가 많아서, 직접 만든 변환기 대신 검증된 마크다운 라이브러리를 새로 설치했습니다. 이때 예전에 겪었던 사고가 떠올라 조심했습니다 — 다른 서비스에서 무심코 패키지 하나를 설치했다가 의존 라이브러리 버전이 올라가면서 전혀 관계없는 AI 기능이 조용히 깨진 적이 있었기 때문입니다. 이번엔 설치 전후로 충돌 검사를 돌려서 확인하고 나서야 넣었습니다.
7. 상단 이미지, 사진 없이 만들기
글마다 상단 이미지가 있어야 하는데, 스톡사진을 붙이면 브랜드 톤과 안 맞고, 매번 사진을 구해오는 것도 지속 가능한 방법이 아니었습니다. 그래서 사진 없이 브랜드 색상과 로고 아이콘만으로 카드형 배너를 코드로 직접 그리는 쪽을 택했습니다. 제목과 카테고리를 얹고, 로고의 새싹 아이콘을 아주 옅게 워터마크로 깔아 톤을 통일했습니다.
여기서도 함정이 있었습니다. 이 배너는 카드 목록(4:3 비율)과 상세페이지 히어로(16:9 비율) 두 군데에 모두 쓰이는데, 같은 이미지를 다른 비율로 자르다 보니 처음엔 4:3에서 잘 보이던 배지와 로고가 16:9로 자르면 위아래가 잘려나갔습니다. 실제로 잘리는 영역을 계산해서 그 안쪽에만 텍스트가 들어가도록 "세이프존"을 두고 나서야 두 비율 다 깨끗하게 나왔습니다.
또 하나, 한글을 그려 넣으려면 폰트가 필요한데 처음엔 이 작업을 하던 맥의 시스템 폰트를 그대로 썼습니다. 나중에 이 생성 과정을 서버에서도 돌려야 하는 상황이 오면서 이 폰트가 서버(Linux)엔 없다는 게 문제가 됐는데, 이 얘기는 뒤에 다시 나옵니다.
8. 광고, 배치를 세 번 고쳤다
광고를 어디에 얼마나 넣을지도 한 번에 정해지지 않았습니다. 처음엔 구글의 반응형 자동 크기 옵션을 그대로 뒀는데, 이게 화면마다 세로로 얼마나 커질지 예측이 안 돼서 레이아웃이 들쭉날쭉했습니다. 높이를 고정하는 슬림한 가로형 배너로 바꾸고, 미디어쿼리로 PC와 모바일 모두 세로로 안 커지게 잡았습니다.
배치 위치도 오해가 몇 번 있었습니다. "오늘의 가드닝팁 아래에 광고를 놓자"는 요청을 처음엔 "새 광고 자리를 만들자"로 이해했는데, 실제로는 이미 다른 곳(월별 추천 식물 그리드 중간)에 있던 광고를 그 자리로 옮겨달라는 뜻이었습니다. 광고 위치를 정할 땐 "새로 만드는 건지 옮기는 건지"를 먼저 확인해야 한다는 걸 배웠습니다.
9. 손으로 쓰던 글을, AI가 초안 쓰게
자체 제작 글이 쌓일수록 손으로 쓰는 속도가 병목이 됐습니다. 그래서 키워드만 넣으면 초안을 써주는 관리자 화면(/admin)을 만들었습니다. 원칙은 하나였습니다. AI가 쓴 글을 검수 없이 바로 노출하지 않는다.
키워드 입력 → AI가 제목/본문/태그를 초안으로 작성 (여기서 저장 안 함)
→ 화면에서 검토·수정
→ "발행" 버튼을 눌러야 실제로 DB에 들어감
앞서 만든 썸네일 생성기가 제 컴퓨터의 시스템 폰트를 쓰고 있었는데, 관리자 화면은 서버에서 돌아가야 하니 그 폰트가 없어서 실패하는 구조였습니다. 오픈소스 한글 폰트를 저장소에 같이 넣어서 어디서든 똑같이 생성되게 바꿨습니다. 이제는 관리자가 발행 버튼을 누르는 순간 서버가 직접 썸네일까지 만듭니다.
10. 사진 한 장으로 시작하는 진단 — AI Plant Companion
여기까지 만들고 나니 확신이 들었습니다. 결국 이 서비스를 다른 도감 사이트와 갈라놓는 건 "내 식물 사진을 찍어서 물어볼 수 있는가"였습니다. 그래서 브랜드 슬로건부터 "초보집사의 성장을 응원합니다"에서 **"당신과 식물이 함께 자라는 시간"**으로 바꾸고, 그 아래 AI PLANT COMPANION을 붙였습니다. 이제 메인 화면 맨 위는 도감이 아니라 진단 유도 배너입니다.
구조는 이렇습니다. 사진을 올리면 Gemini가 사진을 보고 어떤 식물인지, 상태가 어떤지, 무엇을 해야 하는지를 JSON으로 돌려주고, 그걸 곧바로 한 편의 글처럼 저장합니다. 진단 1회가 곧 API 호출 1회(유료)라 계정당 하루 3회로 제한했고, 사진은 브라우저에서 먼저 줄이고(1280px) 서버에서 한 번 더 줄여(900px) 폰 사진 기준 1.87MB짜리가 116KB로 떨어지게 했습니다.
여기서도 크고 작은 함정이 있었습니다.
태그 표기를 자유롭게 두지 않았다: 처음엔 AI가 증상 태그를 알아서 짓게 뒀는데, 그러면 "과습"과 "물 과다"처럼 표기가 갈려서 기존 가드닝팁·쿠팡 상품과 매칭이 안 됩니다. 그래서 프롬프트에 기존 서비스에 이미 쓰이는 태그 어휘를 우선순위로 못박았습니다. 진단이 곧 콘텐츠 허브가 되려면 새 데이터가 기존 데이터와 같은 말을 써야 한다는 걸 다시 확인한 셈입니다.
"~로 보이는 식물"이 도감 연결을 다 놓치고 있었다: AI가 확신이 없을 때 "다육식물 (에케베리아로 보여요)"처럼 답하는데, 도감 이름과 정확히 일치시키는 로직으로는 이런 응답을 거의 다 놓쳤습니다. 학명 일치 → 이름 정확일치 → 도감 이름이 응답 문장에 포함되는지(긴 이름 우선) 순으로 점점 넓혀가서야 실제로 연결되기 시작했습니다.
업로드한 사진이 프로덕션에서만 404가 났다: 배포하고 실제로 사진을 올려 확인하는데 방금 올린 사진이 안 보였습니다. 원인은 Next.js standalone이 빌드 시점에 존재한 public 폴더 파일만 서빙한다는 점이었습니다. 런타임에 새로 저장한 파일은 서버 입장에서 "모르는 파일"이라 404가 났던 겁니다. 백엔드가 그 사진을 직접 내려주는 엔드포인트를 하나 만들어 우회했습니다.
그런데 이 문제를 고치다가 더 오래된 버그를 하나 발견했습니다. 관리자가 글을 발행할 때 서버에서 생성되는 썸네일도 똑같은 이유로 이미 깨져 있었던 겁니다. 서버 에러 로그에 "isn't a valid image ... received null"이라는 흔적이 이미 쌓여 있었는데, 아무도 눈치채지 못하고 있었습니다. 같은 방식으로 고치면서, 이번엔 next.config의 API 프록시 설정 자체가 빌드할 때 주소가 굳어버려서 프로덕션에서도 로컬 기본 주소를 가리키고 있었다는 것까지 함께 찾아냈습니다. 브라우저 요청은 nginx가 알아서 올바른 주소로 보내줘서 여태 아무 문제가 없어 보였을 뿐, 실제로는 곪아 있던 설정이었습니다.
11. 진단을 혼자만 보게 둘 이유가 없었다
처음엔 진단 결과를 마이가든에만 쌓았습니다. 그런데 "다른 사람 진단도 같이 봐야 서비스가 살아있어 보인다"는 지적을 받고 나서야, 저 혼자 쓰는 기능처럼 만들어 놨다는 걸 깨달았습니다. 그래서 공개 피드를 추가했습니다.
- 작성자는 표시하지 않습니다. 백엔드 응답 자체에 사용자 식별값을 아예 넣지 않아서, 코드를 아무리 들여다봐도 "누가 올렸는지"가 새어나갈 구멍이 없습니다.
- 대신 사진에 집 안이 찍힐 수 있으니, 마이가든에서 진단마다 공개·비공개를 직접 토글할 수 있게 했습니다.
- 메인 화면 상단의 "오늘의 가드닝팁" 자리를 이 피드로 바꿨습니다. 페이지 하단에 같은 성격의 가드닝팁 섹션이 이미 있어서 위아래로 내용이 겹치고 있었기 때문입니다. 다만 이 자리는 관리자가 "메인 고정" 체크한 글을 우선 노출하는 용도이기도 했어서, 그 기능이 사라지지 않도록 하단 섹션이 고정글을 맨 앞으로 끌어오게 다시 연결했습니다.
피드를 만들고 나서 바로 다음 문제가 드러났습니다. 카드를 눌러도 진단 내용을 읽을 방법이 없었던 겁니다. 도감으로 바로 연결해뒀는데, 정작 궁금한 "이 식물이 왜 이런 상태인지"는 못 보고 넘어가는 구조였습니다. 진단 하나하나에 상세 페이지를 만들어 사진과 진단 전문, 태그, 도감 링크를 다 보여주게 고쳤습니다. 다만 사용자 사진과 AI 소견이 계속 쌓이는 페이지를 전부 검색에 노출시키면 비슷비슷한 얕은 글이 늘어나 사이트 전체 평가를 깎아먹을 수 있어서, 개별 진단 페이지는 색인 대상에서 뺐습니다. 대신 진단들을 모아 보는 목록 페이지 하나만 색인되게 하고, 링크는 계속 따라가게 열어뒀습니다.
"진단이 100개 쌓이면 그게 다 한 화면에 풀리는 거냐"는 질문도 받았습니다. 미리보기는 이미 최신 몇 개로 제한해뒀지만, 그럼 나머지는 어디서 보냐는 게 맞는 지적이었습니다. "나중에 트래픽 늘면 그때 만들자"고 답했다가 "왜 그걸 미리 안 만드냐"는 말을 듣고, 전체 목록과 페이지 넘김을 그 자리에서 바로 만들었습니다.
12. 쿠팡·광고를 전 페이지에 넣었다가 되돌린 이야기
진단 페이지에 쿠팡 파트너스 상품과 광고를 붙여달라는 요청을, 처음엔 사이트 전체(목록 페이지까지 포함)로 확대 해석해서 작업했습니다. 홈, 식물 목록, 가드닝팁 목록, 마이가든까지 전부 붙이고 나서야 "목록 페이지에는 넣지 말라는 거였다"는 정정을 받았습니다. 상세페이지(식물/가드닝팁/진단)에만 남기고 나머지는 되돌렸습니다. "전체 페이지"라는 말을 들었을 때 어디까지가 대상인지 먼저 확인했어야 했습니다.
13. 목록 페이지에 정작 페이지 번호가 없었다
전체 식물도감과 가드닝팁이 각각 264건 가까이 쌓였는데, 두 목록 다 페이지 구분 없이 전부 한 화면에 그리고 있었다는 걸 뒤늦게 알아챘습니다. "분명 만들어뒀던 것 같은데"라는 말을 듣고 코드를 다시 보니, 실제로 없었습니다. 식물 목록은 검색어를 유지한 채 페이지를 넘기게, 가드닝팁 목록은 이미 실시간 검색 중이라 검색어가 바뀌면 1페이지로 되돌아가게 만들어 붙였습니다.
무엇이 완성됐나
- 식물 227종 — 학명·물주기·빛·난이도·심는 시기·개화 시기·최저 견딜 온도·과(科)·원산지·생육형태·잎꽃열매 색상·번식방법·병충해·독성정보
- 가드닝팁 264건 — 정부 데이터 기반 231건 + 실제 검색어 기반 자체 제작 33건
- AI 식물 진단 — 사진으로 종류·상태 진단, 계정당 하루 3회, 다른 사람 진단을 익명으로 함께 보는 공개 피드
- 검색, 카테고리 필터, 월별 추천 식물, 태그 기반 탐색, 목록 페이지네이션
- 마이가든 — 저장, 개화·파종 알림, 진단 기록·공개 설정, 네모네 통합 계정
- 관리자 도구 — 키워드로 초안을 만들고 검토 후 발행하는 콘텐츠 파이프라인
다음 과제
진단 사진은 서버 디스크에 직접 쌓입니다. 계정당 하루 3회 제한이 있어 당장은 문제가 없지만, 사용자가 늘면 이 디스크 용량이 계속 줄어들기만 한다는 걸 압니다. 지금은 손대지 않고, 실제로 용량이 부담될 시점에 오래된 사진을 정리하거나 별도 저장소로 옮기는 식으로 풀 생각입니다.
그리고 진단이 그 자리에서 끝나지 않게 만드는 일은 이제 시작입니다. "과습 같아요"로 끝나는 게 아니라 그 증상을 다룬 글로 이어지게는 해뒀지만, 반대로 사람들이 자주 물어보는데 아직 다룬 글이 없는 증상이 쌓이면, 그게 다음에 써야 할 글의 힌트가 됩니다. 콘텐츠가 진단을 돕고, 진단이 다시 콘텐츠가 필요한 곳을 알려주는 구조 — 쓰는 사람이 많아질수록 도감도 팁도 같이 채워지는 서비스를 계속 만들어가려고 합니다.
당신과 식물이 함께 자라는 시간 | https://plants.nemoneai.com

COMMENTS
의견을 남기려면 로그인이 필요합니다.