반응형
반응형
// base64로 인코딩한 내용 받아오기
@RequestMapping(value = "/getBase64", method = RequestMethod.GET)
public @ResponseBody String getBase64(HttpServletRequest request, HttpServletResponse response) throws Exception {

    Base6430 base = new Base6430();
    String encodeBase64 = base.encodingBase64();

    return encodeBase64;

}

// 이미지 base64 인식
//	@RequestMapping(value = "/base64", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE)
// mp4 base64 인식
//	@RequestMapping(value = "/base64", method = RequestMethod.GET, produces = "video/mp4")
// pdf base64 인식
//	@RequestMapping(value = "/base64", method = RequestMethod.GET, produces = "application/pdf")
// base64 디코딩해 해석해 화면에 노출
@RequestMapping(value = "/base64", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE)
public @ResponseBody byte[] base64(HttpServletRequest request, HttpServletResponse response) throws Exception {

    String uri = "http://localhost:8080/getBase64";
    String encodeBase64 = callGetMethod(uri);

    byte decode[] = Base64.decodeBase64(encodeBase64);

    return decode;
}

StringBuffer response;
public String callGetMethod(String url) {		
    try {

        // 통신 주소  등록
        URL obj = new URL(url);

        // 통신 방식 설정
        HttpURLConnection conn = (HttpURLConnection) obj.openConnection();
        conn.setRequestProperty("Content-Type", "application/json; charset=utf-8" );
        conn.setDoOutput(true);
        conn.setRequestMethod("GET");

        // ---- 읽어온 데이터를 담기 ----
        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(),"UTF-8"));

        String inputLine;
        response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();

    } catch (Exception e) {
        e.printStackTrace();
    }

    // ---- 읽어온 데이터를 반환 ----
    String responseData =response.toString();
    return responseData; 
}

base64Controller

 

spring에서 제공하는 produces에 다양한 옵션이 존재하는데 ContentType 인식 시키는 방법에 대한 기술

(produces = MediaType.IMAGE_JPEG_VALUE → 이미지로 읽어라~)

 

package com.mycompany.myapp;

import java.io.File;
import java.io.FileInputStream;

import org.apache.commons.codec.binary.Base64;

public class Base6430 {

	public String encodingBase64() throws Exception {

		String strBase64 = "";
		String filePath = "D:\\dog.jpg";
//		String filePath = "D:\\test.mp4";
//		String filePath = "D:\\test.pdf";

		File f = new File(filePath);
		if (f.exists() && f.isFile() && f.length() > 0) {
			byte[] bt = new byte[(int) f.length()];
			FileInputStream fis = null;

			try {
				fis = new FileInputStream(f);
				fis.read(bt);
				strBase64 = new String(Base64.encodeBase64(bt));

			} catch (Exception e) {
				throw e;
			}
			fis.close();
			
		}
		return strBase64;
	}
}

base6430.java

 

해당 Path 정보를 읽어 Base64 인코딩하는 작업

 

<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.9</version>
</dependency>

pom.xml

반응형
반응형

📝List 정렬

public void sort(){

    /** 초기 데이터 init **/
    List<String> list = Arrays.asList("banana", "apple", "cherry");

    /** 오름차순 정렬 **/
    list.sort(Comparator.naturalOrder());
    System.out.println("오름차순: " + list);
    // 오름차순: [apple, banana, cherry]

    /** 내림차순 정렬 **/
    list.sort(Comparator.reverseOrder());
    System.out.println("내림차순: " + list);
    // 내림차순: [cherry, banana, apple]

}

 

📝Map정렬

  public void sort() {

    /** 초기 데이터 init **/
    Map<String, Integer> map = new HashMap<>();
    map.put("apple", 3);
    map.put("banana", 1);
    map.put("cherry", 2);

    /** Map.Entry 리스트로 변환 **/
    List<Map.Entry<String, Integer>> entryList = new ArrayList<>(map.entrySet());

    /** 키(key) 기준으로 오름차순 정렬 **/
    entryList.sort(Map.Entry.comparingByKey());
    System.out.println("키 기준 오름차순: " + entryList);
    // 키 기준 오름차순: [apple=3, banana=1, cherry=2]

    /** 키(key) 기준으로 내림차순 정렬 **/
    entryList.sort(Map.Entry.<String, Integer>comparingByKey().reversed());
    System.out.println("키 기준 내림차순: " + entryList);
    // 키 기준 내림차순: [cherry=2, banana=1, apple=3]

    /** 값(value) 기준으로 오름차순 정렬 **/
    entryList.sort(Map.Entry.comparingByValue());
    System.out.println("값 기준 오름차순: " + entryList);
    // 값 기준 오름차순: [banana=1, cherry=2, apple=3]

    /** 값(value) 기준으로 내림차순 정렬 **/
    entryList.sort(Map.Entry.<String, Integer>comparingByValue().reversed());
    System.out.println("값 기준 내림차순: " + entryList);
    // 값 기준 내림차순: [apple=3, cherry=2, banana=1]

  }

Map은 직접 정렬할 수 없어서 Map.Entry로 변환한 후에 List로 담아서 사용이 가능합니다.

 

📝 JSONArray 정렬

public void sort() throws JSONException {

    /** 초기 데이터 init **/
    String jsonData = "["
        + "{\"name\":\"banana\",\"price\":1},"
        + "{\"name\":\"apple\",\"price\":3},"
        + "{\"name\":\"cherry\",\"price\":2}"
        + "]";

    JSONArray jsonArray = new JSONArray(jsonData);

    /** JSONArray -> List<JSONObject> **/
    List<JSONObject> jsonList = new ArrayList<>();
    for (int i = 0; i < jsonArray.length(); i++) {
      jsonList.add(jsonArray.getJSONObject(i));
    }

    /** 오름차순 정렬 **/
    jsonList.sort(Comparator.comparing(obj -> {
      try {
        return obj.getInt("price");
      } catch (JSONException e) {
        throw new RuntimeException(e);
      }
    }));

    /** 정렬된 List -> JSONArray로 변환 **/
    JSONArray sortedJsonArray = new JSONArray(jsonList);

    System.out.println("오름차순 정렬 JSONArray: " + sortedJsonArray);
    // 오름차순 정렬 JSONArray: [{"price":1,"name":"banana"},{"price":2,"name":"cherry"},{"price":3,"name":"apple"}]

    /** 내림차순 정렬 **/
    jsonList.sort(Comparator.comparing((JSONObject obj) -> {
      try {
        return obj.getInt("price");
      } catch (JSONException e) {
        throw new RuntimeException(e);
      }
    }).reversed());

    /** 정렬된 List -> JSONArray로 변환 **/
    JSONArray descSortedJsonArray = new JSONArray(jsonList);

    System.out.println("내림차순 정렬 JSONArray: " + descSortedJsonArray);
    // 내림차순 정렬 JSONArray: [{"price":3,"name":"apple"},{"price":2,"name":"cherry"},{"price":1,"name":"banana"}]
}

JSONArray도 바로 정렬할 수 없기 때문에 List에 담아서 처리해야합니다. 정렬할 때 정렬할 키를 기준으로 return해서 그 값을 정렬처리하게끔하면 됩니다.

반응형
반응형

Arrays

  Array는 길이 고정 Array 객체를 생성한 후에는 Array의 길이를 마음대로 변경할 수 없다.

 

ArrayList

  ArrayList는 사이즈는 동적 만약 설정한 범위를 넘어 더 많은 크기가 들어오면 배열 크기를 1.5배 증가시킨다.

 

 

Arrays와 ArrayList는 요소를 추가하거나 가져올 때의 성능과 처리시간은 동일하지만 ArrayList의 경우 범위를 넘으면 1.5배 증가시키면서 시간 Resoucre와 Memory 를 더 차지하게 된다.

반응형
반응형
// 우측 마우스 클릭시 이벤트 리스너
document.addEventListener('contextmenu', handleCreateContextMenu);

// 나만의 context menu 생성
function handleCreateContextMenu(event) {
	// 기본 Context Menu가 나오지 않게 차단
	event.preventDefault();

	// 나만의 context menu
	const ctxMenu = document.getElementById('context_menu');
	
	// 노출 설정
	ctxMenu.style.display = 'block';

	// 위치 설정
	ctxMenu.style.top = event.pageY + 'px';
	ctxMenu.style.left = event.pageX + 'px';

	// 각주만들기 누를시에 블록지정이 풀려서 카피 내용이 사라지기 때문에 우측을 눌렀을 때 카피되는 과정이 필요하다
	document.execCommand('copy');

	// 클립보드 내용 가져오는 것은 비동기로 처리되기 때문에 
	// 비동기 함수로 처리해서 값이 다 나왔을 때 필요한 값을 받는 과정이 필요하다
	getClipboardContents();

}


// 클립보드 내용을 가져오려면 비동기 처리가 필요하다.
async function getClipboardContents() {
	try {
		footnoteContent = await navigator.clipboard.readText();
		console.log('Pasted content: ', text);
	} catch (err) {
		console.error('Failed to read clipboard contents: ', err);
	}
}


// 좌측 마우스 클릭시 이벤트 리스너
document.addEventListener('click', handleClearContextMenu);


// Context Menu 제거
function handleClearContextMenu(event) {
	const ctxMenu = document.getElementById('context_menu');

	// 노출 초기화
	ctxMenu.style.display = 'none';
	ctxMenu.style.top = null;
	ctxMenu.style.left = null;
}
// 드래그 했을 때 이벤트 리스너
document.addEventListener("drag", function(event) {
	console.log("이동 중");
}, false);




// 블럭지정 했을 때 이벤트 리스너
document.addEventListener('selectionchange', () => {
	console.log(document.getSelection().toString());
});
반응형
반응형
<!-- 내부 JS 지정 -->
<script>

	/*
	[JS 요약 설명]
	1. window.onload : 브라우저 로드 완료 상태를 나타냅니다 
	2. spin js : 브라우저 내에서 로딩 스핀 상태를 나타낼 수 있습니다 
	3. 로직 : 사용자 통신 요청 시 >> spinnerStart 호출 >> 리턴 응답 받을 시 >> spinnerStop 호출    	
	4. 옵션 참고 공식 사이트 : https://spin.js.org/
	*/


	
	/* [html 최초 로드 및 이벤트 상시 대기 실시] */
	window.onload = function() {
		console.log("");
		console.log("[window onload] : [start]");
		console.log("");

		// 로딩 스피너 호출
		spinnerStart();

		/* setTimeout 호출 : 일정 시간 후 실행 : [함수호출] 일회용 */
		setTimeout(spinnerStop, 3000); //5초후에 spinnerStop() 함수 호출
	};



	/* [spinnerStart 시작 이벤트 호출] */
	function spinnerStart(){
		
		console.log(""); 
		console.log("[spinnerStart] : " + "[start]");           
		console.log("");

		// [로딩 부모 컨테이너 동적 생성] 회색화면
		var createLayDiv = document.createElement("div");
		
		// 설정
		createLayDiv.setAttribute("id", "spinnerLay1000");
		var createLayDivStyle = "width:100%; height:100%; margin:0 auto; padding:0; border:none;";
		createLayDivStyle = createLayDivStyle + " float:top; position:fixed; top:0%; z-index:1000;";
		createLayDivStyle = createLayDivStyle + " background-color:rgba(0, 0, 0, 0.3);"; // 불투명도 설정 >> 자식에게 적용 안됨
		createLayDiv.setAttribute("style", createLayDivStyle);
		
		document.body.appendChild(createLayDiv); //body에 추가 실시


		// [실제 스핀 수행 컨테이너 동적 생성] 스피너
		var createSpinDiv = document.createElement("div");
		
		//설정
		createSpinDiv.setAttribute("id", "spinnerContainer1000");
		var createSpinDivStyle = "width:100px; height:100px; margin:0 auto; padding:0; border:none;"; // 스핀 컨테이너 크기 조절
		createSpinDivStyle = createSpinDivStyle + " float:top; position:relative; top:40%;";
		//createSpinDivStyle = createSpinDivStyle + " background-color:#ff0000;";  
		createSpinDiv.setAttribute("style", createSpinDivStyle);
		
		document.getElementById("spinnerLay1000").appendChild(createSpinDiv); //spinnerLay에 추가 실시


		// [스핀 옵션 지정 실시]
		var opts = {
			lines: 10, // 그릴 선의 수 [20=원형 / 10=막대] [The number of lines to draw]
			length: 10, // 각 줄의 길이 [0=원형 / 10=막대] [The length of each line]
			width: 15, // 선 두께 [The line thickness]
			radius: 42, // 내부 원의 반지름 [The radius of the inner circle]
			scale: 0.85, // 스피너의 전체 크기 지정 [Scales overall size of the spinner]
			corners: 1, // 모서리 라운드 [Corner roundness (0..1)]
			color: '#003399', // 로딩 CSS 색상 [CSS color or array of colors]
			fadeColor: 'transparent', // 로딩 CSS 색상 [CSS color or array of colors]
			opacity: 0.05, // 선 불투명도 [Opacity of the lines]
			rotate: 0, // 회전 오프셋 각도 [The rotation offset]
			direction: 1, // 회전 방향 시계 방향, 반시계 방향 [1: clockwise, -1: counterclockwise]
			speed: 1, // 회전 속도 [Rounds per second]
			trail: 74, // 꼬리 잔광 비율 [Afterglow percentage]
			fps: 20, // 초당 프레임 수 [Frames per second when using setTimeout() as a fallback in IE 9]
			zIndex: 2e9 // 인덱스 설정 [The z-index (defaults to 2000000000)]
		};


		// [스피너 매핑 및 실행 시작]
		var target = document.getElementById("spinnerContainer1000");
		var spinner = new Spinner(opts).spin(target);
	};


	/* [spinnerStop 중지 이벤트 호출] */
	function spinnerStop(){
		console.log("");
		console.log("[spinnerStop] : " + "[start]");
		console.log("");
		try {
			// [로딩 부모 컨테이너 삭제 실시]
			var tagId = document.getElementById("spinnerLay1000");
			document.body.removeChild(tagId); //body에서 삭제 실시 
		}
		catch (exception) {
			// console.error("catch : " + "not find spinnerLay1000");
		}

	};
	
</script>

출저 : https://kkh0977.tistory.com/m/1031

반응형
반응형
package my.spring.project;

public class main {

	public static void main(String[] args) {

        String s = "1000";                     
        
        int i = Integer.parseInt(s); // int 타입 변환
        long L = Long.parseLong(s);  // long 타입 변환
        float f = Float.parseFloat(s); // float 타입 변환
        double d = Double.parseDouble(s) + 1.0; // double 타입 변환
	}

}
반응형
반응형

📝커넥션 풀 (DBCP)

  • 웹 컨테이너(WAS)가 실행되면서 DB와 미리 Connection (연결)을 해놓은 객체들을 pool에 저장해두었다가 클라이언트 요청이 오면 Connection을 빌려주고 처리가 끝나면 다시 Connection 을 반납받아 pool에 저장하는 방식을 말합니다
  • 동시 접속 할 경우 pool에서 미리 생성 된 Connection을 제공하고 없을 경우는 사용자는 Connection이 반환될 때까지 번호순대로 대기상태로 기다린다
  • WAS에서 션 풀을 크게 설정하면 메모리 소모가 큰 대신 많은 사용자가 대기시간이 줄어들고 반대로 커넥션 풀을 적게 설정하면 그 만큼 대기시간이 길어진다
  • 커넥션 풀은 서버당 최대 커넥션 수를 제한하여 따라서 DB에 무한정 연결이 생성되는 것을 막아주어 서 DB를 보호하는 효과도 있다
  • 대표적인 커넥션 풀 오픈소스는 commons-dbcp2 , tomcat-jdbc pool , HikariCP이고 최근에는 hikariCP 를 주로 사용한다 → 스프링 부트 2.0 부터는 기본 커넥 션 풀로 hikariCP 를 제공

 

📝디스크 풀

디스크가 꽉 찼음

 

📝데이터 풀

데이터베이스에서 얻은 데이터들의 집합

 

📝스레드 풀

스레드 제어 문제를 해결할 방법으로 스레드 풀을 사용한다.

스레드 풀은 매번 생성 및 수거 요청이 올 때 스레드를 생성하고 수거하는 것이 아닌 스레드 사용자가 설정해둔 개수만큼 미리 생성해두는 것이다 → 반환될 때까지 번호순대로 대기상태  작업이 끝난 스레드가 60초 이상 새로운 작업요청이 없으면 스레드를 종료하고 스레드 풀에서 제거

 

📝참조 데이터

해당 데이터를 여러 곳에 쓰이는 경우 주소를 참조하게끔 하면 계속 해당 데이터를 만드는 것보다 메모리 할당을 줄일 수 있다

 

 

🔗 참고 및 출처

https://d2.naver.com/helloworld/5102792

반응형
반응형

📝코딩 컨벤션

읽고, 관리하기 쉬운 코드를 작성하기 위한 일종의 코딩 스타일 규약이다

예) boolean 타입인 경우 is, has 접미어를 붙인 변수로 선언한다, 카멜 케이스를 따른다 등...

 

📝UUID

UUID는 128비트의 숫자이며, 32자리의 16진수로 표현된다. 

 

📝R&D

Research and Development의 약자로, 우리말로 "연구 개발"

 

📝sandbox 

외부로부터 받은 파일을 바로 실행하지 않고 보호된 영역에서 실행시켜 봄으로써 외부로부터 들어오는 파일과 프로그램이 내부 시스템에 악영향을 주는 것을 방지하는 기술

 

📝DB 인덱스 

DB 인덱스(Index)는 데이터베이스에서 검색 속도를 향상시키기 위해 사용되는 데이터 구조이다

인덱스 생성 방법으론 다양한 게 있지만 기본적으로 INSERT, UPDATE, DELETE가 자주 발생하지 않는 컬럼을 사용해야하고(인덱스를 생성할 때 성능 이슈가 발생) JOIN이나 WHERE 또는 ORDER BY에 자주 사용되는 컬럼에 효과적이다. 

인덱스를 사용하는 것 만큼이나 생성된 인덱스를 관리해주는 것도 중요하다. 그러므로 사용되지 않는 인덱스는 바로 제거를 해주는게 좋다

 

📝함수(function)

특정 계산을 수행하며 쿼리 내에서 계산된 값을 반환한다

계산하고 반환하는데 중점을 두기 때문에 주로 SELECT문에서 많이 사용한다

SELECT get_keywords();

 

📝프로시저(procedure)

특정 작업을 수행하며 리턴값이 없을 수 있다

프로시저는 주로 데이터 조작 작업(INSERT, UPDATE, DELETE)이나 특정 비즈니스 로직을 수행하는 데 사용하며 단독으로 실행이 가능하다

함수처럼 매개변수를 받을 수 있고 특정 작업들을 수행하지만 뭔가를 반환하는 것보다는 일련의 함수 동작을 수행한다

→ 물건 구매했을 때 구매목록 테이블에 데이터 INSERT되고 배송 테이블에 데이터 INSERT되고 등... 여러 행위를 하나로 묶은 프리시저를 만들어서 활용할 수 있다

CALL UpdateEmployeeSalary(1, 50000);

 

 

 

반응형
반응형
1. (JQuery) 
$(function(){ // 웹브라우저 내의 모든 요소가 준비가 되어야 실행
  // 실행할 기능을 정의해주세요.
});


2. (JQuery)
$.fn.메소드명 = function (인자명) {
//내용
}

3.
자바스크립트 (Javascript)
function 메소드명 (인자값...){

}

4. (1과 4는 등치) (JQuery)
$(document).ready(function(){ // 웹브라우저 내의 모든 요소가 준비가 되어야 실행
	....
});

// 웹브라우저 내의 모든 요소가 준비가 되어야 실행 (Javascript)
5. window.onload = function(){ 
   ....
}
반응형