소스코드 

List<Integer> AList = new ArrayList<Integer>();
for(int i= 0 ; i < A.length ; i ++){
	AList.add(A[i]);
}
Collections.sort(AList);

int result = 1;
if(AList.get(0) != 1){
	result = 0;
}
else{
	if(AList.size() > 1){
		for(int i = 1 ; i < AList.size() ; i ++){
			if((AList.get(i) - AList.get(i-1)) != 1){
				result = 0;
				break;
			}
		}
	}
}

System.out.println(result);

'공부-codility' 카테고리의 다른 글

[Lesson] 4. FrogRiverOne  (0) 2022.08.08
[Lesson] 3. TapeEquilibrium  (0) 2022.08.04
[Lesson] 3. PermMissionElem  (0) 2022.08.04
[Lesson] 3. FrogJmp  (0) 2022.08.04
[Lesson] 2. Arrays - OddOccurrencesInArray  (0) 2022.08.04

소스코드 

Map<Integer, Integer> xCnt = new HashMap();
int cntResult = -1;
for(int i = 0; i < A.length ; i ++){
	if(A[i] <= X){
		xCnt.put(A[i], 0);
		if(xCnt.size() == X){
			cntResult = i;
			break;
		}
	}
}

System.out.println(cntResult);

'공부-codility' 카테고리의 다른 글

[Lesson] 4. PermCheck  (0) 2022.08.08
[Lesson] 3. TapeEquilibrium  (0) 2022.08.04
[Lesson] 3. PermMissionElem  (0) 2022.08.04
[Lesson] 3. FrogJmp  (0) 2022.08.04
[Lesson] 2. Arrays - OddOccurrencesInArray  (0) 2022.08.04

소스코드 

int leftSum = 0;
int rightSum = 0;

int min = 0;

// 2. 한칸씩 이동하며 leftSum 과 차이 계산
for(int p = 0 ; p < A.length ; p ++){

	// 초기화
	if(p == 0){
		leftSum = 0;
		for(int i = 0 ; i < A.length ; i ++){
			rightSum += A[i];
		}
	}
	else if(p == 1){
		leftSum = A[0];
		rightSum = rightSum - A[0];
		min = Math.abs(rightSum - leftSum);
	}
	else {
		leftSum = leftSum+A[p-1];
		rightSum = rightSum - A[p-1];
		if(min > Math.abs(rightSum-leftSum)){
			min = Math.abs(rightSum-leftSum);
		}
	}
}
return min;

'공부-codility' 카테고리의 다른 글

[Lesson] 4. PermCheck  (0) 2022.08.08
[Lesson] 4. FrogRiverOne  (0) 2022.08.08
[Lesson] 3. PermMissionElem  (0) 2022.08.04
[Lesson] 3. FrogJmp  (0) 2022.08.04
[Lesson] 2. Arrays - OddOccurrencesInArray  (0) 2022.08.04

소스코드 

Map<Integer, Boolean> AMap = new HashMap<>();
for (int i = 0; i < A.length; i++) {
	AMap.put(i+1, false);
}
AMap.put(AMap.size()+1, false);

for(int i = 0 ; i < A.length; i ++){
	AMap.put(A[i], true);
}

int result = 1;
Iterator<Integer> keys = AMap.keySet().iterator();
while( keys.hasNext() ){
	Integer key = keys.next();
	if(AMap.get(key) == false) {
		result = key;
		break;
	}
}
return result;

'공부-codility' 카테고리의 다른 글

[Lesson] 4. FrogRiverOne  (0) 2022.08.08
[Lesson] 3. TapeEquilibrium  (0) 2022.08.04
[Lesson] 3. FrogJmp  (0) 2022.08.04
[Lesson] 2. Arrays - OddOccurrencesInArray  (0) 2022.08.04
[Lesson] 2. Arrays - CyclicRotation  (0) 2022.08.04

소스코드 

int div = (Y-X) / D;
int mod = (Y-X) % D;

if(mod > 0){
	div++;
}
return div;

 

'공부-codility' 카테고리의 다른 글

[Lesson] 3. TapeEquilibrium  (0) 2022.08.04
[Lesson] 3. PermMissionElem  (0) 2022.08.04
[Lesson] 2. Arrays - OddOccurrencesInArray  (0) 2022.08.04
[Lesson] 2. Arrays - CyclicRotation  (0) 2022.08.04
[Lesson] 1. Iterations  (0) 2022.08.04

소스코드 

Map<Integer, Integer> counterMap = new HashMap<Integer, Integer>();
for(int i = 0 ; i < A.length ; i ++){
	if(!counterMap.containsKey(A[i])){
		counterMap.put(A[i], 1);
	}
	else{
		if( (counterMap.get(A[i]) + 1) % 2 == 0 ){
			counterMap.remove(A[i]);
		}
		else{
			counterMap.put(A[i], counterMap.get(A[i]) + 1);
		}
	}
}

int result = 0;
Iterator<Integer> keys = counterMap.keySet().iterator();
while( keys.hasNext() ){
	Integer key = keys.next();
	result = key;
}
return result;

'공부-codility' 카테고리의 다른 글

[Lesson] 3. TapeEquilibrium  (0) 2022.08.04
[Lesson] 3. PermMissionElem  (0) 2022.08.04
[Lesson] 3. FrogJmp  (0) 2022.08.04
[Lesson] 2. Arrays - CyclicRotation  (0) 2022.08.04
[Lesson] 1. Iterations  (0) 2022.08.04

소스코드 

if(A.length==0){
	return A;
}

List<Integer> AList = new ArrayList<Integer>();
for(int i = 0 ; i < A.length ; i++){
	AList.add(A[i]);
}

while(K > 0){
	Integer temp = AList.get(AList.size()-1);
	AList.remove(AList.size()-1);
	AList.add(0, temp);
	K--;
}

for(int i = 0 ; i < AList.size() ; i++){
	A[i] = AList.get(i);
}
return A;

 

'공부-codility' 카테고리의 다른 글

[Lesson] 3. TapeEquilibrium  (0) 2022.08.04
[Lesson] 3. PermMissionElem  (0) 2022.08.04
[Lesson] 3. FrogJmp  (0) 2022.08.04
[Lesson] 2. Arrays - OddOccurrencesInArray  (0) 2022.08.04
[Lesson] 1. Iterations  (0) 2022.08.04

소스코드

// 1. make int to binary
String binaryStr = "";
int tempN = N;
while(true){
	if(tempN == 0){
		break;
	}

	int div = tempN % 2;
	binaryStr = div + binaryStr;
	tempN = tempN / 2;
}
// 2. split by 1
String [] arr = binaryStr.split("1");


int arrCount = 0;
// 3. if end of string is 0
if(binaryStr.substring(binaryStr.length()-1).equals("0")){
	arrCount = arr.length-1;
}
// 4. if end of string i 1
else{
	arrCount = arr.length;
}

// 5. find max length
int max = 0;
for(int i = 0 ; i < arrCount ; i++){
	if(max < arr[i].length())
		max = arr[i].length();
}

 

풀이

1. 10진수를 2진수의 문자열로 변환한다.

2. 1번에서 만든 결과를 문자 "1"을 기준으로 분할시킨다. 

3. (예외처리) 1의 자리 값이 0이라면, 2번에서 생성된 배열의 마지막 값은 사용할 수 없다. 

4. (예외처리) 1의 자리 값이 1이라면, 2번에서 생성된 배열의 마지막 값을 사용할 수 있다. 

5. 문자열 배열의 길이값 max를 구한다. 

 

'공부-codility' 카테고리의 다른 글

[Lesson] 3. TapeEquilibrium  (0) 2022.08.04
[Lesson] 3. PermMissionElem  (0) 2022.08.04
[Lesson] 3. FrogJmp  (0) 2022.08.04
[Lesson] 2. Arrays - OddOccurrencesInArray  (0) 2022.08.04
[Lesson] 2. Arrays - CyclicRotation  (0) 2022.08.04

하게 된 이유

https://chainbell.tistory.com/entry/MSA-%EC%B5%9C%EC%86%8C-%EC%84%A4%EA%B3%84-%EC%9A%B4%EC%98%81-%EC%A0%81%EC%9A%A9?category=863960 

 

MSA 최소 설계 (운영 적용)

하게 된 이유 책 내용 그대로 따라하기엔 업무에서 바로 적용을 할 수가 없었다. 이벤트 처리기와 저장소, (여기에 정리하지 않은) DTO 기반 API 구현과 중복 이벤트에 대한 처리 등등 필요는 하지

chainbell.tistory.com

이전 MSA 구성을 최소한으로 적용하여 실제 운영 적용했던 경험을 바탕으로 더 개선할 수 없을까 고민하고 있었다.

이 구성은 간단하고 이해하기 쉬워 만족하긴 했지만 어디까지나 각 서버간 상호 작용에 중점을 둔 구성이었다.

프로젝트 내부적 정리는 되지 않은 상태였기 때문에 이번엔 내부적은 개선을 고려해보기로 했다. 

 

적용한 개념 

내부 구조의 정리를 위해 전에 알아봤던 개념들을 오랜만에 꺼내왔다. 

도메인 기반 설계(Domain Driven Design)의 구성 단위이자, MSA 개발의 최소 단위인 Aggregate이다. 

https://chainbell.tistory.com/entry/1-%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C%EC%84%9C%EB%B9%84%EC%8A%A4-%ED%8C%A8%ED%84%B4MSA%EC%B5%9C%EC%86%8C-%EB%8B%A8%EC%9C%84-%EC%95%A0%EA%B7%B8%EB%A6%AC%EA%B1%B0%ED%8A%B8aggregate?category=863960 

 

1. 마이크로서비스 패턴(MSA)최소 단위 : 애그리거트(aggregate)

애그리거트(aggregate)란? 도메인 객체(Domain object)들을 하나로 취급하는 객체망이다. 애그리거트의 단 하나의 Root Entity와 N개의 기타 객체들(Entity, DTO, DAO, VO, 서비스 로직 객체 등등)로 되어 있다...

chainbell.tistory.com

 

그림으로 보는 구성

기본적인 틀은 MSA Batch Server이다. 하지만 API 서버에도 동일하게 적용할 수 있다.

위 그림에서는 이해를 돕기 위해 Aggregate에서 전달, 반환용 객체는 Aggregate의 범위에서 외부로 걸쳐있는 것처럼 묘사하였다. 

순번대로 설명을 하면 

1) 스케쥴 예약이 된 Batch 서버에서 요청을 담은 Queue로부터 요청을 Pop하여 추출한다.

2) Pop한 요청에 해당하는 Service Method를 호출한다. 

3) Service Method는 Domain Aggregate에 Primary Key를 전달한다.

4) 전달된 Primary Key를 가지고 Aggregate 내에 구현되어있는 실질적인 Service Logic을 실행한다. 

5) 실행된 Service Logic의 결과를 정해진 반환 객체 형태로 변환한다.

6) 반환 객체 형태로 변환된 결과값을 반환한다. 

7) 3)의 과정을 다른 Aggregate에서 진행한다.

8) 4)의 과정을 다른 Aggregate에서 진행한다.

9) 5)의 과정을 다른 Aggregate에서 진행한다.

10) 6)의 과정을 다른 Aggregate에서 진행한다.

11) 3~6, 7~10의 과정으로 반환받은 결과를 정리하여 실행 성공 여부를 반환한다. (API 서버였다면 정리된 결과를 클라이언트에게 반환하면 된다.)

 

이전의 최소 설계와 다른 점은?

이번에 중점을 둔 구간은 3~6번의 과정을 다루는 Aggregate의 구간이다. 최소 적용했던 이전 설계는 Service Class에서 모든 Service Logic을 담고 있기 때문에, Business Logic 별 Service Logic의 정리가 되어 있지 않았다. 그로 인한 Service Logic의 재활용도가 낮았고, Service Class 간의 호출에도 유동적으로 대처할 수 없었다. 

하지만 위 구조로 재설계하면 실질적인 Service Logic은 Domain Aggregate내에 위치하게 되며, Service Class는 Domain으로부터 빌려오기만 하면 된다. 

 

단점은 없을까?

1) 개발 단계에서 Domain, Service Class간 설계에 신경을 많이 써야 한다.

2) 설계의 실수가 발생한 채로 운영까지 배포하게 되면 되돌리기 위한 추가 공수가 발생하게 된다.

3) Domain과 Service Class 사이의 명확한 경계를 제안하는 명세가 필요하게된다. 

 

서버 프로젝트의 구성은?

Aggregate를 적용하기 전에는 Service Package들이 각각 Service Logic과 그에 해당하는 sql들을 보유했다.

하지만 그 역할을 각 Domain이 맡게 되면서 Service Class는 필요한 기능을 명세하는 수준의 코드가 되고, Domain Aggregate의 영역에 Service Logic이 포함되기 때문에 명세와 로직의 구분을 눈으로 볼 수 있도록 위와 같이 분리 시켰다. 

 

위 구상의 적용은 가능할까?

개인 프로젝트로는 위 구성으로 만들어봤자, 이 구조를 위한 프로젝트를 만들어질 뿐이다. 그래서 현재 실무에서 적용할 수 있을지 생각해봤는데, 마침 딱 좋은 프로젝트가 있다. 

실제 적용을 할 순 없겠지만, 동료 개발자와 의논을 해봐야겠다. 

Finalize란?

Class의 resource를 자동으로 관리해주기 위한 장치이다. 

비유하자면, c++의 destructor(소멸자)의 역할을 한다. 

ex) file open을 한 후 작업이 끝났을 때, finalize에서 file close 작업을 처리하도록 등록을 한다. 그러면 객체 소멸 시 finalize가 실행 되면서 file close 작업을 진행하게 된다. 

* Finalize의 의의는 resource 소유권을 객체의 수명에 묶어서, 개발자가 아닌 platform/software에 의해 관리되도록 개발하는 것이다. 

 

하지만?

* Java 9에서 deprecated 되었다. 

resource 관리의 안전성을 보장해주는 method가 어째서 deprecated되었을까?

 

Finalize의 단점

Finalize를 override한 객체는 GC(garbage collector)에서 특별하게 처리된다. 

 

할당이 해제된 후 바로 GC에 수집되지 않는다. 해당 객체는 queue에 등록된 후 별도의 종료 thread가 queue에서 pop을 시켜 순차적으로 종료 시킨다. 때문에 finalize가 요청된 시점과는 다른 주기에 소멸 작업이 진행된다.

 

위 과정에서 발생하는 thread의 생성과 실행은 오버헤드를 발생시킨다. 

JVM는 작업의 안전성 보장을 위해 finalize 처리용 thread를 생성하는데, 해당 thread가 finalize 작업을 진행하는 과정 중에 오류가 발생하거나 blocking이 발생 할 수 있다. 

 

resource의 회수 및 객체 소멸에 대한 처리를 하는데 위와 같은 오버헤드의 위험도를 매번 감수할 수는 없다.

때문에 공식적으로도 finalize를 사용하지 않는 방향으로 개발할 것을 추천해왔고, Java 9버전에 와서 deprecated 처리가 된 것이다. 

 

필요하다면?

resource의 회수와 소멸 기능의 구현이 필요할 때 추천되는 구현 방식은 try-catch-finally를 사용한 logic block을 통한 처리 방식이다. 

 

+ Recent posts