티스토리 뷰

MVC 구조의 개요

  • Model-View-Controller (MVC)사용자 인터페이스와 비즈니스 로직을 분리하여 개발 효율성과 유지보수성을 높이는 소프트웨어 아키텍처 패턴
  • 이 패턴은 애플리케이션을 세 가지 주요 컴포넌트로 분리

Model

  • 애플리케이션의 데이터와 비즈니스 로직을 담당하며, 상태와 동작을 정의

View

  • 사용자에게 데이터를 표시하는 역할을 담당하며, UI 요소를 구성

Controller

  • 사용자의 요청을 받아 처리하고, Model과 View 간의 상호작용을 중재

각 컴포넌트의 역할 및 책임

Model

역할

  • 애플리케이션의 데이터 구조와 비즈니스 로직을 담당

주요 책임

  • 도메인 객체와 데이터베이스 엔티티의 정의
  • 데이터 상태 관리 및 검증 로직 구현
  • 비즈니스 규칙 및 연산 처리

특징

  • 데이터 중심의 컴포넌트로, 뷰와 컨트롤러에 독립적이며 재사용 가능

View

역할

  • 사용자에게 정보를 시각적으로 전달하며, 데이터를 표시하는 역할을 함

주요 책임

  • Model로부터 전달받은 데이터를 기반으로 UI를 구성
  • 사용자 입력(클릭, 입력 등)을 Controller로 전달
  • HTML, CSS, JavaScript 등을 활용한 화면 렌더링

특징

  • 사용자 인터페이스를 담당하며, 디자인과 사용자 경험(UX)에 집중

Controller

역할

  • 사용자의 입력을 받아 이를 처리하고, Model과 View 간의 연결 역할을 수행

주요 책임

  • HTTP 요청 매핑 및 라우팅 처리 (GET, POST 등)
  • 요청 데이터의 유효성 검사 및 처리 로직 위임
  • Model로부터 데이터를 가져와 View에 전달
  • 사용자 액션에 따른 비즈니스 로직 호출

특징

  • 애플리케이션의 흐름을 제어하며, Model과 View 간의 중재자 역할을 담당

 

예시 코드 흐름 (Spring 기반 MVC)

1. 요청 발생 (Controller)

  • 클라이언트가 /products URL에 GET 요청을 보냄

2. 컨트롤러 처리

  • ProductController는 해당 요청을 매핑하고, 비즈니스 로직 처리를 위해 Service나 Model에 요청을 위임

3. 비즈니스 로직 실행 (Model)

  • Service나 도메인 Model은 데이터베이스와 상호작용하여 필요한 데이터를 조회 및 가공

4. View 렌더링

  • 컨트롤러는 조회된 데이터를 Model에 담아 View(예: Thymeleaf, JSP)로 전달하고, View는 이를 렌더링하여 사용자에게 응답

장점

관심사의 분리

  • 데이터 처리, 사용자 인터페이스, 제어 로직을 분리하여 유지보수 및 확장에 유리함

재사용성

  • Model과 View는 독립적으로 재사용 가능하며, 동일한 Model을 다양한 View에서 활용할 수 있음

테스트 용이성

  • 각 컴포넌트를 독립적으로 단위 테스트할 수 있어, 테스트 커버리지를 높일 수 있음

유연한 UI 변경

  • View 변경 시 비즈니스 로직에 영향을 주지 않으므로, UI 개선 및 리디자인이 용이함

단점 및 주의사항

초기 설계 복잡성

  • 단순 애플리케이션에서는 오히려 계층이 분리됨으로써 구조가 복잡해질 수 있음

컴포넌트 간 의존성 관리

  • 각 컴포넌트가 서로 적절히 분리되어야 하며, Controller가 Model이나 View에 과도하게 의존하지 않도록 주의 필요

실무 예시 상황: 온라인 서점 애플리케이션

예시 시나리오

  • 가상의 온라인 서점 애플리케이션에서는 사용자가 도서를 검색하고, 상세 정보를 확인할 수 있으며, 장바구니에 담아 주문할 수 있음
  • 이 예시를 통해 MVC 구조를 실제로 어떻게 적용하는지 알아봄

요구 사항

  • 도서 검색 - 사용자가 검색어를 입력하면, 해당 검색어를 기반으로 도서 목록을 조회
  • 도서 상세 정보 - 특정 도서를 선택하면, 해당 도서의 상세 정보를 보여줌
  • 장바구니 관리 - 사용자가 도서를 장바구니에 담고 주문을 진행할 수 있도록 함

실무 팁 적용

1. Model 구성

  • 도서(Book), 사용자(User), 주문(Order) 등 도메인 엔티티를 정의하고, 각 엔티티에 대해 비즈니스 로직(예: 재고 검증, 할인 정책 등)을 구현

2. View 구현

  • ThymeleafJSP를 사용하여 도서 목록, 상세 정보 페이지, 장바구니 페이지를 구현
  • 사용자 친화적인 UI/UX를 위해 CSS와 JavaScript를 활용해 동적 인터랙션을 추가

3. Controller 역할

  • BookController/books URL 매핑을 통해 도서 검색 및 상세 정보 요청을 처리
  • OrderController는 장바구니 관리와 주문 처리를 담당하며, 입력 검증 및 에러 핸들링을 수행

4. 의존성 주입 및 계층 분리

  • Controller는 Service를 주입받아 비즈니스 로직을 위임하고, Service는 도메인 Model과 Repository에 접근하여 데이터를 처리
  • Spring의 DI 컨테이너를 활용해 느슨한 결합을 유지

5. 예외 처리 및 로깅

  • 글로벌 예외 처리(@ControllerAdvice)를 통해 사용자에게 일관된 에러 메시지를 반환
  • AOP 기반 로깅을 적용하여 서비스 호출 전후로 로그를 남겨 디버깅과 모니터링을 강화

구현 예시 (간략한 코드 샘플)

// Model (Entity)
@Entity
public class Book {
    @Id @GeneratedValue
    private Long id;
    private String title;
    private String author;
    private BigDecimal price;
    // 생성자, getter, setter 등
}
// Controller 예시
@Controller
@RequestMapping("/books")
public class BookController {

    private final BookService bookService;
    
    public BookController(BookService bookService) {
        this.bookService = bookService;
    }
    
    @GetMapping
    public String searchBooks(@RequestParam String query, Model model) {
        List<Book> books = bookService.searchBooks(query);
        model.addAttribute("books", books);
        return "book/list"; // Thymeleaf 뷰 이름
    }
    
    @GetMapping("/{id}")
    public String bookDetail(@PathVariable Long id, Model model) {
        Book book = bookService.getBookById(id);
        model.addAttribute("book", book);
        return "book/detail";
    }
}
// Service 예시
@Service
@Transactional
public class BookService {

    private final BookRepository bookRepository;
    
    public BookService(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }
    
    public List<Book> searchBooks(String query) {
        // 비즈니스 로직 및 검색 알고리즘 적용
        return bookRepository.findByTitleContaining(query);
    }
    
    public Book getBookById(Long id) {
        return bookRepository.findById(id)
                             .orElseThrow(() -> new ResourceNotFoundException("Book not found"));
    }
}
// Repository 예시 (Spring Data JPA 활용)
public interface BookRepository extends JpaRepository<Book, Long> {
    List<Book> findByTitleContaining(String query);
}

 


면접 대비 질문

더보기

기본 질문

Q1. MVC 패턴의 구성 요소와 각각의 역할에 대해 설명하세요.

모범 답변
MVC 패턴은 Model, View, Controller로 구성됩니다.

  • Model: 데이터와 비즈니스 로직을 담당하며, 애플리케이션의 상태를 관리합니다.
  • View: 사용자 인터페이스를 담당하여 데이터를 표시하고 사용자와 상호작용합니다.
  • Controller: 사용자 입력을 받아 Model과 View 간의 연결 및 흐름을 제어합니다.

Q2. MVC 패턴을 사용함으로써 얻을 수 있는 이점은 무엇인가요?

모범 답변
MVC 패턴은 관심사의 분리를 통해 유지보수성, 확장성, 재사용성을 높입니다. 또한, 각 컴포넌트를 독립적으로 테스트할 수 있어 개발 및 디버깅 과정이 용이합니다.


심화 질문

Q1. Spring MVC에서 Controller와 View의 역할은 어떻게 분리되며, 실제 요청 흐름은 어떻게 진행되나요?

모범 답변
Spring MVC에서는 @Controller 어노테이션이 붙은 클래스가 사용자 요청을 받아 처리합니다.
컨트롤러는 비즈니스 로직 처리를 위해 Service 또는 Model을 호출하고, 처리 결과를 Model 객체에 담아 View(예: Thymeleaf, JSP)로 전달합니다.
ViewResolver가 이를 해석하여 최종 사용자에게 렌더링된 페이지를 반환합니다.


Q2. MVC 패턴을 사용하면서 발생할 수 있는 단점과 이를 극복하기 위한 방법은 무엇인가요?

모범 답변
MVC 패턴은 초기 설계 시 구조가 복잡해질 수 있으며, 각 컴포넌트 간 의존성 관리가 중요합니다.
이를 극복하기 위해 의존성 주입(DI)와 AOP 등을 활용하여 컴포넌트 간의 결합도를 낮추고, 각 계층의 역할을 명확히 구분하는 것이 필요합니다.


압박 질문

Q1. Controller가 너무 많은 로직을 처리하게 되는 경우의 문제점과 해결 방안은 무엇인가요?

모범 답변
Controller에 비즈니스 로직이 과도하게 포함되면, 코드의 응집도가 낮아지고 테스트가 어려워집니다.
이 경우, 로직을 Service 계층으로 분리하여 Controller는 단순히 요청과 응답을 중재하도록 개선해야 합니다.


Q2. MVC 패턴과 다른 아키텍처 패턴(예: MVVM, MVP)과의 차이점에 대해 설명하세요.

모범 답변
MVC는 Model, View, Controller로 구성되며, Controller가 사용자 입력을 받아 Model과 View를 연결합니다.
반면, MVVM에서는 View와 ViewModel이 명확히 분리되어 데이터 바인딩을 통해 상호작용하며, MVP는 Presenter가 Controller 역할을 수행하여 View와 Model 간의 중재를 담당합니다.
각 패턴은 애플리케이션의 특성에 따라 장단점이 있으며, MVC는 전통적인 웹 애플리케이션에서 널리 사용됩니다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/08   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함