kikitori Tech Blog

株式会社kikitoriは、農業流通現場のDXを実現するSaaS『nimaru』と青果店『KAJITSU』を運営する会社です。

JavaScript エコシステムでバイナリデータを扱う API の歴史+チートシート

こんにちは。kikitori の永谷です。

テックブログの執筆が一巡したので、改めて私からスタートです。 前回の一巡はテックブログと言いつつテックではない話も多かったので、今回はもう少し技術的な内容も書いていければなと考えています。

というわけで今回は JavaScript エコシステムにおけるバイナリデータの扱いについての記事です。

どうしてこの記事を書こうと思ったのか

弊社のプロダクト「nimaru」はフルスタック TypeScript 構成で開発しています。 農産物という不確実な商品を扱う都合上、画像や PDF ファイルなどバイナリデータを取り扱う処理が多く登場します。

最近もそのあたりのコードレビューを何度か行いましたが、よくコメントするのが、Web API に準拠するのか、Node.js API に寄せるのかという点についてです。

日本語で体系的にまとまっている資料が少なく、しかも歴史的な経緯を知らないと混乱しやすいテーマです。

この記事では、それぞれの API がどのように生まれ、どう関係しているのかを整理してみます。

JavaScript がバイナリを扱えるようになるまで

JavaScript が最初にバイナリデータを扱えるようになったのは、2009 年の Node.js の登場がきっかけでした。

Node.js はネットワーク通信やファイルI/Oを効率的に行うために、文字列ではなくバイト列を直接扱う必要があり、そのために Buffer オブジェクト が導入されました。

Buffer は低レベルなメモリ領域を直接操作できる仕組みで、サーバーサイドでのバイナリ処理を支える重要な要素になりました。

一方で、2010 年ごろにはブラウザ側でも似たようなニーズが生まれます。 WebGL が登場し、GPU に数値配列を渡すために高速なメモリ操作が必要になったのです。

この問題を解決するために考案されたのが ArrayBufferTypedArray で、これは WebGL のための技術として誕生しました。

後にその有用性が広く認められ、2015 年の ECMAScript 2015(ES6) で正式に言語仕様に統合されます。 この時点で、ブラウザ側では ArrayBuffer / TypedArray、サーバー側では Buffer という二系統のバイナリAPI が併存する形になりました。

さらに 2012 年以降、Browserify や Babel、Webpack などのツールが登場し、Node.js のモジュールをブラウザでも動かせるようになります。

その結果、Node.js の Buffer をブラウザで再現する polyfill(npm パッケージ buffer)が普及。 Node.js とブラウザのエコシステムが急速に融合し、現在のように両方の API が混在する環境が生まれました。

バイナリ APIの関係図(チートシート

こうした背景のもとで、JavaScript エコシステムには現在

  • ECMAScript 標準の ArrayBuffer 系列 (ArrayBuffer, TypedArray, DataView)
  • Node.js 由来の Buffer

の二系統が存在します。

その全体像を以下の図にまとめました。

JavaScript エコシステムでバイナリデータを扱うオブジェクトのチートシート

なお、この図には関連する Web API である File や Blob も併記しています。

API の詳細については次の通りになります。

ArrayBuffer (ECMAScript 標準)

「生のメモリ領域」を表す、バイナリデータを扱うための最も基本的なオブジェクトです。 バイト単位で固定長の領域を確保し、その中身を直接読み書きすることはできません。 実際の操作は TypedArrayDataView などのビューを通じて行います。

TypedArray (ECMAScript 標準)

ArrayBuffer の内容を型付きで効率的に操作するためのビューです。 TypedArray オブジェクト自体は公開されておらず、Int8ArrayFloat64Array のように、値の型ごとに異なるサブクラスを使用します。

通常の配列に近い構文で操作できますが、通常の配列と異なり、インデックスアクセスはプロトタイプチェーンを辿りません。具体的に言えば、Object.prototype["0"] = 123 としても new Uint8Array()[0] === undefined です。これにより、通常の配列へのアクセスよりもロジックを簡略化でき、高速化に寄与しています。

なお、Uint8Array は C でいう char[] に近く、「バイト列」の表現として最も自然な API なので、ReadableStream や Fetch API のレスポンスなど、さまざまな Web API で標準的なバイト列表現として利用されており、単なる「ビュー」以上の存在です。

ArrayBuffer の一部分のみから TypedArray を作ることもできるので、 new Uint8Array(oldArray.buffer) はもとの TypedArray とは必ずしも同じサイズにならないことに注意が必要です (byteOffset, byteLength プロパティで位置が分かる)。

  • Uint8Array: 最も汎用的。0〜255 の整数を扱う。
  • Int8Array: 符号付き 8 ビット整数。
  • Float64Array: 64ビット浮動小数点数
  • Float32Array, Uint16Array, Int32Array など他にも多数。

DataView (ECMAScript 標準)

ArrayBuffer をより柔軟に操作するためのビューです。

TypedArray が単一の数値型を扱うのに対し、DataView は任意のバイト位置から任意の型を読み書きできるほか、プラットフォームのアーキテクチャに依存せず好きなエンディアンを使用できます。

便利そうなのですが、一般的な Web アプリケーションで使うのはたいてい Uint8Array なのであまり出番はありません。独自フォーマットのファイルを解析するときとかには便利かもしれませんね。

Blob (Web API)

Blob は イミュータブルなバイト列を抽象的に参照するオブジェクト です。

この「バイト列」がどこに存在するか(メモリ、ファイル、ネットワークキャッシュなど)は実装に依存し、必ずしもメモリ上に読み込まれているとは限りません。 そのため、内容を一度にすべて扱う textarrayBuffer メソッドの呼び出しは、内部でストレージやネットワークからデータを読み出す可能性があるため非同期処理となり、結果としてコピーも発生します。

File (Web API)

Blob を継承したオブジェクトです。Blob が純粋に「データのかたまり」であるのに対し、File はそれに ファイル名 (name)・更新日時 (lastModified) などの「ファイル」に必要なメタ情報が追加されています。

ブラウザで <input type="file">ドラッグ&ドロップ操作を通じて取得できるのは、この File オブジェクトです。

Buffer (Node.js API)

BufferNode.js が独自に持つ伝統的なバイナリ API です。もともとは C++ のネイティブメモリを扱うために設計されましたが、現在は Uint8Array のサブクラスとして実装されています。 現在でも多くの Node.js 標準 APIBuffer を返しますが、内部的には Uint8Array と互換性があるため、ブラウザとの境界は徐々に薄れつつあります。

まとめ

JavaScript でバイナリデータを扱うために、ECMAScript 由来の API と Node.js 由来の API があることを見てきました。

なお、Node.js の BufferUint8Array として実装されるようになったことからも分かる通り、近年の Node.js は ECMAScript 標準、Web API との互換性を重視するようになっています。

新しく書くコードでは、可能な限り標準に準拠した API を使っていきたいですね!

We're hiring!

私たちは、すべての人の生活に不可欠な「食」の基盤となる「農業」を、テクノロジーの力で支える、縁の下の力持ちとも言えるプロダクトを作っています。 私自身、難しいこと、これまで誰も取り組んだことがなかったこと、他の業界では見られない現場のリアルなど、こういった文面や資料では伝えきれない多くのチャレンジのあるドメインだと感じています。 ぜひ一度、ゆっくりお話ししましょう!

ご興味をお持ちいただけた方はこちらまで↓↓↓

herp.careers

0→1フェーズを高速に立ち上げるための要点

kikitoriでエンジニアマネージャーをしている坂村です。 青果流通の新しい事業を立ち上げるなかで、これまでの0→1フェーズでの経験を活かしつつ、日々チームで挑戦しています。

本記事では、その経験をもとに 高速に0→1フェーズを立ち上げるための要点 を整理します。 技術的な工夫はもちろん、チームづくりや文化面の工夫についても触れますので、kikitoriの開発文化を知っていただくきっかけになれば嬉しいです。

要件定義

新規事業の立ち上げでは、ビジネスの仮説は発案者が持っていることが多いため、仮説の立て方そのものには触れません。 ただし、その仮説や信念、あるいはひらめきを 発案者と同じレベルで自分ごと化すること がとても重要だと考えています。

そのうえで、我々エンジニアは事業を技術的な視点から解像度を高めていきます。

  • 今後どんな付加価値を提供できるか
  • 採用する技術が運用コストを高めてしまわないか
  • 技術自体を参入障壁にした場合、その陳腐化リスクをどう見るか

たとえばAIがコモディティ化しつつある近未来においては、「AIそのもの」だけで優位性を担保するのは難しくなっていくでしょう。

次に、サービスが提供する価値をどうやってエンドユーザーに届けるのかを、ユースケースとして分解します。この過程で大枠の機能要件が見え、データの流れや外部連携も整理されます。ユースケース図や全体のワイヤーフレームを作りながら、事業とサービスの解像度を高めていきます。

開発

個人的な感覚ですが、要件が6割程度固まった段階からは同時並行で開発を進め 実際に動くものを見せながら共通認識を形成する 方が早いです。

もちろん作り直しは発生しますが、そこは「プロトタイプだから仕方ない」と割り切ります。設計と開発を明確に分け、レビューを通して承認を得る…といったフローは0→1フェーズにはスピード感が合いません。

ただし、手戻りを最小限に抑える工夫は必要です。

  • 変更が入りそうなテーブルは正規化しておくことで、柔軟性を担保しつつ後の仕様変更に耐えやすくする
  • バックエンドはインターフェースを先に定義し、実装はDIで差し替えられるようにする

こうした仕込みをしながら、仕様変更や方向転換があっても極力追加工数を増やさない工夫を施します。

チーム

0→1フェーズは 少数精鋭 が圧倒的に進めやすいです。

採用観点でいえば、技術を突き詰めるタイプよりも 事業に共感できるタイプ の方が適しています。要件定義と開発を並行して進めるため、常にチームで共通理解を得ながら走り続ける必要があり、大規模なチームだとマネジメントコストが高すぎるのです。また、エンジニア自身も自分はサービス全体のどこの何を作っているのかという意識づけを常にしておくこと、マネージメント側からするとそういうインプットをメンバーにし続けることもポイントになります。でないと、せっかく担当機能を作ったのに結合してみるとちょっと思ったのと違った、みたいな状況になりかねません。ただただ仕様や設計をまとめてエンジニアに渡すのでは0→1フェーズではうまくいきません。

さらに、0→1フェーズでは要件や仕様が変わることは避けられません。確度の低いものは後回しにする工夫をしても、最後はどうしても変更が発生します。 だからこそ 変化に強いチーム構成 を意識することが重要です。

また、特に我々の青果流通ドメインは学習コストがとても高いため、単に技術に強いだけでは立ち上げられません。 生産者さん、JA関係者や市場事業者や運送事業者との会話から要件を拾うことも多く、事業に強く共感できるメンバー でないとキャッチアップが難しいのです。

まとめ

要件定義では、仮説を自分ごと化し、ユースケースから解像度を高める。 開発では、動くものを早く見せつつ、壊れても耐えられる設計を仕込む。 チームは、事業共感と変化耐性を持つ少数精鋭で臨む。

kikitoriでは青果流通という巨大な産業を舞台に、こうした0→1フェーズの挑戦を続けています。不確実性の中でスピード感を持って事業を立ち上げるフェーズにワクワクできる方と、一緒に新しい価値を作っていければ嬉しいです。

現在、kikitoriではエンジニアメンバーを募集しています。

0→1フェーズの事業立ち上げに興味のある方、事業づくりと技術の両輪で挑戦したい方はぜひ採用ページをご覧ください。

自社SaaSに最適なAIコードレビューはどれ?4つのツールを比較して分かったこと

こんにちは。株式会社kikitoriでエンジニアをしている岩本です。

弊社では、AIを活用した業務改善に全社で取り組んでいます。 その一環として、開発時のコードレビューにAIを活用する試みで得られた知見をご紹介します。

AI自動コードレビューツールの選定

ツールの選定にあたり、以下の3つの観点を重視しました。

* ドメイン知識やビジネスロジックを考慮したレビューが可能か

私たちが開発するJA・市場向けの業務SaaS「nimaru」は、専門的な業務知識や複雑なドメインを扱います。そのため、単なる構文チェックに留まらず、プロダクト固有のドメイン知識やビジネスロジックを反映したレビューができることが、ツールを導入する上での重要な要件です。

具体的には、Jiraチケットに記載された仕様をAIが理解し、実装の妥当性や考慮漏れを指摘できるかを重視しました。

* チームの開発フローに馴染むか

チームの一員として自然に受け入れられ、開発フローを妨げない使いやすさも重要な観点です。

* コストは妥当か

機能に見合った価格で、費用を抑えられることが望ましいです。

選定候補ツール

上記の観点とJira連携などを考慮し、以下4ツールを候補としました。

Qodo Merge

オープンソースのPRレビューツール「pr-agent」を企業向けに拡張したサービス。

TOML形式の設定ファイルで細かくカスタマイズでき、RAG技術によるコードベース全体の分析も可能です。

価格: 開発者1人あたり月額38ドル

qodo-merge-docs.qodo.ai

Code Rabbit

対話形式でコードレビューを進められるツールです。専用UIまたは設定ファイルでレビュー内容を柔軟に調整できます。

価格: 開発者1人あたり月額30ドル

docs.coderabbit.ai

Greptile

コードベース全体を読み込み、レビューを行います。

特徴的なのは、レビュアー(人間)のコメントも学習し、使えば使うほどプロジェクトに最適化されていく点です。

Jiraだけでなく、NotionやGoogle Driveのドキュメントを知識ソースとして読み込める点も魅力です。

価格: 開発者1人あたり月額30ドル

www.greptile.com

www.greptile.com

Claude (Anthropic)

AI レビュー専用ツールではありませんが、社内でコーディング支援AIとして利用実績のあるLLM「Claude」でGitHub Actionを使いコードレビューにも活用でき既に導入済みいうことで、比較対象としました。

価格: API利用量に応じた従量課金制

導入と比較評価

比較方法

実際の開発案件を題材に、各ツールを試しました。

題材: 特定の項目をCSVダウンロードする機能の開発

準備1: Jiraに受け入れ条件を詳細に記載

Code Rabbitに明確なチケットの記載例が載っていたのでそれを参考に設定

docs.coderabbit.ai

準備2: 受け入れ条件を意図的に満たさないコミットを一部作成し、AIがそれを指摘できるか検証

評価結果

Qodo Merge

良い点

  • TOMLファイルによる設定の自由度が高く、他のツールより詳細なカスタマイズが可能です。
  • Jira連携の精度が高く、チケットの内容を深く理解した上でのレビューが見られました。

気になる点

  • 他のツールに比べてレビューの指摘事項数が少ない印象です。

tomlファイル設定例

PR上AIツールからの指摘で受け入れた事項は次回以降考慮されます

Qodo Merge PR Jiraチケット分析

Qodo Merge PR 指摘サマリ

Qodo Merge PR 指摘例

Code Rabbit

良い点

  • 他のツールに比べて導入が簡単で、yamlの設定項目もドキュメント見て設定しやすいです。
  • 処理の流れをシーケンス図で自動生成してくれるため、視覚的な理解がしやすいです。

気になる点

  • Jiraチケットの仕様を反映した指摘が少なく、コードの細かな文法チェックが中心でした。

Code Rabbit ウォークスルー

Code Rabbit yamlファイル設定例

Code Rabbit PR指摘例

Greptile

良い点

  • 条件に合致するスタートアップは割引があります。

気になる点

  • レビューのカスタマイズには試行錯誤が必要で、設定項目の参考例が少なかったです。

  • 初期設定からサービスが利用可能になるまでに少し時間がかかりました。

Greptile設定画面

Greptile Context 設定

Greptile PR サマリ

Greptile PR Score

Greptile PR 指摘例

Claude

良い点

  • 指摘の的確さと分かりやすさは、今回試した中で最も優れていました。

  • 正式なJira連携機能はないものの、PRのdescriptionに仕様を書き出すという簡単な工夫で、仕様の考慮漏れなどを的確に指摘できました。

(画像:指摘の例、レビュー総評)

Claude サマリー

Claude PR 指摘例

Claude PR 総評

チーム内での評価

各ツールのレビュー結果をチーム内で比較したところ、「端的かつ仕様の要点を網羅している」として、Claudeのレビューが最も高く評価されました。

まとめ

今回の比較検証を経て、現在の私たちのチームに最もフィットするのはClaudeであるという結論に至りました。

その理由は、指摘の質の高さと、簡単な工夫でドメイン知識を反映させられた柔軟性にあります。重視したドメイン知識を考慮したレビュー」という観点では、ツールごとにアプローチが異なり、今回の検証ではClaudeとQodo Mergeが特に有効でした。

コスト面でも、Claudeの従量課金制は、私たちのチーム状況によって月額固定料金のツールより費用を抑えられる可能性があります。

現状、複雑なロジックの妥当性評価はまだ人間に分がありますが、仕様の考慮漏れを指摘するアシスタントとしては、AIはすでに非常に有用です。

そしてツールを比較する中で、今後AIレビューの質をさらに高めるには、プロジェクトに合わせて「AIを育てていく」という視点が重要だと改めて感じました。

株式会社kikitoriでは、今回の取り組みを足がかりに、今後もAIを活用した業務改善と開発効率の向上に積極的に取り組んでいきます。

(※本記事は2025年7月時点の情報に基づいています。各ツールの最新の価格や機能については、公式サイトをご確認ください。)

React 18 へのアップグレード: 新バージョン非対応の依存ライブラリへの対応

こんにちは。 株式会社 kikitori でエンジニアをしている小川です。

kikitori では JA や卸売市場向けの SaaS「nimaru」を開発しています。

nimaru のフロントエンドは TypeScript + React で構築しており、ローンチから約5年間 React 17 を使用してきました。

このたびようやく React 17 を React 18 にアップグレードしたのでその手順と対応内容をまとめました。

主な対応内容

今回のアップグレード対応は、大きく以下の2点に分かれました。

  • アプリケーションコードの React 18 対応
  • 依存ライブラリの React 18 対応

アプリケーションコードの React 18 対応

React 17 から React 18 への変更内容は内部的な変更が主で、アプリケーションコードが直接影響を受ける変更はそれほど多くありません。

How to Upgrade to React 18

nimaru で対応が必要だったのは以下の3点です。

これらの変更は将来の仕様変更に備えての非推奨化だったので tsceslint による静的解析で検出でき、公式ガイドに沿って対応できました。

※ JSX 名前空間の変更 は React 19 で行われた変更でしたが、React 18.3 でも導入されたため同時に対応しました。

依存ライブラリの React 18 対応

React をアップグレードすると、当然ながら React に依存する各種ライブラリにも影響が出ます。 nimaru で利用しているライブラリのいくつかも React に依存しており、React 18 では不具合が発生したものがありました。

ほとんどの不具合は利用する API を変更するか同等の機能を持つ別のライブラリへの置き換えで解消できましたが、1つだけ代替手段がなく独自に対応する必要がありました。

react-qr-reader

nimaru ではアプリ内の各所でQRコードの読み取りを行っており、そのために react-qr-reader を使用していました。

しかし、React 18 では react-qr-reader で一度カメラを起動するとブラウザをリロードしない限りカメラを停止できないという不具合が発生しました。

react-qr-reader/cant use this library in react@18.2.0

このライブラリは3年以上更新されておらず、公式での修正も期待できない状況でした。幸いMITライセンスで公開されていたため、自分たちで修正を試みることにしました。

まずは GitHub の Issues に解決方法が投稿されていないかを確認しましたが、同様の不具合に関する報告は多数あったものの明確な対処法は見つかりませんでした。

react-qr-reader は、バーコード処理用のライブラリ zxing-js をラップして React コンポーネントとして提供する構成になっており、カメラの制御は主に zxing-js 側で行われています。

そのため zxing-js の Issue を確認したところ以下の投稿を見つけました。

How to stop the reader and turn off the camera

そして このコメント にメディアストリームの停止と video 要素のクリーンアップすることでカメラを停止する方法が投稿されていました。

この処理を react-qr-reader のカメラ停止処理に組み込みます。react-qr-reader では useEffect のクリーンアップ関数でカメラを停止しています。

// from: https://github.com/JodusNodus/react-qr-reader/blob/master/src/QrReader/hooks.ts

export const useQrReader: UseQrReaderHook = ({
  scanDelay: delayBetweenScanAttempts,
  constraints: video,
  onResult,
  videoId,
}) => {
  const controlsRef: MutableRefObject<IScannerControls> = useRef(null);

  ...

  useEffect(() => {
    ...

    return () => {
      controlsRef.current?.stop();
    }
  }, []);

この useEffect のクリーンアップ関数に先ほどの Issue で紹介されていたカメラ停止処理を追加します。 また依存配列も空配列のままだったため依存変数を追加しました。

  useEffect(() => {
    ...

    return () => {
      controlsRef.current?.stop();
+     controlsRef.current = null;
+     BrowserQRCodeReader.releaseAllStreams();
+     const videoElement = document.getElementById(videoId) as HTMLVideoElement;
+     if (videoElement) {
+       BrowserQRCodeReader.cleanVideoSource(videoElement);
+     }
    };
-  }, []);
+  }, [videoId, scanDelay, onResult, constraints]);

この修正により React 18 でも react-qr-reader が正常に動作するようになりました。

React 18 では useEffect の挙動が変更されており、Strict Mode 有効時は開発環境でセットアップとクリーンアップが2回実行されるようになりました。

コンポーネントのマウント時にエフェクトが 2 回実行される

この仕様変更によりクリーンアップ処理が不完全な場合は従来とは異なる挙動になる可能性があるとアナウンスされていました。 react-qr-reader のカメラの停止処理は useEffect のクリーンアップ関数で行われており、今回の不具合もこの仕様変更よるものと考えられます。

振り返って

nimaru で使用しているライブラリは定期的にアップデートしていますが、破壊的変更を含むメジャーバージョンアップはどうしても慎重にならざるを得ず後回しになりがちです。 今回ようやく重い腰を上げて React のアップグレードに取り組みましたがやはり一筋縄ではいきませんでした。

また React 18 への移行は一度にリリースするのではなく、React 17 でも適用可能な変更から少しずつ反映していく方針を取りました。 こうした段階的なリリースにより一度のリリースで発生しうる影響を最小限に抑え、他の機能開発を妨げることなくアップグレードを進められました。 もちろんリリースの分割には手間もかかりましたが、最終的には延べ8,000行以上のコードを変更することになったため結果としては正解だったと思います。

現場の声を大事にする!kikitoriデザイナーの新機能リサーチ

こんにちは。kikitoriでデザイナーをしている太田です。

現在kikitoriには、業務委託を含めて4名程のデザイナーが所属しています。 業務としては、主に仕様設計などプロダクトに関する業務を行いますが、事業紹介映像・販促チラシ・営業資料など、ビジネスサイドやコーポレートの制作を行うことも多いです。

今回は、生産管理という新機能の立ち上げ時にデザイナーが行ったリサーチについてご紹介します。

サービスについて

我々が作っているサービスnimaruは、卸売市場・JA・生産法人・生産者と、農業物流に関わる方の業務を支援するSaaSです。 北は北海道から南は九州まで、広範囲で多くの事業者様に導入いただいています。

生産管理機能とは

今回実装することになった生産管理機能は、生産に関わる方向けの栽培管理機能です。 ニーズに合わせて、nimaruで以下のことができるようになります。

  • 生産現場で使用した農薬や作業内容を記録できる
  • 記録された農薬が問題ないか判定できる
  • 関係する事業者が使用状況を確認できる

リサーチ開始

PMから依頼を受け、機能とまつわる環境について調査を始めます。

まずは生産管理・栽培管理において、現場資料やインターネットから単語や主な業務を調べて概要を掴みます。 次に営業に依頼し、事業者様との面談の際にお時間いただき、生産管理における現場フローについてヒアリングを行います。

モック作成

概要が掴めた段階で、PMに報告します。 どの機能があるべきかすり合わせ、この段階から開発と進めます。

取り組む課題と機能内容の方向性が固まった段階で、大まかなイメージモックを作成します。

この時に作る画面は、社内間での認識合わせと現場のニーズ把握を目的としており、スピード感を持って叩きを作ることを優先しています。

現場リサーチ

特定の作物に対する判定基準や、圃場の単位について幅があることがわかったため、実際にエンジニアと共に高知県に出張しました。 生産現場の業務を拝見し、モックを元に使いやすさ・懸念点の吸い上げを行いました。

また、農薬に関する知識を深めるため、東京農業大学の教授にもお時間いただき、農薬の化学的な話についてお伺いしました。

仕様検討

リサーチ結果を踏まえて、開発内で要件の具体的なすり合わせが行われます。 開発とコミュニケーションをとりながらUIを修正して、仕様を固めました。 その後開発が行われ、先日無事にリリースされました。

まとめ

このように、kikitoriは現場をリスペクトしており、実際の知見や業務フローを深く理解することを大事にしています。

システム開発側にいると現場業務を非効率に感じることがあるかもしれませんが、現場は現場特有の課題に取り組むために、明確な意図を持ってそのオペレーションをしています。

全体の流れや背景を確認できないと、現場が本当に必要としているものが作れず、結局使われないものを作ってしまいます。

現場にリスペクトを持って寄り添い、かつシステムで効率化していくために俯瞰して考えることで、使われるサービスができます。

また、この考え方は、kikitoriのValueであるSeek Wisdomにも含まれており、会社として大事にしている姿勢です。

最後に

エンジニアもデザイナーも要件定義から関わることができ、現場の声を聞いて働くことができるので、とてもやりがいがあります。 そんなkikitoriでは事業拡大に伴い、一緒に働く仲間を募集しています! ご興味ありましたらぜひお気軽にエントリー・面談をお申し込みください。 お待ちしております!

careers.kikitori.jp

紙にもスマホにも対応。誰でも使える栽培記録の仕組み

こんにちは。株式会社kikitoriの大木です。

kikitoriは「nimaru」という、JAや市場向けの業務SaaSを開発しています。

農業現場では、入出荷情報や栽培記録などは、紙で運用されていることが多く残っています。

今回、栽培記録を管理する機能を開発するにあたり、PCやスマートフォンから作業を登録できる仕組みに加えて、従来の紙による運用にも対応する必要がありました。

そこで、記録用紙の画像をOCRで読み取り、データ化する仕組みを構築しました。

本記事では、なぜ紙での運用にも対応する必要があるのか、それを実現するために選定したOCRサービスの理由についてご紹介します。

農業現場の課題

栽培記録とは、種をまく・収穫する・使用した農薬や肥料の内容など、栽培に関する一連の作業を記録したものです。

この記録は、市場や消費者に安心して届けられる農産物であることを証明する根拠にもなり、特に正確さが求められます。

加えて、トレーサビリティの観点からも重要です。トレーサビリティとは、「いつ・どこで・誰が・どのように」生産したかを記録・追跡できる仕組みであり、農産物の信頼性や安全性を担保するために欠かせません。

出典: 農林水産省ウェブサイト https://www.maff.go.jp/j/syouan/seisaku/trace/index.html

多くの産地では、エクセルなどで作成された帳票を印刷し、手書きで記録し、それを後日JAが回収・確認する運用が続いています。

紙での記録は、高齢の農業従事者にも馴染みやすく、記入の自由度も高いため、現場に定着したスタイルとして根強く残っています。

栽培日誌 - Google検索

農家やJA関係者へのヒアリングから、次のような課題が多く挙がりました。

  • 項目が多く、記入が大変
  • 作物により帳票のレイアウトが異なり、管理が大変
  • JA側での確認やシステムへの転記作業に手間がかかる
  • 紙で提出された帳票は後から探しにくく、保管管理に課題がある

このように、紙での運用には合理的な理由がある一方で、情報の活用や記録の信頼性の面では改善の余地があります。

農家とJA双方の業務を尊重しながら効率化を図るには、紙で記載する運用は残しつつも、デジタル化するための仕組みが求められていました。

そのため、nimaruでは帳票そのものの形式は極力変えず、記載された情報を自動でデータ化する手段としてOCRの活用を検討しました。

導入したOCRサービス

OCRサービス各種や自前での実装も検討しましたが、最終的に Google Cloud の Document AI を採用しました。その理由は以下の3点です。

1. 基盤モデルを活用したトレーニングが行える仕組み

Document AI は、事前にトレーニングされた基盤モデルを活用しつつ、帳票ごとの追加トレーニングが可能です。 そのため、初期状態でもある程度の精度で項目を自動抽出でき、アノテーション作業の負担を大きく軽減できました。

トレーニングして評価する  |  Document AI  |  Google Cloud

2. 手書きの日本語にも対応

他のOCRサービスでは日本語対応が限定的なものもありましたが、Document AI は手書き文字を含む日本語にも対応しています。 特に栽培記録のように、手書き入力が多くを占める帳票を扱う場合、この点は導入の必須条件でした。

プロセッサのリスト  |  Document AI  |  Google Cloud

3. 既存の Google Cloud 環境をそのまま活用できる

他の機能でも Google Cloud を活用しているため、Document AI の導入もスムーズに進めることができました。

現場の運用に対応するために

帳票ごとにレイアウトや記入スタイルが異なるため、nimaruでは「書き方を変えずに使えること」を重視して設計しました。

OCRの読み取り精度を高めるため、記入欄の配置や罫線の整え方など、帳票のレイアウトにも工夫を加えています。

帳票のレイアウトを調整した場合でも、再度アノテーションを設定する作業を比較的少ない負担で行えるため、試行錯誤しながらの改善もスムーズに進めることができました。

おわりに

農業の課題をテクノロジーで解決するといっても、現場のすべてを一度に変えることはできません。帳票や業務の流れには長年の積み重ねがあり、そこには理由があります。

それでも、「いま、変えられること」から地道なチャレンジを積み重ねられるのは、農業という領域ならではの面白さであり、やりがいだと感じています。

今後も現場の運用に寄り添いながら、より良いプロダクトとなることを目指して取り組んでいきます。

herp.careers

農業流通SaaSが向き合う課題、その一例

こんにちは。株式会社kikitoriでプロダクトマネージャーをしている松本です。

kikitoriは「nimaru」という、JAや市場の方が業務で使うSaaSの開発をおこなっています。

この記事では、日々nimaruを使っていただくなかで発生した課題について、どのように解決しているかを紹介します。

集出荷業務は手書きの紙で溢れている

nimaruにはJAの集出荷業務をサポートする機能があります。

集出荷業務とは、簡単に言うと下記のような業務です。

  1. 農家さんが育てた野菜や果物をJAに持って行く
  2. JA職員さんが、農家さんから商品を受け取る
  3. 受け取った商品を市場や販売先に出荷する

この集出荷業務は現在、手書きの紙を中心としたオペレーションで行われています。

農家さんは、どの商品をどれだけ持ってきたかを紙に書き、その紙を元にシステムに手打ちして記録。

JA職員さんは、市場や販売先にいくつ出荷するかを紙やエクセルに書き、それを元にシステムに手打ちして記録。

nimaruはこのような紙によるオペレーションをデジタル化し、業務効率化のお手伝いをしています。

以下の画面は、集出荷業務の1と2をおこなう際の、実際のnimaru画面です。

農家さんはスマートフォンからJAにどれだけの商品を持って行くかを連絡することができ、その集計をJA職員さんはどこでも確認することができます。

またJAのシステムにもつながっており、データを手打ちすることなくnimaruからそれぞれのシステムに連携できます。

JAや商品ごとに異なるオペレーション

このようにnimaruを全国で使っていただいているのですが、日々課題が出てきます。

ここ数ヶ月ホットだったのは荷姿です。皆様は荷姿についてご存知でしょうか。

荷姿というのは荷物の包装や梱包の状態を表す物流用語です。

ダンボールやパック、袋などどのような梱包で荷物を扱うのかを表します。

今までのnimaruは、事業者ヒアリングの上で、商品と業務フローごとに荷姿を一つに定めていました。

農家さんがダンボールでJAに商品を持ち込む場合、JAの荷受けも出荷もダンボールになります。

またダンボールとパックの両方の荷姿で持ってくるということを想定していませんでした。

例えば、28パックのしいたけを12パックが入るダンボールで出荷する場合、ダンボールを2ケース分出荷し、ダンボールに入りきらなかった4パックは翌日出荷するというオペレーションを元に荷姿周りの実装をしていたのです。

しかし昨年末、ある事業者様に導入検討いただいた際、この仕様では現場で使えないという意見をいただきました。

農家さんはダンボールとパックで出荷し、JAが市場や販売先にパックで出荷するというオペレーションをしているから、とのことでした。

このように野菜や果物の集出荷業務には全国的なルールがなく、それぞれのJAや商品によってオペレーションが異なっているということがよくあります。

結果どうなったか

このような複数の荷姿を扱う品目が出てきたことにより、再度事業者へのヒアリングをおこないました。例として挙げたのはしいたけでしたが、似た声はいちごのオペレーションでもあがっており、どのフローでどのような荷姿を使っているのか改めて整理しました。

その結果、以下の画面を実装しました。

農家さんのスマートフォン上の入力欄が荷姿の分増えており、JA職員の方が見る集計画面も欄が増えています。

実装した結果だけを見ると欄を増やしただけでシンプルですが、ここに至るまでにデータ構造の設計変更、複雑化した表の機能洗い出し、洗い出した結果元々あった機能を別機能に移す等々、クリアしなければいけない壁がたくさんありました。

また今回はこの課題を解決する実装に至ったのですが、その前段階には本当にこの課題をシステムで解決するのかというフェーズがあります。

オペレーションを事業者や担当のセールスの方から聞き、理解しどれくらい困っているのか、本当に開発しないと業務がまわらないのか議論し、クリアにした上でエンジニアとどう実装していくのか考えていきます。

kikitoriで働くおもしろさ

ここまで読んでいただきありがとうございます。ここ数ヶ月の間、脳の2割ほどを占めていた荷姿の取扱いについて紹介しました。

kikitoriでは、このような農業流通現場の課題を一つずつ解決していっています。

私自身、農業に特別な興味や思い入れがあるわけではありませんでした。ただ入社してから、日々農業流通現場の課題や複雑なオペレーションに向き合い、チームで膝を突き合わせながら悩み考えることに、スタートアップ味とやりがいを感じています。

農業を題材に課題解決に向けて一緒に悩み解決したい方はぜひ一度お話ししましょう!

herp.careers