컴포넌트(component)란 여러 개의 프로그램 함수들을 모아 하나의 특정한 기능을 수행할 수 있도록 구성한 작은 기능적 단위를 말한다. 컴포넌트를 이용하면 소프트웨어 개발을 마치 레고(Lego) 블록을 쌓듯이 조립식으로 쉽게 할 수 있다. 모듈(module)이라고도 한다. 상용 컴포넌트에는 DextUpload, r-Mate Chart 등이 있다. 컴포넌트 기반의 개발 방법론을 CBD 방법론이라고 한다.
소프트웨어는 독립적으로 개발되지 않은 경우가 많고, 독립적으로 개발되어도 다른 모듈과의 호환을 생각하지 않고 개발한다. 이는 소프트웨어의 재사용을 어렵게 하고 유지보수 비용이 크게 증가하는 원인이 된다. 이러한 상황에서 소프트웨어의 재사용의 중요성과 필요성을 위해 나온 기술이 컴포넌트 기술이다.
기본 흐름과 주요 컴포넌트
스프링 MVC를 이용해서 서비스를 개발하려면 스프링 MVC가 어떤 식으로 동작하는지 이해하고 있어야 합니다.
기본적인 이해없이 개발하게 된다면 여러 응용 단계에서 더 나은 방안을 생각하기 어렵습니다.
이러한 문제를 해결하기 위해 기본 흐름과 주요 컴포넌트에 대해 알고 있을 필요가 있습니다.
최초에 사용자가 웹으로 요청을 하게되면 DispatcherServlet이 요청을 받으며, 밑의 이미지와 같은 과정을 거쳐 사용자 웹으로 응답을 전송하게 됩니다.
*순서
1. 요청전송
2. 요청 URL과 매칭 되는 컨트롤러 검색
3. 처리 요청
4. 실행
5. 결과
6. 컨트롤러 실행 결과를 ModelAndView로 리턴
7. 컨트롤러의 실행 결과를 보여줄 View 검색
8. 응답 생성 요청
9. 응답 생성
*DispatcherServlet
클라이언트의 요청을 전달받습니다. 컨트롤러에게 클라이언트의 요청을 전달하고, 컨트롤러가 리턴한 결괏값을 View에 전달하여 알맞은 응답을 생성하도록 합니다.
*HandlerMapping
클라이언트의 요청 URL을 어떤 Controller가 처리할지를 결정합니다.
*HandlerAdapter
DispatcherServlet의 처리 요청을 변환해서 Controller에게 전달하고, Controller의 응답 결과를 DispatcherServlet이 요구하는 형식으로 변환합니다.
웹브라우저 캐시 등의 설정도 담당합니다.
*Controller
클라이언트의 요청을 처리한 뒤, 결과를 리턴합니다.
응답 결과에서 보여줄 데이터를 모델에 담아 전달합니다.
*ModelAndView
Controller가 처리한 결과를 정보 및 뷰 선택에 필요한 정보를 담습니다.
*ViewResolver
Controller의 처리 결과를 보여줄 뷰를 결정합니다.
*View
Controller의 처리 결과 화면을 생성합니다.
JSP나 Velocity 템플릿 파일 등을 이용해서 클라이언트에 응답 결과를 전송합니다.
참조자료 : 웹 개발자를 위한 SPRING 4.0 프로그래밍
후기
스프링을 사용할 때 어떤 흐름으로 요청과 응답이 나오는지 모른다면 응용하기 힘들 것입니다.
요즘에는 스프링 부트를 사용하는데, 스프링 부트 장점 중 하나는 개발자가 기본적인 설정에 덜 신경 써도 된다는 것입니다.
그러다 보니 스프링 부트로 프로젝트를 만들고 요청받을 컨트롤러에 경로를 적어주면 만들어 놓은 비즈니스 로직대로 흘러간다 정도만 알 수도 있습니다.
하지만 명확하게 어떤 방식으로 동작하는지 알고 있어야 응용할 때 더 나은 방법으로 접근할 수 있습니다.
server:
port: 9000
spring:
profiles:
active: local
config:
import: "configserver:http://localhost:9100" # config server url
cloud:
config:
name: config # config name
profile: local # config sub name
label: main # branch name
management:
endpoints:
web:
exposure:
include: refresh # refresh
ConfigClientApplication
package cg.park.configclient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class, args);
}
}
ApiController
package cg.park.configclient.controllers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ApiController {
Logger logger = LoggerFactory.getLogger(this.getClass());
@RequestMapping("/test")
public String apiTest() {
logger.info("### info !!!");
logger.debug("### debug !!!");
return "test입니다.";
}
}
설명
서비스를 운영하다 보면 INFO 레벨로 자세한 로그 확인이 불가능하여
DEBUG로 로그레벨 변경 후 로그를 확인하는 경우가 있다.
하지만 로그레벨 변경 후 빌드를 하고 배포를 해야하기 때문에 서비스 운영에 문제가 있다.
Spring Cloud Config를 사용하면 빌드 후 재배포 과정없이 로그레벨 변경 가능하다.
Admin(관리자) 측이 설정 파일이 있는 Repository의 설정 값을 수정한다. (본인은 Git으로 했음. 로컬도 가능)
import java.util.LinkedList;
import java.util.Queue;
class Solution {
/**
* 카카오 캐시
* @param cacheSize
* @param cities
* @return
*/
public int solution(int cacheSize, String[] cities) {
int answer = 0;
int count = cities.length;
Queue<String> qu = new LinkedList<>();
for (int i = 0; i < count; ++i) {
String str = cities[i].toLowerCase();
// 캐시 사이즈가 0일 경우 밑의 로직 수행 X -> 수행 시간 +5
if (0 == cacheSize) {
answer += 5;
continue;
}
// 캐시에 존재하는 데이터면 순서 변경 후 수행 시간 +1
if (qu.contains(str)) {
qu.remove(str);
qu.add(str);
++answer;
continue;
}
// 캐시 사이즈에 자리가 없을 경우 먼저 들어온 데이터 제거 후 삽입 수행 시간 +5
if (qu.size() >= cacheSize) {
qu.poll();
qu.add(str);
answer += 5;
continue;
}
// 그 외 캐시에 삽입 후 수행 시간 +5
qu.add(str);
answer += 5;
}
return answer;
}
}
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {
/**
* 럭키 스트레이트
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine();
int count = str.length();
int left = 0;
int right = 0;
for (int i = 0; i < count/2; ++i) {
left += (str.charAt(i));
}
for (int i = count/2; i < count; ++i) {
right += (str.charAt(i));
}
System.out.println((left == right ? "LUCKY":"READY"));
}
}
후기
* 난이도 (5점 만점)
5 : 풀 줄 알면 기업 코딩테스트는 문제 없음.
4 : 평균적인 기업 코딩테스트의 중간 이상.
3 : 평균적인 기업 코딩테스트의 쉬운 문제 .
2 : 알고리즘 문제를 연습하고 있다면 풀 수 있는 문제.
1 : 시간이 오래 걸리지 않고, 누구나 풀 수 있는 문제.
난이도는 매우 쉬운 편이었으며 for문을 사용할 때 길이를 지정해서 사용할 줄 알면 어렵지 않다.