SMALL

Given an array of positive integers nums and a positive integer target, return the minimal length of a contiguous subarray [numsl, numsl+1, ..., numsr-1, numsr] of which the sum is greater than or equal to target. If there is no such subarray, return 0 instead.

 

양수로 이루어진 배열 nums와 양수 integer target이 주어진다.

target보다 크거나 같은 연속적인 서브 배열의 길이를 구해라, 단 길이는 최소한이어야 한다.

만약 조건에 만족하는 서브 배열이 없는 경우에는 0을 반환하라.


주어진 배열에서 타겟보다 크거나 같은 서브 배열의 합의 길이를 구하는 문제이다.

해당 조건을 만족하는 여러개의 서브 배열이 존재할 수 있지만, 그중에서 가장 길이가 짧은 내역을 반환하면 된다. 

 

배열을 for문을 돌며 sum이 target보다 커지는 시점을 찾고,

해당 시점에서 idx가 0부터 sum을 빼며 길이를 짧게 하며 조건을 만족하는지 찾아보도록 하자.

중간중간 조건이 만족할 때마다, 해당 시점의 서브  배열의 길이를 체크하며 최솟값을 찾도록 하자.

 

    public int minSubArrayLen(int target, int[] nums) {

        int idx = 0;
        int rst = Integer.MAX_VALUE;
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];

            if (sum >= target) {
                // make shorter of idx
                rst = Math.min(rst, i - idx + 1);
                sum -= nums[idx];
                idx++;
                while (sum >= target) {
                    rst = Math.min(rst, i - idx + 1);
                    sum -= nums[idx];
                    idx++;
                }
            }
        }
        return rst == Integer.MAX_VALUE ? 0 : rst;
    }
LIST
SMALL

Spring Cloud Config는 비대칭키, 대칭키 각각 암호화/복호화 방식을 지원한다.

보안 측면에서 public key, private key가 각각 존재하는 비대칭키 방식이 더 안전하다. 

대칭키 방식은 암호화/복호화에 같은 키가 사용되므로 키가 유출됐을 때의 위험이 크다는 단점이 있다. 

 

 

비대칭키 생성 

// private key 생성
keytool -genkeypair -alias privateKey -keyalg RSA -dname "CN=Web Server,OU=Unit,O=Organization,L=City,S=State,C=US" -keypass "password123" -keystore privateKey.jks -storepass "password123" -storetype pkcs12

// 인증서 파일 생성
keytool -export -alias privateKey -keystore privateKey.jks -rfc -file trustServer.cer

// 인증서 파일 -> jks 파일 public key 생성
keytool -import -alias trustServer -file trustServer.cer -keystore publicKey.jks

 

Java Cryptography Extension (JCE) 설치

자바에서 제공하는 encrypt를 사용하기 위해서는 JCE 다운로드하여 classpath에 등록해주어야 한다. 

( 11버전 이후부터는 default로 포함되어 있다고 한다)

https://www.oracle.com/java/technologies/javase-jce-all-downloads.html )

 

server - application.yml 설정 추가 ( for encrypt endpoint )

encrypt:
  key-store:
    location: file:../server/key/privateKey.jks # location of key 
    alias: privateKey
    password: password123

 

encrypt endpoint 

 

spring cloud config - properties example 

 

spring cloud config - properties 조회

위의 내용을 그림으로 표현하면 아래와 같다.

spring cloud server에서 encrypt, decrypt를 모두 담당하게 된다.

client에게 properties를 전달할 때 decrypt 된 값들을 전달하는 것이다.

 

 

Server-Encrypt, Client-Decrypt

 

위와 같은 형태가 아닌 server에서는 encrypt된 properties를 들고 있고

client에서 해당 properties를 가져갈때 decrypt 하고 싶은 상황에는 아래와 같이 설정하면 된다.

 

server - application.yml 설정 추가 ( for encrypt endpoint )

spring:
  cloud:
    config:
      server:
        encrypt:
          enabled: false
encrypt:
  key-store:
    location: file:../server/key/publicKey.jks # location of key 
    alias: trustServer
    password: password123

server side에서 decrypt 하는 것을 방지하기 위해 

spring.cloud.config.server.encrypt.enabled = false로 지정 

server side에는 encrypt만 담당하기 위해 public key 등록 

 

 

client-appliation.yml 설정 추가 decrypt

encrypt:
  key-store:
    location: file:../sba-server/key/privateKey.jks
    alias: privateKey
    password: 1q2w3e4r

 

 

LIST
SMALL

Spring Cloud Config를 통해서 설정 값을 중앙에서 관리할 수 있다.

보통은 기본값으로 git을 통한 관리가 이루어진다.

(https://joomn11.tistory.com/79)

 

설정값들 중에 password와 같은 중요 데이터들은 암호화가 필요할 수 도있다.

이러한 경우에 어떻게 해야하는지 알아보도록 하자.

 

Java Cryptography Extension (JCE) 설치

자바에서 제공하는 encrypt를 사용하기 위해서는 JCE 다운로드하여 classpath에 등록해주어야 한다. 

( 11버전 이후 부터는 default로 포함되어 있다고 한다) (https://www.oracle.com/java/technologies/javase-jce-all-downloads.html)

 

 

application.yml 설정 추가 

대칭키를 이용하기 위해서는 application.yml or bootstrap.yml에 해당 설정 추가 

encrypt:
  key: test_key // set user key !

 

encrypt endpoint 

위의 두 설정을 완료한다면 encrypt endpoint를 이용하여 원하는 property를 암호화 할 수 있다.

 

암호화 property 설정

응답으로 온 값을 spring cloud config의 값으로 사용 할 수 있다.

 

 

실제 spring cloud config 서버에 로드된 값들을 조회해보면 아래와 같이 복호화된 형태로 조회가 된다.

 

추가적으로 암호화한 내용을 client로 전달할때 복호화를 하지 않고 건내고 싶은경우에 대해서 알아보자.

아래의 설정은 default값이 true이다.

해당 설정을 false로 바꾼다면 client에게 설정값을 전달할때 암호화 된 형태로 전달할 수 있다.

spring:
  cloud:
    config:
      server:
        encrypt:
          enabled: false

하지만 저 형태로 설정을 한다면, client 측에서는 encrypt.key값을 가지고 있어야지 spring cloud config로 부터 설정 값들을 받을 수 있다. 

해당 설정이 없다면 아래와 같은 exception이 발생한다.

 

 

 

 

LIST
SMALL

서버 개발을 하다 보면 오류 처리를 해야 될 경우가 매우 많이 존재한다.

오류를 제대로 처리하지 않는다면, 서버가 안정적이지 못하게 동작할 수 있다.

 

보통의 경우에는 Exception 처리를 try-catch를 통해 해결한다.

하지만 이러한 로직들은 비즈니스 로직이 존재하는 곳에 코드가 써져 

코드를 복잡하게 하고 유지보수를 어렵게 만든다.

 

이런 문제를 개선하기 위해 @ExceptionHandler와 @ControllerAdvice를 사용해 보자.

 

@ExceptionHandler

@Controller, @RestController가 적용된 bean 내에서 발생하는 예외를 처리할 수 있게 해주는 어노테이션

 

@RestController 
public class HelloController {
    @GetMapping("/error")
    public void test() {
    	throw new IllegalArgumentException("test error");
    }
    @ExceptionHandler(Exception.class)
    public ResponseEntity<?> handle(Exception ex) {
        return new ResponseEntity<>(new ResponseError(LocalDateTime.now(), "error"), HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

@ExceptionHandler는 등록된 해당 Controller에만 적용이 된다.

다른 Controller에서 발생하는 예외는 잡을 수 없다.

여러 Controller에서 동일하게 발생하는 예외는 Controller에 적용된 @ExcptionHandler가 아닌 다른 방법으로 처리해야 한다.

 

@ControllerAdvice

@Controller, @RestController에서 발생한 예외를 한 곳에서 처리할 수 있는 어노테이션

스프링에서 예외처리를 전역적으로 핸들링하기 위해 사용

@ControllerAdvice
public class GlobalExceptionHandler {

	@ExceptionHandler(IllegalArgumentException.class)
	public ResponseEntity<?> handleIllegalArguException(IllegalArgumentException e) {
		return new ResponseEntity<>(new ResponseError(LocalDateTime.now(), "error"), 
			HttpStatus.INTERNAL_SERVER_ERROR);
	}
}

Controller에 해당하는 모든 예외를 처리할 수 있지만, 사용자가 원한다면 특정 패키지로 제한을 할 수 있다

@ControllerAdvice("com.exam.controller")

 

@RestControllerAdvice

추가적으로 @RestControllerAdvice에 대해서 간단하게 알아보자

해당 어노테이션은 @ControllerAdvice + @ResponseBody 조합 어노테이션이라 생각하면 된다.

( @Controller, @RestController 관계와 비슷하게 @ResponseBody 설정이 추가된 어노테이션)

( https://joomn11.tistory.com/53?category=936835 )

 

다만 위에 예시처럼 Exception을 처리한 메서드의 리턴 값을 ResponseEntity로 지정을 한다면 @RestControllerAdvice 어노테이션을 사용하지 않고도 ResponseBody에 결괏값을 실을 수 있다.

 

@RestControllerAdvice 사용 예시

@RestControllerAdvice
public class GlobalExceptionHandler {

	@ExceptionHandler(IllegalArgumentException.class)
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
	public ResponseError handleIllegalArguException(IllegalArgumentException e) {
		return new ResponseError(LocalDateTime.now(), "error"));
	}
}
@Getter
@Setter
@AllArgsConstructor
public class ResponseError {
	private LocalDateTime timestamp;
    private String details;
}

다만, @RestControoerAdvice 어노테이션을 사용하는 경우 각각의 Handler 메서드에 @ResponseStatus 어노테이션을 추가해 주어야 한다.

( 해당 정보를 세팅하지 않는다면 디폴트로 200으로 응답)

LIST

+ Recent posts