'GenericContorller'에 해당되는 글 1건

  1. 2018.09.20 :: springframework(스프링) Controller 작성전략(제네릭스,매핑정보상속)
Web/Spring 2018. 9. 20. 23:22

모든 컨트롤러의 중복된 로직 코드량 확줄여버리는 코딩전략, 제네릭스와 매핑정보 상속을 이용한 컨트롤러 작성전략




웹개발을 하면서 지겹도록 작성하는 코드가 CRUD 관련 코드이다. 매번 똑같은 패턴이며 도메인 오브젝트만 바뀔뿐 딱히 로직이 크게 차이가 없다. 그렇지만 우리는 서비스 클래스는 물론 컨트롤러의 코드에 CRUD코드가 많이 중복되며 대부분 서비스클래스에게 작업을 위임해주는 작업뿐이다. 그렇다면 어떻게 중복된 것을 최대한 배제시킬 수 있을까?

그것이 바로 제네릭스를 이용한 상속 전략이다. 바로 예제 코드로 넘어가면,


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
32
33
34
35
36
37
38
39
package com.toby.spring.controller;
 
import java.util.ArrayList;
import java.util.List;
 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
public abstract class GenericController<D,P,S> {
    S service;
    @RequestMapping(method=RequestMethod.POST)
    public int add(D dto) {
        System.out.println("DTO 객체에 대한 DAO 삽입로직");
        return 0;
    }
    @RequestMapping(method=RequestMethod.PUT)
    public int update(D dto) {
        System.out.println("DTO 객체에 대한 DAO 수정로직");
        return 1;
    }
    @RequestMapping(value="{id}",method=RequestMethod.GET)
    public D getByID(P primaryKey) {
        System.out.println("id 값을 이용하여 DTO 객체를 가져오는 DAO 로직");
        D d=(D) new Object();
        return d;
    }
    @RequestMapping(method=RequestMethod.DELETE)
    public int delete(P primaryKey) {
        System.out.println("id 값을 이용하여 해당 DTO 객체를 삭제하는 DAO 로직");
        return 1;
    }
    @RequestMapping(value="/all",method=RequestMethod.GET)
    public List<D> getByList(){
        System.out.println("DAO에서 DTO 타입의 객체 리스트를 가져오는 로직");
        List<D> dList=new ArrayList();
        return dList;
    }
}
 
cs


이것은 대부분의 컨트롤러에서 중복되는 CRUD관련 공통적인 컨트롤러 메소드 및 매핑선언이다. 여기서 집중해서 봐야하는 것이 제네릭스 타입이다. 물론 이것은 예제 코드라서 간단한 제네릭스 타입이지만(실무코드에서는 조금더 다듬어져야하는 부분) 대게 저렇게 3가지 타입으로 컨트롤러 단에서 CRUD 로직을 처리가능하다. 또하나 집중해서 봐야하는 것은 추상클래스의 메소드의 @RequestMapping이다. 이거 관련해서는 뒤에서 설명한다. 이 추상클래스를 상속하는 실 컨트롤러 클래스를 만들어준다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.toby.spring.controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
 
import com.toby.spring.dto.UserDTO;
import com.toby.spring.service.UserService;
 
@Controller
@RequestMapping("/user")
public class UserController extends GenericController<UserDTO, Integer, UserService>{
    @RequestMapping("/login")
    public void login(UserDTO userDto) {
        System.out.println("로그인 인증관련 로직");
    }
    @RequestMapping("/logout")
    public void logout() {
        System.out.println("로그아웃 관련 로직");
    }
}
 
cs


너무 간단하지 않은가? CRUD 관련 메소드는 보이지도 않으면서 메소드를 이용할 수 있다. 상속받은 컨트롤러 제네릭스 타입에 집중하자 그러면 추상클래스의 제네릭스 타입들에 들어가는 타입을 알 수 있을 것이며, 이것들은 많이 봐왔던 패턴일 것이다. 그리고 중요한 것이 실 컨트롤러 클래스 타입에 공통적인 url패턴을 등록하고 각각 CRUD 로직의 매핑은 추상클래스의 매핑타입을 그대로 상속받아 사용하는 것이다. 그렇다면 여타 게시판관련 CRUD에서는 똑같이 추상클래스를 상속하고 단순히 클래스 타입에 @RequestMapping url값만 바꿔주면 그대로 사용이 가능한 것이다. 물론 CRUD 이외의 매핑과 메소드는 실 컨트롤러 클래스에서 선언하여 사용할 수 있다. 이렇게 제네릭스 타입을 이용하여 추상클래스를 만들면 여타 엄청난 양의 코드가 줄어버린다. 지금은 컨트롤러에서만 이 전략을 이용하였지만 추후에 서비스클래스 쪽과 DAO쪽도 이와 같은 전략을 이용한다면 전체적으로 일관된 프로젝트 전략이 될것이며 덩달아 코드량도 엄청나게 줄어버릴 것이다. 



posted by 여성게
: