MVC 패턴이란?
- Controller는 클라이언트로부터 요청을 받음. (처리 과정을 담당)
- Model은 최종 페이지에 쓰일 데이터를 뷰에 전달한다. (데이터를 담당)
- View는 최종 페이지를 만들어준다.
- 이렇게 각자의 역할을 나누는 기법을 MVC 패턴이라고 한다.
스프링 부트의 로직
- Controller : 웹 브라우저의 요청 전담하여 처리, Service 호출 →
- Provider/ Service: 비즈니스 로직(아이디 중복검사,비밀번호 재검사, validation...)을 수행하며, 데이터베이스에 접근하는 DAO를 이용해 결과값을 받아옴.
- Provider : Read와 관련된 곳으로, DB에서 select해서 얻어온 값을 가공해서 결과로 추출한다.
- Service : Create, Update, Delete와 관련된 곳으로, CUD에서도 Read관련 로직이 필요한 경우가 있는데, 이때는 Provider의 함수를 사용한다.
- DAO : 데이터베이스에 접속하여 비즈니스 로직 실행에 필요한 쿼리 호출 ->
- DB: 알맞은 쿼리 실행해 반환.
실제 작동 프로세스
- Controller내에서 관련된 Provider/Service의 함수 호출
- Provider 내에서 DAO 호출하여 데이터베이스 접근
- DAO내의 함수를 통해 DTO를 받아와서 비즈니스 로직 수행함.
- 이렇게 가공된 데이터 처리 결과를 가지고 Controller가 필요한 로직 수행 후에 브라우저에게 결과를 응답한다.
코드 예시
1) Controller
package com.example.demo.src.user;
//클래스 관련 정보 생략
@RestController
@RequestMapping("/app/users")
public class UserController {
final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private final UserProvider userProvider;
@Autowired
private final UserService userService;
@Autowired
private final JwtService jwtService;
public UserController(UserProvider userProvider, UserService userService, JwtService jwtService){
this.userProvider = userProvider;
this.userService = userService;
this.jwtService = jwtService;
}
/**
* 회원 조회 API
* [GET] /users
* 회원 번호 및 이메일 검색 조회 API
* [GET] /users? Email=
* @return BaseResponse<List<GetUserRes>>
*/
//Query String
@ResponseBody
@GetMapping("") // (GET) 127.0.0.1:9000/app/users
public BaseResponse<List<GetUserRes>> getUsers(@RequestParam(required = false) String Email) {
try{
if(Email == null){
List<GetUserRes> getUsersRes = userProvider.getUsers();
return new BaseResponse<>(getUsersRes);
}
// Get Users
List<GetUserRes> getUsersRes = userProvider.getUsersByEmail(Email);
return new BaseResponse<>(getUsersRes);
} catch(BaseException exception){
return new BaseResponse<>((exception.getStatus()));
}
}
}
@RestController
- Spring MVC 컨트롤러에 @ResponseBody가 추가된 것으로, RestController의 주용도는 JSON 형태로 객체 데이터를 반환하는 것이다. 데이터를 응답으로 제공하는 RESTFUL API를 개발할 때 주로 사용한다.
- Client는 URI 형태로 웹 서비스에 요청을 보낸다.
- Mapping되는 Handler와 그 Type을 찾는 DispatcherServlet이 요청을 인터셉트한다.
- DispatcherServlet은 Spring MVC application의 web.sml 파일에 등록됨.
- 모든 HTTP 요청을 수신하고 이를 컨트롤러 클래스에 위임한다.
- 스프링 부트는 이를 자동으로 등록하고 구성하여 수동으로 등록할 필요가 없다.
- RestController는 해당 요청을 처리하고 데이터를 반환한다.
@RequestMapping
우리가 특정 URI로 요청을 보내면 Controller에서 어떤 방식으로 처리할지 정의한다. 이때 들어온 요청을 특정 메소드와 매핑하기 위해 사용하는것이 @RequestMapping이다.
- value : 요청받은 url 설정
- method : HTTP Method 정의
@ResponseBody
클라이언트와 서버의 비동기 통신을 위해 사용하는 어노테이션으로, 자바 객체를 HTTP 요청의 바디 내용으로 매핑하여 클라이언트로 전송한다. 즉, 클라이언트로 응답 데이터를 전송할때 사용되며, @RestController 어노테이션을 사용하면 자동으로 해당 Body가 붙게 된다.
@GetMapping, @PostMapping, @PatchMapping....
해당 어노테이션은 HTTP Method에 맞게 추가하면 된다.
2) Service/Provider
@Service
public class UserProvider {
private final UserDao userDao;
private final JwtService jwtService;
final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
public UserProvider(UserDao userDao, JwtService jwtService) {
this.userDao = userDao;
this.jwtService = jwtService;
}
public List<GetUserRes> getUsers() throws BaseException{
try{
List<GetUserRes> getUserRes = userDao.getUsers();
return getUserRes;
}
catch (Exception exception) {
throw new BaseException(DATABASE_ERROR);
}
}
}
@Service/@Provider 어노테이션이 붙으며, 비즈니스 로직 (validation, 암호화...)을 수행하는 걸 확인할 수 있다.
@Service
- 해당 클래스를 루트 컨테이너에 빈(Bean) 객체로 생성해주는 어노테이션이다.
3) DAO
@Repository
public class UserDao {
private JdbcTemplate jdbcTemplate;
@Autowired
public void setDataSource(DataSource dataSource){
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public List<GetUserRes> getUsers(){
String getUsersQuery = "select * from UserInfo";
return this.jdbcTemplate.query(getUsersQuery,
(rs,rowNum) -> new GetUserRes(
rs.getInt("userIdx"),
rs.getString("userName"),
rs.getString("ID"),
rs.getString("Email"),
rs.getString("password"))
);
}
}
-> 직접 데이터베이스에 쿼리를 통해 접근하며, 데이터의 집합체인 DTO를 만들어 반환하는 걸 확인할 수 있다.
- @Repository : DB나 파일같은 외부 I/O 작업을 처리할때 사용하는 어노테이션이다. Service와 같이 루트 컨테이너에 빈을 생성하고, DAO 객체를 생성하려면 new가 아닌 해당 컨테이너를 통해서 받아와야 한다.
- Bean/Container/DI 관련 포스팅은 이전 포스팅 참조!
'Web > Java (Spring+JSP)' 카테고리의 다른 글
Spring Boot에서 구글 소셜 로그인 REST 방식으로 구현하기 (14) | 2022.03.11 |
---|---|
JWT을 활용한 로그인/ Interceptor를 활용한 인가 처리 구현 (0) | 2022.03.11 |
Spring 핵심 원리 #9- 컴포넌트 스캔 (0) | 2022.01.15 |
Spring 핵심 원리 #8- 싱글톤 컨테이너 (0) | 2022.01.12 |
Spring 핵심 원리 #7- 스프링 컨테이너 관련 인터페이스 (0) | 2022.01.11 |