๐Ÿ“ Route, Controller, Service ๊ตฌ์กฐ๋ž€?

๊น€๋ฏผ์ง€ยท2025๋…„ 1์›” 28์ผ

Route, Controller, Service ๊ตฌ์กฐ

1. Routes

์—ญํ• 

  • ํด๋ผ์ด์–ธํŠธ(FE)์˜ ์š”์ฒญ์„ ๋ฐ›์•„์„œ ํ•ด๋‹น ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  Controller ์—๊ฒŒ ์ „๋‹ฌํ•˜๋ฉฐ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ง„์ž…์ (entry point)๋กœ ๋™์ž‘ํ•จ

  • ํŠน์ • HTTP ๋ฉ”์„œ๋“œ(GET, POST, PUT, DELETE ๋“ฑ)์™€ API์˜ URL ๊ฒฝ๋กœ๋ฅผ ๋งคํ•‘ํ•˜๋ฉฐ, ์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ ์ ˆํ•œ Controller ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•จ

  • app.get('/users', <์ปจํŠธ๋กค๋Ÿฌ ๋ฉ”์„œ๋“œ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ>) ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์ •์˜๋จ

๋น„์œ 

  • ๋ผ์šฐํŠธ๋Š” ์‹๋‹น์˜ ๋ฉ”๋‰ด์™€ ๊ฐ™์Œ. ๊ฐ ๋ฉ”๋‰ด๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์š”์ฒญํ•  ์ˆ˜ ์žˆ๋Š” ํŠน์ • ๊ธฐ๋Šฅ(์—”๋“œํฌ์ธํŠธ)์„ ๋‚˜ํƒ€๋ƒ„.

์˜ˆ์ œ ์ฝ”๋“œ

  • ์˜ˆ์ œ์—์„œ๋Š” ๊ฐ„๋‹จํ•œ ์š”์ฒญ์ด๋ฏ€๋กœ controller๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋Œ€์‹  ๊ฐ„๋‹จํžˆ ์•„๋ž˜์™€ ๊ฐ™์ด ์ฒ˜๋ฆฌํ–ˆ์ง€๋งŒ, ์‹ค์ œ ์ฝ”๋“œ์—์„œ๋Š” ์ฃผ๋กœ controller๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ์ฝ”๋“œ๋ฅผ ๋ถ„๋ฆฌํ•ด ์‚ฌ์šฉํ•จ
(req, res) => {
    res.send('GET ์š”์ฒญ ์ฒ˜๋ฆฌ: ๋ชจ๋“  ์‚ฌ์šฉ์ž ์กฐํšŒ');
}
import express from 'express';

const app = express();

// GET ์š”์ฒญ ์ฒ˜๋ฆฌ
app.get('/users', (req, res) => {
    res.send('GET ์š”์ฒญ ์ฒ˜๋ฆฌ: ๋ชจ๋“  ์‚ฌ์šฉ์ž ์กฐํšŒ');
});

// POST ์š”์ฒญ ์ฒ˜๋ฆฌ
app.post('/users', (req, res) => {
    res.send('POST ์š”์ฒญ ์ฒ˜๋ฆฌ: ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž ์ƒ์„ฑ');
});

// ์„œ๋ฒ„ ์‹คํ–‰
app.listen(3000, () => {
    console.log('Server is listening on port 3000');
});

2. Controllers

์—ญํ• 

  • Routes ์—์„œ ์ „๋‹ฌ๋ฐ›์€ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์„œ ์ฒ˜๋ฆฌํ•˜๊ณ , ์ ์ ˆํ•œ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•จ

  • ์ด ๋•Œ, ์ฒ˜๋ฆฌ ๊ณผ์ •์—์„œ Service ๊ณ„์ธต(์ปจํŠธ๋กค๋Ÿฌ โ†” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์—ฐ๊ฒฐ)์„ ํ˜ธ์ถœํ•ด ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์‹คํ–‰ ํ›„ ์„œ๋น„์Šค์—์„œ ๋ฐ˜ํ™˜๋œ ๊ฒฐ๊ณผ๋ฅผ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•์‹(JSON ๋“ฑ)์œผ๋กœ ๋ณ€ํ™˜ ํ›„ ๋ฐ˜ํ™˜ํ•จ

๋น„์œ 

  • Controllers๋Š” ์‹๋‹น์˜ ์›จ์ดํ„ฐ์™€ ๊ฐ™์Œ. ์›จ์ดํ„ฐ๋Š” ๊ณ ๊ฐ(ํด๋ผ์ด์–ธํŠธ)์˜ ์ฃผ๋ฌธ(์š”์ฒญ)์„ ๋ฐ›์•„ ์ฃผ๋ฐฉ(์„œ๋น„์Šค)์— ์ „๋‹ฌํ•˜๊ณ , ์ค€๋น„๋œ ์Œ์‹์„ ๋‹ค์‹œ ๊ณ ๊ฐ์—๊ฒŒ ๊ฐ€์ ธ์˜ด.

์˜ˆ์ œ ์ฝ”๋“œ

import { UserService } from './services/UserService';
import express from 'express';

export class UserController {
    constructor(private userService: UserService) {
        this.userService = userService;
    }

    // ๋ชจ๋“  ์‚ฌ์šฉ์ž ์กฐํšŒ
    getAllUsers = async (req: express.Request, res: express.Response) => {
        try {
            const users = await this.userService.getAllUsers();
            res.json(users); // ์„œ๋น„์Šค์—์„œ ๋ฐ˜ํ™˜๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์‘๋‹ต์œผ๋กœ ์ „์†ก
        } catch (err) {
            res.status(500).json({ message: err.message });
        }
    };

    // ์‚ฌ์šฉ์ž ์ƒ์„ฑ
    createUser = async (req: express.Request, res: express.Response) => {
        try {
            const newUser = req.body; // ์š”์ฒญ ๋ฐ์ดํ„ฐ์—์„œ ์ƒˆ ์‚ฌ์šฉ์ž ์ •๋ณด ๊ฐ€์ ธ์˜ด
            const user = await this.userService.createUser(newUser);
            res.status(201).json(user);
        } catch (err) {
            res.status(500).json({ message: err.message });
        }
    };

    // ์‚ฌ์šฉ์ž ์—…๋ฐ์ดํŠธ
    updateUser = async (req: express.Request, res: express.Response) => {
        try {
            const updatedUser = req.body;
            const user = await this.userService.updateUser(updatedUser);
            res.json(user);
        } catch (err) {
            res.status(500).json({ message: err.message });
        }
    };
}

3. Services

์—ญํ• 

  • ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•˜๋Š” ์ž‘์—…์„ ์ •์˜ํ•˜๋ฉฐ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•จ

  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ์ˆ˜ํ–‰ํ•จ

  • ์„œ๋น„์Šค๋Š” ์ปจํŠธ๋กค๋Ÿฌ์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(๋ฆฌํฌ์ง€ํ† ๋ฆฌ) ๊ฐ„์˜ ์ค‘๊ฐ„ ๊ณ„์ธต์œผ๋กœ ์ž‘๋™.
    ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์„œ๋น„์Šค์— ์ง‘์ค‘์‹œ์ผœ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ด๊ณ , ์ฝ”๋“œ ํ…Œ์ŠคํŠธ๋ฅผ ์šฉ์ดํ•˜๊ฒŒ ๋งŒ๋“ฆ.

๋น„์œ 

  • ์„œ๋น„์Šค๋Š” ์‹๋‹น์˜ ์ฃผ๋ฐฉ๊ณผ ๊ฐ™์Œ. ์›จ์ดํ„ฐ(์ปจํŠธ๋กค๋Ÿฌ)๊ฐ€ ์ „๋‹ฌํ•œ ์ฃผ๋ฌธ์„ ๋ฐ›๊ณ , ์Œ์‹(์‘๋‹ต)์„ ์ค€๋น„.

์˜ˆ์ œ ์ฝ”๋“œ

import { UserRepository } from '../repositories/UserRepository';
import { User } from '../models/User';

export class UserService {
    constructor(private userRepository: UserRepository) {
        this.userRepository = userRepository;
    }

    // ๋ชจ๋“  ์‚ฌ์šฉ์ž ์กฐํšŒ
    async getAllUsers(): Promise<User[]> {
        return await this.userRepository.getAllUsers();
    }

    // ์ƒˆ ์‚ฌ์šฉ์ž ์ƒ์„ฑ
    async createUser(user: User): Promise<User> {
        return await this.userRepository.createUser(user);
    }

    // ์‚ฌ์šฉ์ž ์—…๋ฐ์ดํŠธ
    async updateUser(user: User): Promise<User> {
        return await this.userRepository.updateUser(user);
    }
}

4. Repositories (์ €์žฅ์†Œ)

  • ์—ญํ• : ์„œ๋น„์Šค์™€ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ๊ณ„์ธต(DAL) ์‚ฌ์ด์—์„œ ์ถ”์ƒํ™” ๋ ˆ์ด์–ด ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•˜๋ฉฐ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์ง์ ‘ ํ†ต์‹ .
  • ์žฅ์ : ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ณ€๊ฒฝ ์‹œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์œ ์ง€๋ณด์ˆ˜์„ฑ๊ณผ ํ™•์žฅ์„ฑ์„ ๋†’์ž„.
  • ๋น„์œ : ์ €์žฅ์†Œ๋Š” ๋ ˆ์‹œํ”ผ์™€ ๊ฐ™์•„์„œ, ์„œ๋น„์Šค(์…ฐํ”„)๊ฐ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(์‹์ž์žฌ ์ฐฝ๊ณ )์—์„œ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜ ์กฐํ•ฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค์คŒ.

โžก๏ธ ๋น„์œ ๋กœ ์ดํ•ดํ•˜๊ธฐ

  • ๋ผ์šฐํŠธ: ์‹๋‹น์˜ ๋ฉ”๋‰ด โ†’ ์–ด๋–ค ๊ธฐ๋Šฅ์„ ์š”์ฒญํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์ •์˜.
  • ์ปจํŠธ๋กค๋Ÿฌ: ์›จ์ดํ„ฐ โ†’ ์š”์ฒญ์„ ๋ฐ›์•„ ์„œ๋น„์Šค๋กœ ์ „๋‹ฌํ•˜๊ณ , ์‘๋‹ต์„ ํด๋ผ์ด์–ธํŠธ์— ๋ฐ˜ํ™˜.
  • ์„œ๋น„์Šค: ์ฃผ๋ฐฉ โ†’ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํ•ฉํ•ด ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜.

0๊ฐœ์˜ ๋Œ“๊ธ€