[스프링 기초] 간단한 프로젝트 만들기

디자인 패턴

디자인 패턴이란 프로그램이나 어떤 특정한 것을 개발하는 중에 발생했던 문제점들을 정리해서 상황에 따라 간편하게 적용해서 쓸 수 있는 것을 정리하여 특정한 “규약”을 통해 쉽게 쓸 수 있는 형태로 만든 것을 말한다.

만약

웹 애플리케이션을 개발할 때 아무런 규칙이 존재하지 않는다면 어떻게 될까요?

다음의 코드를 봅시다.

package com.example;
 
import java.io.IOException;
import java.io.PrintWriter;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
@Controller
public class Test1 {
        
       @GetMapping("/")
       public void home(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       	  
          // DB 서버 주소
          String serverURL = "jdbc:mysql://localhost:3306/sys"; 
          
		  String id = "root";
		  String pw = "1234";

		  Class.forName("com.mysql.jdbc.Driver");			
		  Connection con = DriverManager.getConnection(serverURL, id, pw);

		  String sql = "select userNm from emp where userId = ?";
		  PreparedStatement pstmt = con.prepareStatement(sql);
          pstmt.setString("kdj9878");
		  ResultSet rs = pstmt.excuteQuery();
          
          String userNm = "";
          if(rs.next()){
          	userNm = rs.getString();
          }
          
          // step1: set the content type
          resp.setContentType("text/html");
          
          // step2: get the printwriter
          PrintWriter out = resp.getWriter();
         
          // step3: generate HTML content
          out.println("<html><body>");

          out.println("<h2>Hello World</h2>");
          out.println("My Name is " + userNm);
          out.println("<hr>");
          out.println("Time on the server is: "+new java.util.Date());
          
          out.println("</body></html>");
       }
    }

단지 예를 들기 위해서 극단적으로 작성된 코드입니다!!!

클라이언트에서의 요청을 받는 Controller 클래스에서 DB에 접근을 해 비지니스 로직을 처리하고 PrintWriter 클래스를 통해서 홈페이지 화면에 내용을 출력 하고 있습니다. 그런데 위의 코드와는 다르게 누군가는 비지니스 로직을 처리하는 부분을 분리해서 작성할 수도 있고 누군가는 JSP를 통해서 화면을 출력할 수 있습니다.

이러한 방식으로 여려명의 개발자가 각자 다른 방식으로 코드를 작성하게 되면 개발을 할 때나 유지 보수를 할 때 상당히 힘들어질 것입니다. 그래서 이 문제를 해결하기 위해서 디자인 패턴이라는 것이 존재하는 것이고 웹 애플리케이션을 개발할 때 가장 대표적으로 사용되는 것이 밑에서 설명할 MVC패턴입니다.

Spring MVC

MVC 패턴이란?

Spring MVC은 웹 사용자가 보는 화면, 비지니스 로직 처리, 웹 요청을 받는 부분을 분리한 디자인 패턴

위의 설명대로 MVC패턴은 코드를 Controller, Model, View 세 가지로 분리 해 각자의 역할에 집중하여 개발하는 것으로 작업의 효율성을 늘리고 후에 애플리케이션을 유지 보수할 때도 큰 이점을 가져오게 됩니다.

Controller

컨트롤러는 모델과 뷰를 연결 시켜주는 다리 역할을 함과 동시에 도메인 객체들의 조합을 통해 프로그램의 작동 순서나 방식을 제어한다.

Model

정보들의 가공을 책임지는 컴포넌트로 주로 데이터 베이스와 연동하여 사용자가 원하는 데이터를 출력하거나 변경하는 로직들을 처리하는 역할을 한다.

View

모델이 처리한 데이터나 그 작업 결과를 사용자에게 보여주는 역할을 한다.

이미지 출처

도메인 설정하기

도메인이란 소프트웨어로 해결하고자 하는 문제 영역

온라인으로 타코를 주문하는 타코 가게 사이트를 만든다고 가정을 한다면 개발자가 개발을 해야하는 이 타코 가게가 도메인이 됩니다. 그리고 타코 가게에서의 상품의 조회, 주문, 조회 등의 작업은 하위 도메인이 됩니다.

먼저 2개의 도메인 객체를 정의하겠습니다.

타코의 재료를 정의하는 도메인 객체

@Data
@RequiredArgsConstructor	
public class Ingredient {
	
	private final String id;
	private final String name;
	private final Type type;
	
	// enum => 서로 연관된 상수들의 집함
	public static enum Type{
		WRAP, PROTEIN, VEGGIES, CHEESE, SAUCE
	}
}

타코 디자인을 정의하는 도메인 객체

@Data
public class Taco {
	private String name;
	private List<String> ingredients;
}

위에서 정의한 두 도메인 객체를 보면 공통적으로 @Data 어노테이션이 사용되었습니다. 이 어노테이션의 경우 많은 기능들을 포함하고 있어 코드를 간결하게 해주는 장점을 가지고 있습니다.

기능은 다음과 같습니다.

@ToString : 해당 객체의 정보를 String 형태로 반환해줍니다.
@EqualsAndHashCode : 두 객체의 내용이 같은지 비교하는 equasl 메소드와 같은 객체인지 비교하는 hashCode 메소드를 생성해줍니다.
@Getter : 객체의 필드 정보를 받아올 수 있는 메소드를 생성해줍니다.
@Setter : 객체의 속성 값을 변경할 수 있는 메소드를 생성해줍니다.

컨트롤러 클래스 생성하기

다음으로 식자재를 고를 수 있는 페이지를 사용자에게 보여주는 Controller의 메소드를 작성해보겠습니다.

@Slf4j
@Controller
@RequestMapping("/design")
public class DesignTacoController {
	
	@GetMapping
	public String showDesignForm(Model model) {
		List<Ingredient> ingredients = Arrays.asList(
			new Ingredient("FLTO", "Flour Tortilla", Type.WRAP),
			new Ingredient("COTO", "Corn Tortilla", Type.WRAP),
			new Ingredient("GRBF", "Ground Beef", Type.PROTEIN)
			);
		Type[] types = Ingredient.Type.values();
		for(Type type : types) {
			model.addAttribute(type.toString().toLowerCase(),
			filterByType(ingredients, type));
		}
		model.addAttribute("taco", new Taco());
		return "design";
	}
	
	private List<Ingredient> filterByType(List<Ingredient> ingredients, Type type){
		return ingredients
				.stream()
				.filter(x -> x.getType().equals(type))
				.collect(Collectors.toList());
	}
 }
  1. 클라이언트에서 /design 경로에 대해서 GET 요청을 하게 되면 showDesignForm 메소드가 호출이 됩니다.
  2. new Ingredient(타코 재료의 식별자, 타코 재료 이름, 타코 재료 타입)를 통해 타코 재료 객체들을 생성해주고 Arrays.asList() 메소드를 통해 List로 바꿔줍니다.
  3. Ingredient클래스의 재료 타입들에 대한 배열을 만든 후 반복문을 돌려 "재료 타입" : 해당하는 재료 타입의 재료들을 model 객체에 추가합니다.
    ex) "wrap" : [{id : "FLTO", name : "Flour Tortilla", type : WRAP}, {id : "COTO", name : "Corn Tortilla", type : WRAP}]
  4. model 객체에 타코 객체를 생성해서 추가해줍니다.

결과 페이지

좋은 웹페이지 즐겨찾기