Spring발행일 2024. 7. 2.원본 https://blog.naver.com/jword_/223498958145 ↗

[JAVA Spring] MVC패턴이란?

[JAVA Spring] MVC패턴이란? — #JAVASpring #자바스프링 #의존성주입 #MVC #MVpattern #MVC패턴 #웹서버MVC패턴 #개발자...

#Spring#Naver Blog

#JAVASpring #자바스프링 #의존성주입 #MVC #MVpattern #MVC패턴 #웹서버MVC패턴 #개발자의도구들

​

AI스쿨 msa기반 java 백엔드 코스 중에 공부한 내용을 작성하였습니다

\* 현재 Spring 프로젝트를 진행 중입니다. 전체적인 목차를 보시려면 여기​를 눌러주세요.

​

MVC 패턴이란?

디자인 패턴 중 웹 서버에서 자주 사용되는 패턴으로, MVC 패턴이 있습니다. MVC패턴은 Model, View, Controler로 총 3개의 Layer로 구성된 패턴입니다. 이번글을 통해서 각 Layer 기능을 간략하게 살펴보고 간단한 예시 코드도 알아보겠습니다.

Model Layer

Model Layer는 데이터와 비즈니스 로직을 포함하는 Layer입니다. 서버에 데이터를 저장하고, 불러오고, 삭제하고, 수정하고 등 데이터와 관련된 모든 로직을 포함하며, 데이터가 저장된 레이어를 말합니다.

​

이 말만 듣고보면, 바로 떠오르는게 하나 있으실텐데요. 바로 DataBase입니다. 실제로 Model의 경우 옛날에 DataBase에 연결된 객체 자체를 의미하기도 하였습니다.

​

웹 서버를 구현할 때 DataBase와의 연결을 담당하고, 관련 로직을 수행한다면 Model Layer로 생각하시면 될 것 같습니다.

java 코드 예제
public class Employee {
    // declaring the variables
    private String EmployeeName;
    private String EmplyeeId;
    private String EmployeeDepartment;

    // defining getter and setter methods
       public String getId() {
          return EmployeeId;
       }

       public void setId(String id) {
          this.EmployeeId = id;
       }

       public String getName() {
          return EmployeeName;
       }

       public void setName(String name) {
          this.EmployeeName = name;
       }

       public String getDepartment() {
              return EmployeeDepartment;
           }

       public void setDepartment(String Department) {
              this.EmployeeDepartment = Department;
           }

}

View Layer

View Layer는 말 그대로 View를 담당하는 Layer입니다. 사용자로 하여금 서버로 부터 받은 데이터를 볼 수 있게끔 하는 역할입니다.

​

java 코드 예제
public class EmployeeView {
    // method to displyay the Employee details
    public vod printEmployeeDetails(String EmployeeName, String EmployeeId, String EmployeeDepartment) {
        System.out.println("Employee Details: ");
        System.out.println("Name: " + EmployeeName);
        System.out.println("Employee ID: " + EmployeeId);
        System.out.println("Employee Department: " + EmployeeDepartment);
    }
}

하지만, 현 시대는 FE와 BE가 서로 나눠져있기 때문에, View는 전적으로 FE가 담당합니다. 따라서 BE 프로젝트에서는 View가 존재하지 않습니다.

Controller Layer

Controller Layer는 Model과 Veiw 사이에 위치해 있습니다. 사용자의 input을 처리하고, input에 따른 action을 수행합니다. Controller는 Model과 View에 둘다 직접적으로 관여하는데, 유저로 부터 받은 Input 데이터를 해석하여 Model에게 필요한 로직을 처리하게끔 하여 데이터를 받아오고, 받아온 데이터를 View Layer에 전달하는 역할을 수행합니다.

​

Java Programming에서는 보통 데이터와 내부 로직을 캡슐화하여 외부에 노출되지 않도록 하는데, 컨트롤러는 유저와 Model 중간에 위치하여 안전하게 서버의 데이터를 유저에게 전달합니다.

java 코드 예제
public class EmplyeeContoller {
    // declaring the variable model and view
    private Employee model;
    private EmployeeView view;

    public EmployeeController(Employee model, Employee view) {
        this.model = model;
        this.view = view;
    }

    public void setEmployeeName(String name) {
        model.setName(name);
    }

    public String getEmployeeName(){
          return model.getName();
    }

    public void setEmployeeId(Stirng id) {
        model.setId(id);
    }

    public void getEmployeeId() {
        return model.getId();
    }

    public void setEmployeeDepartment(String Department){
        model.setDepartment(Department);
    }

    public String getEmployeeDepartment(){
        return model.getDepartment();
    }

    // method to update view
    public void updateView() {
        view.printEmployeeDetails(model.getName(), model.getId(), model.getDepartment())
    }
}

// model data( variables)에 대한 set/get이 이뤄진다.

​

Service Layer

Java Spring의 구조상 MVC에서 V가 없어지고 Service Layer가 있습니다. 이 Layer는 보통 핵심 로직을 담당하여, Model과 Controller 사이에 위치하게 됩니다.

​

느낌상 Layer를 많이 생성할 수 록 캡슐화를 통한 로직 은닉이 가능하기 때문에, 중간단계에 핵심 Logic들을 Service로 깔아둡니다.

( 자세한건 더 조사 후 수정하겠습니다)

​

​

Spring 웹서버에 적용하기

Model Layer

java 코드 예제
package com.example.webserver;

import jakarta.annotation.PostConstruct;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;

import java.sql.*;
import java.util.HashMap;

@Getter
@Repository
@Slf4j
public class DataBaseModel {
    private Connection connection;
    private final Object dataBaseLock = new Object();
    private final String url = "jdbc:mariadb://localhost:3306/http";
    private final String user = "root";
    private final String password = "3353";

    @PostConstruct
    public void startConnection() {
        log.info("start connection!!");
        try {
            this.connection = DriverManager.getConnection(url, user, password);
            log.info("connecting success");
        } catch (SQLException e) {
            log.error("<<DataBaseManger>>\n - sql err: " + e.getMessage() + "\n");
        }
    }
    public boolean putText(String key, String value) {
        String sql = "INSERT INTO texts (text_id, text_value) VALUES (?, ?)";

        try {
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, key);
            preparedStatement.setString(2, value);

            int effectedRows = preparedStatement.executeUpdate();
            preparedStatement.close();

            if (effectedRows > 0) {
                log.info("A new row has been inserted successfully.");
                return true;
            } else {
                log.error("A new row insertion failed");
                return false;
            }
        } catch (SQLException e) {
            log.error("DataBase Manger: putText err: " + e.getMessage());
            return false;
        }
    }

    --- 생략 ---
}

이전글에 JDBC를 활용하여 제가 만든 웹서버와 DB를 연결했었습니다. 이를 Spring으로 다시 Build하여 Model 부분을 구현했습니다. 로직이 크게 바뀌지는 않았습니다.

​

여기서는 DataBase와 연결되는 부분이 Model임을 말하고 싶었습니다.

Controller Layer

java 코드 예제
package com.example.webserver;

import lombok.AllArgsConstructor;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;

@RestController
@AllArgsConstructor
public class DataController {
    DataBaseModel dataBaseModel;

    @GetMapping("/time")
    public ResponseEntity<String> getTime() {
        LocalDateTime now = LocalDateTime.now();
        String formattedNow = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        return ResponseEntity.ok(formattedNow);
    }
    @GetMapping("/textall")
    public ResponseEntity<HashMap<String, String>> getTextAll() {
        HashMap<String, String> texts = dataBaseModel.getTextAll();
        if (texts != null && !texts.isEmpty()) {
            return ResponseEntity.ok(texts);
        }
        return ResponseEntity.noContent().build();
    }

    @GetMapping("/text/{id}")
    public ResponseEntity<String> getText(@PathVariable("id") String id) {
        String text = dataBaseModel.getText(id);
        if (text != null) {
            return ResponseEntity.ok(text);
        }
        return ResponseEntity.notFound().build();
    }

    @PostMapping("/text/{id}")
    public ResponseEntity<String> postText(@PathVariable("id") String id, @RequestBody String data) {
        boolean isSaved = dataBaseModel.putText(id, data);
        if (isSaved) {
            return ResponseEntity.status(HttpStatus.CREATED).body("Save successfully");
        }
        return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body("Error occurred");
    }

    @DeleteMapping("/text/{id}")
    public ResponseEntity<String> deleteText(@PathVariable("id") String id) {
        boolean isDeleted = dataBaseModel.deleteText(id);
        if (isDeleted) {
            return ResponseEntity.status(HttpStatus.ACCEPTED).body("Delete Successfully");
        }
        return ResponseEntity.notFound().build();
    }

}

이전글에서 HTTP 요청을 직접 parsing하여, 로직을 나눠, Response응답을 하였었습니다만, Spring에서는 직접 할 필요가 없습니다.

​

Spring의 @Controller 어노테이션을 사용하게 되면, 자동으로 해당 객체에 Controller 기능을 부여하게 됩니다. 심지어 @Contoller는 Reponse도 알아서 입맛대로 보낼 수 있습니다.

​

또한, 원한다면 Request로 받은 패킷의 Header정보도 불러올 수 있습니다. 제가 직접 구현한 모든 기능을 Spring에서는 이미 훨씬 더 잘 구현되어 있습니다. 그리고 이걸 사용하려면 단지 @어노테이션 하나만 붙이면 된다는게 상당히 매력적이네요!

​

어쨋든 사용자의 요청을 처리하는 로직이 담긴 Controler Layer를 보여드렸습니다!

​

\* Service는 아직 이해중이라 구현하지 못했습니다. 추후에 업데이트 해보겠습니다.