[Java] MVC 패턴

cowmin·2025년 7월 20일

1. MVC 패턴이란

모델-뷰-컨트롤러(model–view–controller, MVC)는 소프트웨어 공학에서 사용되는 소프트웨어 디자인 패턴이다. 이 패턴을 성공적으로 사용하면, 사용자 인터페이스로부터 비즈니스 로직을 분리하여 애플리케이션의 시각적 요소나 그 이면에서 실행되는 비즈니스 로직을 서로 영향 없이 쉽게 고칠 수 있는 애플리케이션을 만들 수 있다. MVC에서 모델은 애플리케이션의 정보(데이터)를 나타내며, 뷰는 텍스트, 체크박스 항목 등과 같은 사용자 인터페이스 요소를 나타내고, 컨트롤러는 데이터와 비즈니스 로직 사이의 상호동작을 관리한다.
출처: MVC - wikipedia



2. MVC 패턴 구조

단계데이터 형태설명
클라이언트 → Controller요청 DTOJSON으로 요청, DTO로 매핑
Controller → Service요청 DTOService에 전달
Service → RepositoryEntityDTO를 Entity로 변환
Repository ↔ DBEntity ↔ 테이블JPA가 자동 매핑
Service ← RepositoryEntityDB 결과 반환
Service → Controller응답 DTOEntity를 DTO로 변환
Controller → 클라이언트JSON응답 DTO를 JSON으로 반환

2.1 Controller – 요청을 받고 응답을 만든다

  • HTTP 요청을 받음
  • 요청 데이터를 DTO로 받음 (@RequestBody, @PathVariable 등)
  • Service를 호출해서 처리하고, 결과를 다시 DTO로 응답함

2.2 Service – 비즈니스 로직 처리

  • 핵심 비즈니스 로직 담당
  • Repository를 호출하고, Entity ↔ DTO 변환함

2.3 Repository – DB와 직접 통신

  • Entity를 DB에서 읽고 쓰는 역할
  • 전통적인 DAO(Data Access Object)의 역할을 수행함

2.4 Model

  • 요청, 응답에서 필요한 데이터만 담기 위해 사용
  • 로직 없이 순수하게 데이터만 담는 클래스

2.4.1 Entity

DB 테이블과 매핑되는 비즈니스 객체

2.4.2 DTO(Data Transfer Object)

Controller ↔ Service 간 데이터 전달 객체

2.5 View

  • 사용자가 보는 화면(UI)을 구성하는 영역
  • 백엔드가 JSON 응답을 반환하면, 프론트엔드는 그 데이터를 View에서 표시


3. MVC 패키지 구조

도메인별 패키지 구조 + 하위에 역할별 패키지 구조

 user
 ┣ 📂controller
 ┣ 📂service
 ┣ 📂model
 ┣ 📂entity
 ┣ 📂repository

board
 ┣ 📂controller
 ┣ 📂service
 ┣ 📂model
 ┣ 📂entity
 ┣ 📂repository


4. MVC 패턴 예시

4.1 controller/BoardCreateController

package com.example.board.controller;

@WebServlet("/board/create")
public class BoardCreateController extends HttpServlet {
    private final BoardService boardService = new BoardService();
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            BoardDto.Create dto = BoardDto.Create.from(req);
            Boolean result = boardService.create(dto);
    }
}

4.2 model/BoardDto

package com.example.board.model;

public class BoardDto {

    public static class Create {
        private String title;
        private String contents;
        
        public static Create from(HttpServletRequest req) throws IOException {
            ObjectMapper objectMapper = new ObjectMapper();
            BoardDto.Create dto = objectMapper.readValue(req.getReader(), Create.class);
            return dto;
        }

        public String getTitle() {
            return title;
        }

        public String getContents() {
            return contents;
        }
    }
}

4.3 service/BoardService

package com.example.board.service;

public class BoardService {
    private final BoardRepository boardRepository = new BoardRespositoryImplJdbc();
    
    public Boolean create(BoardDto.Create dto) throws SQLException {
        return boardRepository.save(dto) > 0;
    }
}

4.4 repositoty

4.4.1 BoardRepository

package com.example.board.repository;

public interface BoardRepository {
    Integer save(BoardDto.Create dto) throws SQLException;
    BoardDto.BoardList findAll() throws SQLException;
    BoardDto.Read findById(Integer idx) throws SQLException, IOException;
}

4.4.2 BoardRespositoryImplJdbc

package com.example.board.repository;

public class BoardRespositoryImplJdbc implements BoardRepository {

    @Override
    public Integer save(BoardDto.Create dto) throws SQLException {
        Statement stmt = DBUtil.getStatement();

        Integer result = stmt.executeUpdate(
                "INSERT INTO board (title, contents) VALUES ('"
                        + dto.getTitle() + "', '"
                        + dto.getContents() + "')");

        return result;
    }
}

0개의 댓글