- 1. はじめに
- 2. 作ったもの
- 3. なぜ作ったのか? (動機・背景)
- 4. こだわりの設計(技術的ハイライト)
- 4.3. 開発環境:誰でも構築できる環境作り
- 5. 開発プロセスにおける挑戦と学び
- 6. 今後の展望
- 7. おわりに
1. はじめに
現在、就労移行支援事業所での訓練を通じて、データエンジニアとしてのキャリアを歩むことを目指しています。
この度、学習の集大成として、企業の財務データを分析するためのETL・可視化パイプラインをスクラッチで構築しました。本記事では、そのプロジェクトの概要と、特にこだわった技術的な設計についてご紹介します。
データエンジニアリングに興味のある方や、Pythonでのアプリケーション設計に関心のある方にとって、何かしらの参考になれば幸いです。
2. 作ったもの
EDINET APIから取得した企業の財務データを、整形・加工してデータベースに保存し、Streamlit製のダッシュボードでインタラクティブに可視化するWebアプリケーションです。
GitHubリポジトリ https://github.com/Zack-K/ir_analyses (https://github.com/Zack-K/ir_analyses)
デモ画面 (https://github.com/Zack-K/ir_analyses/blob/main/vizialize_demo.gif)
3. なぜ作ったのか? (動機・背景)
データエンジニアへのキャリアチェンジを目指す上で、実務で求められるスキルセットを証明する必要があると考えました。具体的には、Web上に散在する不整形なデータを収集(Extract)、ビジネス要件に合わせて加工(Transform)、そして分析可能な形でデータベースに格納する(Load)という、一連のデータパイプライン構築能力です。
この課題に挑戦する題材として、企業のIR情報を提供する金融庁のEDINET APIに着目しました。信頼性が高いデータソースである一方で、データの内容は業種や会計基準などによって異なるためです。それらの情報を抽出・標準化するプロセスは、データエンジニアリングの実践的な訓練として最適だと考え、本プロジェクトを開始しました。
4. こだわりの設計(技術的ハイライト)
本プロジェクトでは、単に動くものを作るだけでなく、将来の機能拡張やチームでの開発を想定した、保守性と拡張性の高い設計を強く意識しました。
4.1. データパイプライン:データの流れを整理する
まず、プロジェクトの根幹であるETLの全体像です。APIからのデータ取得、加工、DBへの格納までを、以下のパイプラインとして設計しました。
graph TD
subgraph Extract
A[EDINET API] --> B{財務報告書ZIP};
end
subgraph Transform
B --> C[CSV展開];
C --> D[Pandas DataFrame<br>データ標準化・整形];
D --> E{DBモデルへマッピング};
end
subgraph Load
E --> F[SQLAlchemy<br>Unit of Work];
F --> G[(PostgreSQL)];
end
G --> H{分析・可視化<br>app.py};
各ステップの責務を明確に分離することで、例えば将来データソースがAPIから別のものに変わったとしても、Extract部分の修正だけで対応できるようにしています。
4.2. アプリケーションアーキテクチャ:責務を分離する
当初、Streamlitの単一スクリプト内にデータ取得・加工・表示のロジックが混在し、コードの見通しが悪いという課題がありました。*1 そこで、アプリケーション全体を以下の3層アーキテクチャへとリファクタリングしました。
graph TD
subgraph プレゼンテーション層
A[View/Controller<br>app.py]
end
subgraph ビジネスロジック層
B[Service<br>financial_service.py]
C[Unit of Work<br>unitofwork.py]
end
subgraph データアクセス層
D[Repository<br>repositories/*]
E[ORM Model<br>db_models.py]
end
subgraph データベース
F[(PostgreSQL)]
end
A -->|1. 処理要求| B; B -->|2. UoW経由で<br>Repository呼び出し| C; C -->|3. Repository取得| D; D -->|4. CRUD操作| E; E --- F;
F -->|5. データ返却| E; E -->|6. モデル返却| D; D -->|7. モデル返却| C; C -->|8. モデル返却| B;
B -->|9. DTOに変換| B; B -->|10. DTO返却| A; A -->|11. UI表示| A;
- プレゼンテーション層: UIの表示とユーザー入力の受付に特化。
- ビジネスロジック層: アプリケーション固有のルール(利益率の計算など)を担う。
- データアクセス層: DBとのやり取りを完全にカプセル化。
この設計により、UIの変更がビジネスロジックに影響を与えなくなり、各層を独立してテストできるようになりました。特に、Unit of Workパターンを導入し、トランザクション管理をビジネスロジック層から分離した点は、堅牢性を高める上で重要な判断でした。
4.3. 開発環境:誰でも構築できる環境作り
後述する高すぎた目標を下げて生まれた余裕を使ってDockerを採用することにしました。
システムエンジニア時代に、環境構築が本当に大変だったこともあり、それを乗り越える技術を経験したかったのが理由です。
docker compose up --buildコマンド一つで、Python実行環境、PostgreSQLデータベース、データ処理用のコンテナがすべて起動します。
また、Ruffによるコードフォーマットとpytestによる単体テストを自動実行することで、コードの品質を常に一定に保つ仕組みを取り入れています。こちらも、システムエンジニア時代に画面のスクリーンショットを画面に貼り付けつつ、テスト証跡を取っていた苦労を再現したくない、という思いから取り入れました。
5. 開発プロセスにおける挑戦と学び
このプロジェクトの開発は一直線の道のりではありませんでした。ここでは、特に大きな壁となった2つの挑戦と、それを乗り越えるために行った工夫についてお話しします。
挑戦①:高すぎた初期目標と現実的なスコープ調整
当初、私は「Google Cloudの各種サービスをフル活用した、クラウドネイティブなデータパイプラインを構築する」という非常に高い目標を掲げていました。
しかし、開発を進める中で、Cloud Run, Cloud Functions, BigQueryなど、習得すべき未経験技術の学習コストが想定以上に大きいことに気づきました。このままでは目標期間とする3ヶ月内での完成は困難であると判断し、プロジェクトのスコープを見直すとこととしました。
具体的には、目標を「GCP上でのパイプライン構築」から、「Dockerコンテナ上で完結する、堅牢なETLプロトタイプの完成」に再設定しました。
この方針転換により、高レベルな技術の学習に時間を費やす代わりに、アプリケーションの「基礎体力」とも言える、クリーンなアーキテクチャの追求や、Dockerによる開発環境の標準化といった、ソフトウェアエンジニアリングの根幹となる品質向上に徹底的に注力することができました。これは、結果として着実なステップアップに繋がったと考えています。
挑戦②:設計の手戻りと、アーキテクチャの全面見直し
開発中盤、もう一つの大きな壁に直面しました。それは、設計の大幅な手戻りです。
設計に関する大きな勘違いをしていた結果、場当たり的な実装となっており密結合で責務の分担ができていない状態になっていました。
ここで手戻りになることを覚悟して、責務分離を徹底する3層アーキテクチャへの全面的なリファクタリングを決断しました。この方針転換により、開発期間は1ヶ月以上延長となりました。しかし、その対価として、各コンポーネントが疎結合でテストしやすく、将来の機能追加にも柔軟に対応できる、質の高い設計に変更できました。
これらの挑戦を支えた工夫
こうした試行錯誤の過程で、プロジェクトの進行を支えたのが以下の2つの工夫です。
徹底したドキュメント化: AIも私も、一度決めた方針を忘れがちです。そこで、設計の意図、アーキテクチャの変更理由、日々の進捗などを逐一ドキュメントに残しました。これにより、常に最終的なゴールを見失うことなく、一貫性のある開発を続けることができました。
利用可能な学習リソースの最大活用: 技術的な壁にぶつかった際は、Udemyや書籍で基礎を学び直し、生成AIをペアプログラマーのように活用して実装のヒントを得ました。そして、定期的にメンターへ進捗を報告し、客観的なフィードバックをもらうことで、独りよがりにならずにプロジェクトの軌道修正を行うことができました。
6. 今後の展望
このプロジェクトはまだ発展途上です。今後は、以下のような機能拡張を計画しています。
- 分析機能の強化: 前期比較機能、キャッシュフロー分析など、新たな分析指標を追加。
- データパイプラインの高度化:
- ワークフロー管理: Airflowを導入し、データ取得・処理の定期実行と依存関係の管理を実現。
- パフォーマンス改善: 大規模データ処理を想定した、DBのクエリチューニングやインデックス戦略の見直し。
7. おわりに
最後までお読みいただき、ありがとうございました。 このプロジェクトを通じて、データパイプラインの設計から、保守性の高いアプリケーションアーキテクチャ、そして開発環境の構築まで、一気通貫で取り組む貴重な経験ができました。
データエンジニアのポートフォリオとして、さらに改善していくために、皆様から「もっとこうすると良いのでは?」「この部分の設計について、自分ならこうする」といったご意見をいただけると、大変嬉しく思います。
GitHubのIssueやPull Request、あるいは本記事のコメント欄にて、どんな些細なことでもフィードバックをお待ちしております!