코딩 규칙과 방법들

[MVC패턴] 역할을 어떻게 나눠야할까?

SoU330 2024. 10. 29. 22:36

 

 

 

 

지난번에 MVC 패턴에 대해 간단히 정리해뒀었다.

MVC 패턴을 직접 적용해보며 Model-View-Controller 도 다양한 기준에 따라 나눠지고 사용된다는 것을 깨달았다.

 

 

https://sou330.tistory.com/56

 

MVC 패턴이 무엇일까?

MVC (Model-View-Controller) 소프트웨어 설계 패턴 중 하나로 주로 웹 애플리케이션에서 많이 사용된다.이 패턴은 애플리케이션의 구조를 세 가지 역할로 분리하여 유지보수성과 확장성을 높여준다.

sou330.tistory.com

 

 

 

 

MVC 패턴을 구성할 때 클래스들을 나누는 기준

코드의 역할책임을 명확히 구분하여 유지보수와 확장성을 높이기 위함

각각의 요소는 서로의 역할을 침범하지 않고 독립적으로 동작하도록 설계된다.

 

 

 

 

1. Controller

사용자의 요청을 받고 이를 처리하여 적절한 응답을 View로 전달

  • 사용자가 View를 통해 요청한 작업을 처리함
  • Service를 호출하여 비즈니스 로직을 수행하고 그 결과를 View에 전달
  • URL 매핑, 파라미터 추출 등과 같은 작업 수행

ex ) UserController, ProductController

public class UserController {
    private UserService userService = new UserService();

    // 사용자 등록 요청 처리
    public String registerUser(String id, String name, int age) {
        return userService.registerUser(id, name, age);
    }
}

 

 

 

2. View

데이터를 사용자에게 보여주고 사용자의 입력을 받는 화면을 담당

  • 사용자에게 데이터를 표시하고 사용자의 입력을 받을 준비를 함
  • 비즈니스 로직을 포함하지 않으며 순수하게 UI와 데이터 표시를 담당

ex ) UserView, ProductView, HTML 템플릿 파일

import java.util.Scanner;

public class UserView {
    private UserController userController = new UserController();
    private Scanner scanner = new Scanner(System.in);

    // 사용자 등록 화면
    public void registerUserView() {
        System.out.println("Enter User ID:");
        String id = scanner.nextLine();

        System.out.println("Enter User Name:");
        String name = scanner.nextLine();

        String result = userController.registerUser(id, name);
        System.out.println(result); // 등록 결과 출력
    }
}

 

 

 

3. Model

데이터와 관련된 모든 로직을 관리하며 데이터의 상태와 변화를 저장하고 관리

  • 데이터베이스와 연동하여 데이터의 생성, 조회, 수정, 삭제(CRUD)를 담당
  • 비즈니스 로직을 포함할 수 있음

ex ) UserModel, ProductModel

public class User {
    private String id;
    private String name;
    private int age;

    public User(String id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    // Getters and Setters
    public String getId() { return id; }
    public String getName() { return name; }
    public int getAge() { return age; }
}

 

 

 

4. Service

주요 비즈니스 로직을 수행하는 클래스

  • Controller와 Model 사이에서 복잡한 비즈니스 로직을 수행함
  • Model에서 처리하기에는 복잡한 비즈니스 로직을 분리하여 재사용성과 유지보수를 높임

ex ) UserService, OrderService

import java.util.HashMap;
import java.util.Map;

public class UserService {
    private Map<String, User> userDatabase = new HashMap<>();

    // 사용자 등록 로직
    public String registerUser(String id, String name, int age) {
        if (userDatabase.containsKey(id)) {
            return "User with this ID already exists.";
        }
        if (age < 0) {
            return "Age cannot be negative.";
        }
        User user = new User(id, name, age);
        userDatabase.put(id, user);
        return "User registered successfully.";
    }
}

 

 

 

 

5. DTO (Data Transfer Object) - 데이터 전송 객체

주로 데이터의 전송에 사용되는 객체로 외부와의 데이터 교환에 초점을 맞춤

  • Controller에서 View로, 또는 다른 계층 간의 데이터 전송을 담당
  • 데이터 전송과 직렬화/역질렬화에 최적화됨

ex ) UserDTO, OrderDTO

public class UserDTO {
    private String id;
    private String name;

    public UserDTO(String id, String name) {
        this.id = id;
        this.name = name;
    }

    // Getters only, 불변성을 유지
    public String getId() { return id; }
    public String getName() { return name; }
}

 

 

 

 

 

 

 

6. Validator

입력 데이터의 유효성을 검사하는 역할

  • 사용자가 입력한 데이터가 올바른지 확인하고 예외 발생 시 처리
  • 각종 입력값 검증을 위한 정규 표현식, 필드 조건 등을 포함함

ex ) UserValidator, OrderValidator

public class UserValidator {

    // ID가 null이 아니고 공백이 아닌지 확인
    public static boolean isValidId(String id) {
        return id != null && !id.trim().isEmpty();
    }

    // 이름이 null이 아니고 최소 2자 이상인지 확인
    public static boolean isValidName(String name) {
        return name != null && name.length() >= 2;
    }
}

 

 

 

7. Repository/DAO (Data Access Object)

데이터베이스와의 연동을 담당하며 데이터 저장 및 조회를 수행

  • Model에 포함되지만 주로 데이터베이스 연동을 담당
  • CRUD 기능을 포함하며 SQL 또는 ORM을 통해 데이터베이스와 소통

ex ) UserRepository, ProductRepository

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class UserRepository {

    private static final String DB_URL = "jdbc:mysql://localhost:3306/mydb";
    private static final String DB_USER = "username";
    private static final String DB_PASSWORD = "password";

    // 사용자 저장
    public void save(User user) throws SQLException {
        String query = "INSERT INTO users (id, name, age) VALUES (?, ?, ?)";
        try (Connection connection = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             PreparedStatement statement = connection.prepareStatement(query)) {
            statement.setString(1, user.getId());
            statement.setString(2, user.getName());
            statement.setInt(3, user.getAge());
            statement.executeUpdate();
        }
    }
}

 

 

 

 

8. Util

여러 곳에서 사용될 수 있는 공통 로직을 제공하는 클래스

  • 애플리케이션 전반에서 반복적으로 사용되는 기능을 모아 제공
  • 특정 도메인에 국한되지 않고 범용적으로 사용됨

ex ) StringUtil, DateUtil

public class StringUtil {

    // 문자열이 null이거나 비어 있는지 확인
    public static boolean isNullOrEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }

    // 문자열의 첫 글자만 대문자로 변환
    public static String capitalize(String str) {
        if (isNullOrEmpty(str)) return str;
        return str.substring(0, 1).toUpperCase() + str.substring(1).toLowerCase();
    }

    // 문자열을 특정 길이로 자르고 끝에 "..." 추가
    public static String truncate(String str, int maxLength) {
        if (isNullOrEmpty(str) || str.length() <= maxLength) return str;
        return str.substring(0, maxLength) + "...";
    }
}

 

 

 

 

 

9. Config (설정 파일)

애플리케이션의 환경 설정을 관리하는 클래스

  • 데이터베이스, 외부 API 연동 정보 등 애플리케이션 전역 설정을 관리

ex ) AppConfig, DatabaseConfig

public class DatabaseConfig {
    public static final String DB_URL = "jdbc:mysql://localhost:3306/mydb";
    public static final String DB_USER = "username";
    public static final String DB_PASSWORD = "password";

    // 데이터베이스 연결 생성 메서드
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
    }
}

 

 

 

 

10. Exception

애플리케이션에서 발생할 수 있는 예외를 처리하는 클래스

  • 특정한 예외 상황을 다루기 위한 사용자 정의 예외 클래스를 정의함
  • 애플리케이션 전반에서 발생할 수 있는 예외를 미리 예측하여 명시적으로 관리

ex ) UserNotFoundException, OrderValidationException

public class UserNotFoundException extends RuntimeException {
    public UserNotFoundException(String message) {
        super(message);
    }
}

 

 

 

 

11. Message

애플리케이션에서 사용자에게 보여질 메시지를 관리

  • 에러 메시지, 사용자 피드백 메시지 등을 관리하여 다국어 지원이 가능하게 함
  • 코드 내에서 하드코딩하지 않고 메시지를 모아 관리

ex ) ErrorMessages, SucessMessages

public class Message {
    public static final String ERROR_USER_NOT_FOUND = "사용자를 찾을 수 없습니다.";
    public static final String ERROR_INVALID_INPUT = "잘못된 입력입니다.";
    public static final String SUCCESS_REGISTRATION = "회원가입이 완료되었습니다.";
    public static final String SUCCESS_ORDER_PLACED = "주문이 성공적으로 완료되었습니다.";
}