0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ポートフォリオで差をつける!就活に向けて成果物を作ろう!

Posted at

Spring Boot 3とJava 17で作るECサイト完全ガイド【実装から学ぶWeb開発】

この記事で分かること

  • Spring Boot 3.1.5を使った実践的なECサイトの作り方
  • JWT認証の実装方法
  • Spring SecurityとSpring Data JPAの使い方
  • 1万行規模のプロジェクト構成とアーキテクチャ設計
  • 学生・初学者が実務レベルのコードを書くためのポイント

対象読者: Javaの基礎を学んだ学生・初学者、Spring Bootでポートフォリオを作りたい方

開発期間: 約2ヶ月
コード規模: 10,000行以上
GitHubリポジトリ: https://github.com/shanks665/ECplatform


目次

  1. プロジェクト概要
  2. 技術スタック
  3. アーキテクチャ設計
  4. 実装で学んだ重要ポイント
    • JWT認証の実装
    • DTOパターンとMapStruct
    • 例外ハンドリング
    • ページネーションと検索
    • セキュリティ対策
  5. 苦労した点と解決策
    • 循環参照エラー
    • LazyInitializationException
    • テストデータ管理
    • フロントエンド連携
  6. 学生エンジニアへのアドバイス
  7. 今後の展望
  8. まとめ

プロジェクト概要

こんにちは!現在、Javaを学習中の学生エンジニアです。

今回、Spring Boot 3.1.5Java 17を使って、本格的なEコマースプラットフォームを開発しました。コード行数は10,000行以上、エンティティやサービス、コントローラーなど合わせて85ファイル以上の規模になりました。

この記事では、プロジェクトを通じて学んだ技術や苦労した点、そして学生の皆さんへ伝えたいポイントをまとめます。

この記事を読むことで得られる知識:

  • 実務レベルのSpring Bootプロジェクトの構成方法
  • JWT + Spring Securityによる認証実装
  • JPA/Hibernateのベストプラクティス
  • よくあるエラーと解決方法
  • 初学者が大規模プロジェクトを完成させるコツ

🎯 なぜこのプロジェクトを作ったのか

動機

  • 実践的なJavaスキルの習得: 教科書やチュートリアルを超えた、実務レベルのコードを書きたかった
  • モダンな技術スタックの理解: Spring Boot 3系、JWT認証、RESTful APIなど、現場で使われる技術を体験したかった
  • ポートフォリオとしての価値: 就活や将来のキャリアに向けて、実力を示せるものを作りたかった

学習目標

  1. Spring Bootのエコシステムを深く理解する
  2. レイヤードアーキテクチャを実践する
  3. 認証・認可の実装を学ぶ
  4. データベース設計とJPAの使いこなし
  5. RESTful APIの設計原則を体得する

🛠️ 技術スタック:モダンなJava開発環境

バックエンド技術

  • Java 17(LTS版): 最新の長期サポートバージョン。Records、Switch式、Text Blocksなどの新機能を活用
  • Spring Boot 3.1.5:
    • Spring Framework 6系ベース
    • 依存性注入(DI)、AOP、トランザクション管理
    • Auto-configuration機能で設定を最小化
  • Spring Security 6 + JWT:
    • トークンベースのステートレス認証
    • JJWT 0.11.5を使用
    • BCryptによるパスワードハッシュ化
  • Spring Data JPA(Hibernate):
    • データアクセス層の抽象化
    • クエリメソッドの自動生成
    • Specificationパターンで動的クエリ
  • H2 Database / PostgreSQL:
    • 開発時はH2(インメモリDB)
    • 本番環境はPostgreSQL

開発支援ツール

  • Lombok 1.18.30:
    • @Data, @Builderでボイラープレート削減
    • コンパイル時にGetter/Setter自動生成
  • MapStruct 1.5.5:
    • DTOとエンティティ間のマッピング自動化
    • リフレクション不要で高パフォーマンス
  • Swagger/OpenAPI 2.2.0:
    • API仕様書の自動生成
    • ブラウザでAPIテスト可能
  • Maven 3.9+:
    • 依存性管理とビルド自動化
    • pom.xmlで一元管理

フロントエンド技術

  • Vanilla JavaScript (ES6+):
    • フレームワークに依存しない基礎力を養成
    • Async/Awaitで非同期処理
  • Fetch API:
    • RESTful APIとの通信
    • Promise/Async/Await対応
  • LocalStorage API:
    • JWTトークンの保存
    • カート情報の永続化

📐 アーキテクチャ設計

レイヤードアーキテクチャの採用

┌─────────────────────────────────┐
│   Presentation Layer            │ ← Controller
│   (REST API Endpoints)          │
├─────────────────────────────────┤
│   Service Layer                 │ ← Business Logic
│   (ビジネスロジック)             │
├─────────────────────────────────┤
│   Repository Layer              │ ← Data Access
│   (データアクセス)               │
├─────────────────────────────────┤
│   Database                      │ ← H2/PostgreSQL
└─────────────────────────────────┘

なぜこの構造にしたか:

  • 各層の責務が明確で、コードの見通しが良い
  • テストが書きやすい(モックを使った単体テストが容易)
  • 将来的な変更に強い(例: DBをMySQLに変更しても上位層は影響を受けない)

主要なエンティティ設計

User (ユーザー)
  ├─ 1:N  ShoppingCart (カート)
  ├─ 1:N  Order (注文)
  └─ 1:N  Address (住所)

Product (商品)
  ├─ N:1  Category (カテゴリー)
  ├─ 1:N  ProductImage (画像)
  └─ 1:N  ProductReview (レビュー)

Order (注文)
  ├─ N:1  User (ユーザー)
  └─ 1:N  OrderItem (注文明細)

ポイント:

  • 双方向の関連は極力避け、単方向に統一(無限ループ防止)
  • @JsonIgnore@JsonBackReferenceを使ってシリアライズ問題を回避
  • カスケード設定(CascadeType)を慎重に選択

💡 実装で学んだ重要ポイント

1. Spring SecurityでJWT認証を実装する方法

従来のセッションベース認証ではなく、トークンベースのJWT認証を採用しました。Spring Security 6系で動作確認済みです。

メリット:

  • スケーラブル(複数サーバーでのセッション共有不要)
  • RESTfulの原則に沿う(ステートレス)
  • モバイルアプリとの連携が容易

実装のポイント:

// JWTトークンの生成
public String generateToken(Authentication authentication) {
    UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal();
    Date now = new Date();
    Date expiryDate = new Date(now.getTime() + jwtExpirationMs);

    return Jwts.builder()
        .setSubject(userPrincipal.getUsername())
        .setIssuedAt(now)
        .setExpiration(expiryDate)
        .signWith(key(), SignatureAlgorithm.HS512)
        .compact();
}

学び:

  • トークンの有効期限管理の重要性
  • リフレッシュトークンの設計(今後の課題)
  • セキュリティヘッダーの設定(CORS、XSS対策)

2. DTOパターンとMapStructの使い方【ボイラープレート削減】

エンティティをそのままAPIレスポンスとして返すのではなく、DTO(Data Transfer Object)を経由させました。MapStruct 1.5.5を使って自動マッピングを実現しています。

なぜDTOを使うのか:

  • エンティティの内部構造を隠蔽(セキュリティ)
  • 循環参照の回避
  • APIバージョン管理がしやすい
  • 不要なデータの送信を防ぐ(パフォーマンス向上)

MapStructの威力:

@Mapper(componentModel = "spring")
public interface ProductMapper {
    ProductResponseDTO toResponseDTO(Product product);
    Product toEntity(ProductRequestDTO dto);
}

手動でマッピングコードを書く必要がなく、コンパイル時に自動生成されます。


3. @ControllerAdviceで例外ハンドリングを統一する

カスタム例外クラスと@ControllerAdviceでグローバルな例外処理を実装。すべてのコントローラーで一貫したエラーレスポンスを返せます。

@ControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleResourceNotFound(
            ResourceNotFoundException ex) {
        ErrorResponse error = new ErrorResponse(
            HttpStatus.NOT_FOUND.value(),
            ex.getMessage(),
            LocalDateTime.now()
        );
        return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
    }
}

メリット:

  • 一貫したエラーレスポンス形式
  • コントローラーがスッキリする
  • デバッグが容易

4. Spring Data JPAでページネーションと検索機能を実装

大量の商品データを効率的に扱うため、Spring Data JPAのPageableインターフェースを活用。動的検索にはSpecificationパターンを使用しています。

@GetMapping
public ResponseEntity<ApiResponse<Page<ProductResponseDTO>>> getAllProducts(
        @RequestParam(defaultValue = "0") int page,
        @RequestParam(defaultValue = "12") int size,
        @RequestParam(required = false) String search,
        @RequestParam(required = false) Long categoryId) {
    
    Pageable pageable = PageRequest.of(page, size);
    Page<Product> products = productService.searchProducts(
        search, categoryId, pageable);
    // ...
}

学び:

  • Pageableインターフェースの活用
  • 動的なクエリ生成(Specificationパターン)
  • N+1問題の対策(@EntityGraphの利用)

5. セキュリティのベストプラクティス

  • パスワードはBCryptでハッシュ化(10ラウンド)
  • JWTシークレットキーは環境変数で管理
  • SQLインジェクション対策(JPQLのパラメータバインディング)
  • XSS対策(入力値のバリデーション、出力のエスケープ)
  • CORS設定の適切な制限
@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder(10);
}

🚧 苦労した点と解決策

1. 循環参照エラーの解決方法【JPA + Jackson】

問題: エンティティ間の双方向関連で、JSONシリアライズ時に無限ループが発生。JacksonのJsonMappingExceptionが頻発しました。

User → Order → OrderItem → Product → Category → ...

解決策:

  • @JsonIgnoreで不要な方向の関連を除外
  • DTOに変換してからレスポンスを返す
  • 単方向の関連を優先する設計に変更

2. LazyInitializationExceptionの原因と対策

問題: トランザクション外でLazy Fetchしたエンティティにアクセスしてエラー。Hibernateで頻出する問題です。

could not initialize proxy - no Session

解決策:

  • サービス層に@Transactionalを付与
  • 必要なデータは@EntityGraphで事前にFetch
  • DTOへの変換をトランザクション内で完結させる

3. テストデータの管理

問題: 開発・テスト時に毎回データを手動で投入するのが面倒。

解決策:

@Component
@RequiredArgsConstructor
public class DataInitializer implements CommandLineRunner {
    
    @Override
    public void run(String... args) {
        // 初期データの投入
        initializeUsers();
        initializeCategories();
        initializeProducts();
    }
}

アプリケーション起動時に自動でサンプルデータを投入。


4. フロントエンドとの連携

問題: APIのエラーハンドリング、認証トークンの管理。

解決策:

// 共通のFetch関数
async function fetchWithAuth(url, options = {}) {
    const token = localStorage.getItem('token');
    const headers = {
        'Content-Type': 'application/json',
        ...(token && { 'Authorization': `Bearer ${token}` }),
        ...options.headers
    };
    
    const response = await fetch(url, { ...options, headers });
    
    if (response.status === 401) {
        // トークン切れの処理
        localStorage.removeItem('token');
        window.location.href = '/login.html';
    }
    
    return response.json();
}

📊 プロジェクト規模

最終的なコードの規模:

項目 数量
総コード行数 10,000+ 行
Javaファイル 85+ ファイル
エンティティクラス 12 個
リポジトリ 12 個
サービスクラス 6 個
コントローラー 6 個
DTO 20+ 個
列挙型 6 個

🎓 学生エンジニアへのアドバイス

1. 小さく始めて、着実に拡張する

最初から完璧を目指さず、MVPから始めましょう。

第1週: ユーザー登録・ログイン
第2週: 商品一覧・詳細
第3週: カート機能
第4週: 注文機能
...

2. 公式ドキュメントを読む習慣

Stack OverflowやQiitaも有用ですが、公式ドキュメントが最強です。


3. コードレビューを積極的に受ける

  • GitHubでプルリクエストを出す
  • 先輩や仲間にコードを見てもらう
  • オープンソースプロジェクトのコードを読む

4. テストコードを書く

実装よりもテストを先に書く「TDD(テスト駆動開発)」にも挑戦してみましょう。

@Test
void testCreateProduct_Success() {
    // Given
    ProductRequestDTO request = new ProductRequestDTO(...);
    
    // When
    ProductResponseDTO response = productService.createProduct(request);
    
    // Then
    assertNotNull(response.getId());
    assertEquals("Test Product", response.getName());
}

5. ポートフォリオとして磨く

  • READMEを充実させる(スクリーンショット、デモ動画)
  • デプロイする(Heroku、Railway、AWS EC2など)
  • 技術ブログを書く(Qiita、Zenn、個人ブログ)

🚀 今後の展望

このプロジェクトをさらに進化させたい分野:

技術的な改善

  • キャッシュ層の追加: Redis導入でパフォーマンス向上
  • 全文検索: Elasticsearchで高度な検索機能
  • リアルタイム通知: WebSocketで在庫変更通知
  • マイクロサービス化: 認証、商品、注文を独立したサービスに分離

機能追加

  • 商品レコメンデーション(機械学習)
  • 決済システムの統合(Stripe、PayPal)
  • 管理画面(React/Vue.js)
  • モバイルアプリ(React Native)

📚 参考にした資料

書籍

  • 「Spring徹底入門」(翔泳社)
  • 「リーダブルコード」(オライリー)
  • 「実践ドメイン駆動設計」(翔泳社)

オンラインリソース


🔗 リポジトリ

プロジェクトの全コードはGitHubで公開しています:

GitHub: https://github.com/shanks665/ECplatform

# クローンして試してみる
git clone https://github.com/shanks665/ECplatform.git
cd ECplatform
mvn spring-boot:run

# ブラウザで開く
open http://localhost:8080

主な機能:

  • ✅ ユーザー登録・ログイン(JWT認証)
  • ✅ 商品一覧・検索・フィルタリング
  • ✅ ショッピングカート
  • ✅ 注文処理
  • ✅ 管理者機能
  • ✅ Swagger API ドキュメント

まとめ:Spring Boot学習で得られた5つのこと

この10,000行超えのプロジェクトを通じて、Spring Bootの奥深さ設計の重要性を実感しました。

本プロジェクトで習得した技術

  1. Spring Boot 3系の実践的な使い方

    • Spring Security 6でのJWT認証実装
    • Spring Data JPAによるデータベースアクセス
    • RESTful APIの設計とSwagger統合
  2. レイヤードアーキテクチャの実践

    • Controller/Service/Repository層の適切な分離
    • DTOパターンによる責務の明確化
    • MapStructを使った効率的なマッピング
  3. 実務で使えるエラーハンドリング

    • @ControllerAdviceでの統一的な例外処理
    • カスタム例外クラスの設計
    • 循環参照やLazyInitializationExceptionの対策
  4. セキュリティのベストプラクティス

    • BCryptによるパスワードハッシュ化
    • JWT + Refresh Tokenの設計
    • CORS、XSS、SQLインジェクション対策
  5. 大規模プロジェクトの完遂力

    • 段階的な機能追加による進め方
    • テストデータの効率的な管理
    • Gitを使ったバージョン管理

初学者・学生エンジニアの方へのメッセージ

まずは小さく始めよう:

  • いきなり完璧を目指さず、まずは基本的なCRUD操作から
  • 1週間ごとに1機能ずつ追加していく
  • 動くものを早く作って、フィードバックを得る

失敗を恐れないこと:

  • エラーは学びのチャンス(このプロジェクトも数百回エラーが出ました)
  • Stack OverflowとGitHub Issuesは最高の教材
  • 公式ドキュメントを読む習慣をつける

作ったものを公開しよう:

  • GitHubでソースコードを公開
  • README.mdを丁寧に書く
  • Qiitaやブログで技術記事を書く
  • 就活のポートフォリオとして活用

技術を学ぶ過程で、このプロジェクトが少しでも参考になれば嬉しいです。

フィードバック歓迎

質問やフィードバックがあれば、ぜひGitHubのIssueやコメント欄でお気軽にどうぞ!

  • 🐛 GitHubでIssueを作成
  • 💬 コメント欄で質問
  • ⭐ 参考になったらGitHubスターをお願いします!


関連キーワード

Spring Boot 3 Java 17 Spring Security JWT認証 Spring Data JPA ECサイト Webアプリ開発 RESTful API Maven H2 Database PostgreSQL ポートフォリオ 学生エンジニア 初心者向け 実践的 アーキテクチャ設計 Lombok MapStruct Swagger


この記事が役立つ人

  • ✅ Spring Bootの実践的な使い方を知りたい
  • ✅ ポートフォリオとして見せられるWebアプリを作りたい
  • ✅ JWT認証の実装方法を学びたい
  • ✅ レイヤードアーキテクチャを理解したい
  • ✅ JPA/Hibernateの使い方をマスターしたい
  • ✅ 就活に向けて技術力をアピールしたい

タグ

Java SpringBoot 初心者 ポートフォリオ Web開発 RESTfulAPI JWT SpringSecurity SpringDataJPA ECサイト Maven 実装 学習 チュートリアル 入門

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?