MVC패턴과 Service, Controller, Repository

Estar·2024년 8월 3일

Spring

목록 보기
1/3
post-thumbnail

MVC 패턴이란?

MVC 패턴은 Model-View-Controller의 약자로, 소프트웨어 디자인 패턴 중 하나입니다. MVC 패턴은 애플리케이션을 세 가지 주요 구성 요소인 모델(Model), 뷰(View), 컨트롤러(Controller)로 나누어 각각의 역할을 명확히 분리함으로써, 코드의 재사용성과 유지보수성을 높이는 데 목적이 있습니다.

MVC의 구성 요소와 역할

  • 모델(Model)

애플리케이션의 데이터와 그 데이터를 처리하는 비즈니스 로직을 담당합니다.
데이터베이스와 상호작용하며, 데이터를 가져오거나 저장하는 역할을 합니다.
상태 변화를 관리하고, 상태 변경이 발생하면 이를 뷰에 통보합니다.

  • 뷰(View)

사용자에게 보여지는 UI를 담당합니다.
모델로부터 데이터를 받아와서 화면에 표시합니다.
사용자의 입력을 받으며, 이를 컨트롤러에 전달합니다.

  • 컨트롤러(Controller)

사용자 입력을 처리하고, 그 입력에 따라 모델과 뷰를 업데이트하는 역할을 합니다.
사용자의 요청을 받고, 해당 요청을 처리할 모델을 호출하며, 처리 결과를 뷰에 전달합니다.

컨트롤러 (Controller)

컨트롤러는 사용자의 요청을 처리하고, 비즈니스 로직을 호출하며, 최종적으로 응답을 반환하는 역할을 합니다. 주로 웹 애플리케이션에서 사용자의 HTTP 요청을 처리하는 데 사용됩니다.

많은 종류의 서비스를 한 클래스를 만들어서 꽉꽉 몰아 처리할 게 아니라 Controller라는 중간 제어자를 만들어서 A서비스에 대한것은 A-Controller가 맡고 B서비스는 B-Controller 이런식으로 역할에 따라 설계를 하고 코딩을하면 개발비용이나 유지보수비용이 대폭 줄어들기 때문에 Controller를 사용한다고 함미당.

// Controller 구현 예시
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

@Controller
public class MemberController {

    private final MemberService memberService;

    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }

    @GetMapping("/members/new")
    public String createForm() {
        return "members/createMemberForm";
    }

    @PostMapping("/members/new")
    public String create(MemberForm form) {
        Member member = new Member();
        member.setName(form.getName());
        memberService.join(member);
        return "redirect:/members";
    }

    @GetMapping("/members")
    public String list(Model model) {
        model.addAttribute("members", memberService.findMembers());
        return "members/memberList";
    }
}

서비스 (Service)

서비스 계층은 비즈니스 로직을 담당합니다. 컨트롤러와 리포지토리 사이에서 중간 역할을 하며, 트랜잭션 관리 등의 중요한 비즈니스 로직을 처리합니다.

주요역할

  • Client가 Request를 보낸다.(Ajax, Axios, fetch등..)
  • Request URL에 알맞은 Controller가 수신 받는다. (@Controller , @RestController)
  • Controller 는 넘어온 요청을 처리하기 위해 Service 를 호출한다.
  • Service는 알맞은 정보를 가공하여 Controller에게 데이터를 넘긴다.
  • Controller 는 Service 의 결과물을 Client 에게 전달해준다.
//Service 구현 예시
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class MemberService {

    private final MemberRepository memberRepository;

    @Autowired
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    public Long join(Member member) {
        validateDuplicateMember(member);
        memberRepository.save(member);
        return member.getId();
    }

    private void validateDuplicateMember(Member member) {
        memberRepository.findByName(member.getName())
                .ifPresent(m -> {
                    throw new IllegalStateException("이미 존재하는 아이디입니다.");
                });
    }

    public List<Member> findMembers() {
        return memberRepository.findAll();
    }

    public Optional<Member> findOne(Long memberId) {
        return memberRepository.findById(memberId);
    }
}

리포지토리 (Repository)

리포지토리 계층은 데이터 접근을 담당합니다. 데이터베이스와의 CRUD(Create, Read, Update, Delete) 작업을 처리합니다. JPA, JDBC, MyBatis 등을 사용하여 데이터베이스와 상호 작용합니다.

import org.springframework.stereotype.Repository;

import java.util.*;

@Repository
public class MemoryMemberRepository implements MemberRepository {

    private static Map<Long, Member> store = new HashMap<>();
    private static long sequence = 0L;

    @Override
    public Member save(Member member) {
        member.setId(++sequence);
        store.put(member.getId(), member);
        return member;
    }

    @Override
    public Optional<Member> findById(Long id) {
        return Optional.ofNullable(store.get(id));
    }

    @Override
    public Optional<Member> findByName(String name) {
        return store.values().stream()
                .filter(member -> member.getName().equals(name))
                .findAny();
    }

    @Override
    public List<Member> findAll() {
        return new ArrayList<>(store.values());
    }
}

요약

컨트롤러(Controller): 사용자 요청을 처리하고 응답을 생성합니다.
서비스(Service): 비즈니스 로직을 처리하고 트랜잭션을 관리합니다.
리포지토리(Repository): 데이터베이스와의 CRUD 작업을 처리합니다.

참고 : https://velog.io/@jybin96/Controller-Service-Repository-%EA%B0%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C

profile
개발자를 꿈꿔요

0개의 댓글