i-Vinci TechBlog
株式会社i-Vinciの技術ブログ

0から作って理解するWeb API

みなさんこんにちは、積みゲー消化中のTです。

ここ1年ほど、改修やAWS移行の案件に携わってきました。
仕事ではシニアエンジニアが先に実装した機能を参考にしながら進めることが多く、仕組みを深く理解しなくても開発を進められる場面が少なくありません。
もちろん、そのやり方でも仕事は回せますが、いざ聞かれたときに詳しく説明できないもどかしさを感じることもありました。

そこで今回は、自分の理解を深めるために一度整理してみようと思います。
特に最近担当しているWeb APIについて、仕組みを整理しつつ、実際に簡単なWeb APIを自分で作ってみることで、コードレベルでの理解も深めていく記事です。

APIとは?

APIとはApplication Programming Interfaceの略称で、プログラムやシステム同士の情報が送受信される仕組みのことです。

APIと聞くと一般的にWebアプリで使用されるWebAPIが想像されますが、WindowsやmacOSでもアプリケーションとカーネル間の通信に使われるなど、非常に多くの用途があります。

以下の図ではWeb APIの仕組みについて簡単な図で表しています。

画像 alt

Web APIを理解するために必要なキーワード

以下のキーワードは経験のある人であれば当たり前のように知っている言葉だと思いますが、ここではジュニア層に向けて改めて説明したいと思います。

1. HTTPメソッド(GET, POST, PUT, DELETE)

API に対する操作を示す命令

  • GET:データ取得
  • POST:データ作成
  • PUT:データ更新
  • DELETE:データ削除

2. エンドポイント(Endpoint)

API のアクセス先 URL
例: https://api.example.com/users

3. リクエスト(Request)

API に送る「こうしてほしい」内容
含まれるもの:URL、HTTPメソッド、ヘッダー、ボディなど

4. レスポンス(Response)

API から返ってくる結果
ステータスコード(成功/失敗)やデータが含まれる

5. ステータスコード(Status Code)

レスポンスの状態を示す数字

  • 200番台:成功

    • 200 OK:リクエスト成功。正常にデータが返ってきた状態。
  • 400番台:クライアント側のエラー

    • 400 Bad Request:リクエストが不正
    • 401 Unauthorized:認証が必要、または認証失敗
    • 403 Forbidden:権限がないためアクセス禁止
    • 404 Not Found:リソースが見つからない
  • 500番台:サーバー側のエラー

    • 500 Internal Server Error:サーバー内部で問題が発生

簡単なWeb APIを実装してみましょう!

今回実装するWeb APIは、ローカルに名前と年齢を格納するjsonファイルがあり、リクエストとして名前を送ると、レスポンスで年齢を返す仕様です。

私のPCがMacであるためIDEにJetBrains Rider、使用する言語はC#、フレームワークにASP.Net Core 8.0を使用します。

画像 alt

今回のディレクトリ構成は以下となります。

MyApp/
┣ Controllers/
┃ ┗ EmployeeController.cs
┣ Services/
┃ ┗ EmployeeService.cs
┣ Models/
┃ ┗ Employee.cs
┣ bin/
┃ ┗ employees.json
┗ Program.cs

ファイルの説明

Controllers/EmployeeController.cs — APIの入口(Controller層)

  • クライアント(ブラウザやアプリ)からの HTTP リクエストを受け取る
  • 必要な Service を呼び出し、結果を返す
  • ルーティング(URLパス)を定義
  • リクエストのバリデーション
  • レスポンスの返却形式を制御
  • アプリの入り口(API Gateway)の役割を持つ

Services/EmployeeService.cs — ビジネスロジック(Service層)

  • Controller から呼ばれ、実際にデータを扱う処理を担当
  • bin/employees.json を読み込み、ID で検索して返す
  • Controller と分離し、再利用可能な処理ロジックをまとめる

Models/Employee.cs — データ構造(Model層)

  • アプリで扱う「データの型」を定義するクラス
  • この場合は従業員を表す Employee モデル
  • データベース・JSON など外部データとのやり取りに使われる
  • Model 層は「データ構造」を表すだけで、ビジネスロジックは持たない

Program.cs — アプリの起動設定(エントリーポイント)

  • アプリ全体の設定・初期化を担当
  • ルーティングや DI(依存性注入)を設定
  • Service の登録
  • Swagger の設定など
  • ASP.NET Core アプリのスタート地点

実際のソースは以下となります。

Controllers/EmployeeController.cs


using Microsoft.AspNetCore.Mvc;
using MyApp.Services;
using MyApp.Models;

namespace MyApp.Controllers;

[ApiController]
[Route("api/[controller]")]
public class EmployeeController : ControllerBase
{
   private readonly EmployeeService _employeeService;

   public EmployeeController(EmployeeService employeeService)
   {
       _employeeService = employeeService;
   }

   [HttpGet("{id:int}")]
   public ActionResult<Employee> GetEmployee(int id)
   {
       var employee = _employeeService.GetEmployeeById(id);
       if (employee == null)
           return NotFound(new { message = "Employee not found" });

       return Ok(employee);
   }
}

Services/EmployeeService.cs


using System.Text.Json;
using MyApp.Models;

namespace MyApp.Services;

public class EmployeeService
{
   private readonly string _jsonPath;

   public EmployeeService(IWebHostEnvironment env)
   {
       // binフォルダ内のJSONファイルを参照
       _jsonPath = Path.Combine(env.ContentRootPath, "bin", "employees.json");
   }

   public Employee? GetEmployeeById(int id)
   {
       if (!File.Exists(_jsonPath))
           return null;

       var json = File.ReadAllText(_jsonPath);
       var employees = JsonSerializer.Deserialize<List<Employee>>(json);

       return employees?.FirstOrDefault(e => e.Id == id);
   }
}

Models/Employee.cs


namespace MyApp.Models;

public class Employee
{
   public int Id { get; set; }
   public string Name { get; set; } = string.Empty;
   public string Department { get; set; } = string.Empty;
}

Program.cs


using MyApp.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// DI登録
builder.Services.AddScoped<EmployeeService>();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
   app.UseSwagger();
   app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.MapControllers();

app.Run();

bin/employee.json


[
 { "Id": 1, "Name": "Yamada Taro", "Department": "Engineering" },
 { "Id": 2, "Name": "Suzuki Hanako", "Department": "Sales" },
 { "Id": 3, "Name": "Tanaka Ichiro", "Department": "HR" }
]

ソースを書き終わったら、デバッグボタンをクリックして起動します。

画像 alt

Chrome(デフォルト設定のブラウザ)でSwaggerUIが立ち上がるので、リクエストに名前を入力して実行するとレスポンスとして年齢が返却されることを確認できます。

画像 alt

ここではリクエストパラメーターにidを入力し、200レスポンスが返却されることまで確認できました。

まとめ

APIは「アプリケーション同士がデータをやり取りするための入り口」であり、内部の仕組みを整理して理解することが重要です。今回のシンプルなAPIでは、Controller・Service・Modelという3層構成を採用しました。

Controllerはリクエストを受け取り、Serviceを呼び出して処理結果を返します。Serviceは実際のビジネスロジックを担い、データの取得や加工を行います。Modelはアプリ内で扱うデータ構造を定義する層です。このように役割を分けることで、処理の流れが明確になり、保守や拡張が容易になります。小規模なAPIでも構造を意識することで、より実践的な理解が深まります。