🌟

オタクくん「ギャル先輩!中規模WEBサービスを一人で立ち上げたいです!」

2024/06/01に公開

オタクくん「ギャル先輩!中規模WEBサービスを一人で立ち上げたいです!」

ギャル先輩「おっと、野心的だね〜。でも大丈夫、一人でもできるよ〜。まずは、何を作りたいかをちゃんと決めるところから始めよう!」

サービスのアイデアを固める

ギャル先輩「まず、どんなサービスを作りたいのかを明確にしようよ。具体的なアイデアはある?」

オタクくん「ユーザーが自分のタスクを管理できるToDoアプリを作りたいんです。でも、ただのToDoアプリじゃなくて、他のユーザーと共有したり、コメントしたりできる機能も欲しいんです。」

ギャル先輩「なるほど〜、じゃあ、次は技術スタックを決めようか!」

技術スタックの選定

オタクくん「技術スタックって何ですか?」

ギャル先輩「技術スタックっていうのは、サービスを作るために使う技術やツールのことだよ〜。例えば、フロントエンドにはReact、バックエンドにはNode.js、データベースにはMongoDBみたいな感じで決めていくんだよ。」

オタクくん「どうやって選べばいいんですか?」

ギャル先輩「それじゃ、オススメの技術スタックを教えるね〜」

  1. フロントエンド: React + Next.js
  2. バックエンド: Node.js + Express
  3. データベース: MongoDB
  4. ホスティング: Vercel (フロントエンド), Heroku (バックエンド)
  5. 認証: Firebase Authentication

プロジェクトのセットアップ

ギャル先輩「まず、フロントエンドのプロジェクトをセットアップしようか!」

オタクくん「どうやってやるんですか?」

ギャル先輩「こんな感じで、Next.jsのプロジェクトを作るよ〜」

npx create-next-app my-todo-app
cd my-todo-app

ギャル先輩「次に、バックエンドのプロジェクトをセットアップしよう!」

mkdir backend
cd backend
npm init -y
npm install express mongoose

基本的なAPIの作成

ギャル先輩「次は、バックエンドで基本的なAPIを作るよ〜。まずは、Expressを使って簡単なサーバーを立ち上げるね」

const express = require('express');
const mongoose = require('mongoose');
const app = express();
const port = 3000;

app.use(express.json());

mongoose.connect('mongodb://localhost:27017/todo-app', {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

const todoSchema = new mongoose.Schema({
  task: String,
  completed: Boolean,
});

const Todo = mongoose.model('Todo', todoSchema);

app.get('/api/todos', async (req, res) => {
  const todos = await Todo.find();
  res.json(todos);
});

app.post('/api/todos', async (req, res) => {
  const newTodo = new Todo({
    task: req.body.task,
    completed: false,
  });
  const savedTodo = await newTodo.save();
  res.json(savedTodo);
});

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});

フロントエンドとバックエンドの連携

ギャル先輩「次は、フロントエンドからバックエンドのAPIを呼び出す部分を作るよ〜」

オタクくん「どうやってAPIを呼び出すんですか?」

ギャル先輩「こんな感じで、Next.jsのgetServerSidePropsを使ってデータをフェッチするんだよ〜」

// pages/index.js
import { useState } from 'react';

export default function Home({ initialTodos }) {
  const [todos, setTodos] = useState(initialTodos);
  const [task, setTask] = useState('');

  const addTodo = async () => {
    const res = await fetch('/api/todos', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ task }),
    });
    const newTodo = await res.json();
    setTodos([...todos, newTodo]);
    setTask('');
  };

  return (
    <div>
      <h1>ToDo App</h1>
      <ul>
        {todos.map((todo) => (
          <li key={todo._id}>{todo.task}</li>
        ))}
      </ul>
      <input
        type="text"
        value={task}
        onChange={(e) => setTask(e.target.value)}
      />
      <button onClick={addTodo}>Add Todo</button>
    </div>
  );
}

export async function getServerSideProps() {
  const res = await fetch('http://localhost:3000/api/todos');
  const initialTodos = await res.json();

  return {
    props: {
      initialTodos,
    },
  };
}

認証の追加

ギャル先輩「最後に、認証機能を追加しようか。Firebase Authenticationを使うと簡単だよ〜」

オタクくん「Firebase Authenticationって何ですか?」

ギャル先輩「Firebase Authenticationは、Googleが提供してる認証サービスで、簡単にユーザー認証を実装できるんだよ〜」

// pages/api/auth/[...nextauth].js
import NextAuth from 'next-auth';
import Providers from 'next-auth/providers';

export default NextAuth({
  providers: [
    Providers.Google({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
  ],
  database: process.env.DATABASE_URL,
});

まとめ

オタクくん「ギャル先輩、本当にありがとうございました!これで中規模WEBサービスを立ち上げる準備が整いました!」

ギャル先輩「よかったってばよ!」

Discussion