안드로이드 aar 트러블슈팅 기록

안드로이드 aar 트러블슈팅 기록

너무 많은 시간을 허비했다.

오랜 삽질 끝에 해결은 했는데 도대체 뭐가 문제였는지도 잘 모르겠다.

일단 기록해놓지 않으면 나중에 기억나지 않을 것이기에 기록한다.

1. 1차 시도

일단 기존 쓰고 있는 앱 소스코드를 기반으로, 새로운 2개의 앱을 만들어내는게 핵심과제였다.

그런데 새로운 앱 2개에서는 만들어내자 기존에 잘 돌던 코드가 동작하지 않았다.

앱 위변조검증이라는 기능이었는데, 타 업체의 라이브러리에 의존하는 코드였다.

타업체가 만든 라이브러리는 2.1.7.jar 라는 파일을 쓰고 있었다.

알고보니 이 라이브러리는 안드로이드 앱의 패키지명이 변경되면 동작하지 않는 방식이었다.

정확히 표현하면 build.gradle 의 applicationId 값이 바뀌면 라이선스 어쩌구 하는 못보던 오류 메시지가 발생했다.

정식 라이선스 값이라는 String 변수가 있고, 해당 변수가 패키지명과 매칭되지 않으면 동작하지 못하도록 제어하는 것 같았다.

이것을 알아내는 데에도 엄청난 시간이 걸렸다(잘 동작하는 AS-IS 프로젝트를 갖다 놓고, TO-BE와 같아지도록 한 줄씩 수정하면서 언제 라이선스 어쩌구 오류 메시지가 발생하는지 테스트했다).

아무튼 패키지명에 알맞게 2개의 정식 라이선스 값을 받아내면 된다고 생각했는데, 새로운 버전의 라이브러리로 교체하라는 답변을 업체로부터 받았다.

새로운 버전의 라이브러리는 라이선스 값과 무관하게 잘 동작한다고 했다.

2. 2차 시도

새로운 버전의 라이브러리는 jar 파일이 아니고 aar 파일이었다.

검색을 동원해본 결과 aar 파일을 프로젝트에 적용하는 방법은 2가지가 있다.

첫번째는 libs 폴더에 aar 파일을 넣고, build.gradle 파일을 수정하는 것이다. 이것에 대해서는 https://blog.naver.com/bb_/221758376358 포스트에 정리해둔 바 있다.

결과적으로 이 방법으로 성공했다.

두번째 방법은 aar을 사용하고 있는 모듈을 추가하는 것이다.

예제로 받은 샘플 프로젝트가 이 방식을 사용하고 있어서 계속 시도해본 방법이다.

결과적으로 이 방법은 실패했지만 방법만 적어둔다.

(1) File – New – Import Module – 모듈 폴더를 선택.

개인적으로는 받은 샘플 프로젝트 안에 aar을 사용하는 모듈이 들어있어서, 해당 폴더를 그대로 복사해왔다. 폴더명은 library_name_v4.0.0 이었다.

(2) build.gradle 파일에 implementation project(path: ‘:library_name_v4.0.0’) 추가

(3) settings.gradle 파일에 include ‘:library_name_v4.0.0’ 추가

처음에는 두번째 방법(aar을 사용하고 있는 모듈을 추가)을 시도했는데, 계속 실패했다.

계속 실패했다는 것은 뭔가 잘못된 것 같으면 전체 롤백하고 처음부터 다시 하기를 반복했다는 뜻이다.

기존에 쓰던 2.1.7.jar 파일을 삭제하고, library_name_v4.0.0 모듈을 추가하고, 빨간줄이 발생한(오류가 발생한) 코드를 고치는 작업이었는데 고칠게 너무 많았다.

기존에 com.업체명~ 으로 시작했던 것들이 모두 net.업체명~ 식으로 패키지명이 바뀌었다.

또 사용하던 메서드들이 없어진 것들이 많아서 코드를 마구 삭제하다가, 너무 많이 건드린 것 같으면 롤백하기를 반복하였다.

결국 작업은 완료되었는데, 이제 앱이 죽는 현상이 생겼다.

한참 원인을 찾지 못하다가 로그캣을 보게 됐다.

——— beginning of crash 라고 해서 익셉션이 나와있었고, FATAL EXCEPTION 이 발생한 것이었다.

핵심이 되는 오류는 java.lang.VerifyError 였다.

Caused by: java.lang.VerifyError: Verifier rejected class com.타업체패키지명.타업체클래스명: void     com.타업체패키지명.타업체클래스명<init>(boolean) failed to verify: void     com.타업체패키지명.타업체클래스명<init>(boolean): [0x31] Expected initialization on uninitialized reference Precise Reference: java.lang.String (declaration of ‘com.타업체패키지명.타업체클래스명’ appears in /data/app/com.자사패키지명-1/split_lib_slice_9_apk.apk)

막막해서 지인들에게 도움을 요청해보니 검색하여 아래 답변을 주었다.

생각해보면 나도 검색해서 얻을 수 있는 정보였는데 찾지 못한 이유는, 하필 라이브러리에서 오류가 나는 해당 메서드 명이 verify여서 이게 자바 레벨의 오류가 아니라 특정 업체 라이브러리에서만 발생하는 특수한 오류라고 생각했다. 나는 VerifyError 라는 키워드만 빼고 나머지 키워드들로 검색을 하고 있었다…

VerifyError 발생 원인

1. 컴파일 시 사용한 라이브러리와 런타임 시 사용한 라이브러리 버전이 달라서 메서드 형태가 다른 경우

2. 사용한 라이브러리가 상위 버전의 JDK 에서 컴파일 된 경우

결국 라이브러리 버전을 맞춰야 한다.

저기 분명 라이브러리 버전을 맞춰야 한다고 했는데, 나는 어쩐 일인지 JDK버전 내지는 안드로이드 SDK 버전을 맞춰야 한다는 생각이 들었다.

뭐가 뭔지 모르겠는 상태에서 library_name_v4.0.0.aar 을 반디집으로 열어서 AndroidManifest.xml 을 열어보니 안드로이드 버전 29로 되어있었다.

내 프로젝트는 안드로이드 버전 28 이었는데, 어쩐 일인지 build.gradle을 29로 고치면 앱이 동작하지 않았다.

검색을 거듭한 결과 안드로이드 스튜디오 버전 4.0 이상에서 안드로이드 버전 29를 쓸 수 있다는 내용을 보았다.

내가 사용한 안드로이드 스튜디오는 버전 3.4 였다.

확실한지는 모르지만 지푸라기라도 잡는 심정으로 안드로이드 스튜디오 4.0을 깔고, 작업중인 프로젝트를 로드했다.

결과적으로 안드로이드 스튜디오 4.0 에서는 VerifyError 가 발생하지 않았다.

버전을 29로 올리지도 않았다.

그냥 내 프로젝트는 여전히 버전 28이고, aar 은 버전 29였다.

돌이켜보면 샘플 프로젝트도 3점대 안드로이드 스튜디오에서는 빨간줄이 그어져 빌드가 안됐고, 안드로이드 스튜디오 4.0 에서는 잘 열리고 빌드가 됐다.

뇌피셜이지만 해결된 이유는 aar 모듈이 안드로이드 스튜디오 4에서 만들어진 모듈이라서, 그걸 사용하는 프로젝트 역시 안드로이드 스튜디오 4에서 빌드해야 되는 것 같다.

문제는 이렇게 오류는 해결이 됐는데 앱위변조 검증이 통과가 됐다.

통과가 안되어야 정상인데 통과가 됐다.

이게 말이 안되는게 서버쪽에 앱의 고유 해시값이 있을건데 내가 이것저것 고쳤기 때문에, 서버에 올라가 있는 앱의 해시값과 내 앱의 해시값은 전혀 다를 것이란 말이다.

나중에 언급하겠지만 이 때는 verify 를 SimpleVerify 로 고쳐도 똑같이 위변조 검증이 통과됐다.

아무튼 오류는 발생하지 않으나 라이브러리가 똑바로 동작하지 않으니 모두 롤백했다.

=> 나중에 알게된 사실인데 이때 이미 성공을 한 것이었다.

앱위변조 검증은 서버에 따로 앱을 업로드해서 해시값을 만드는게 아니라, 첫번째로 앱위변조 요청(verify 메서드)을 했을 경우 해시값을 서버에 저장하고 그 값을 기준으로 검증하는 것이었다.

3. 3차 시도

2차 시도는 어제인 토요일 얘기고, 일요일인 오늘은 3차 시도였다.

처음부터 안드로이드 스튜디오 4.0 에서 프로젝트를 열어서 빌드를 하고 시작했다.

업체로부터 받은 aar 버전이 2가지가 있었는데, 하나가 어제 시도한 library_name_v4.0.0.aar 이었다.

사실 이것은 또 다른 업체로부터 받았으니 간접적으로 받은 파일에 해당한다.

다른 하나가 library_name_v4.0.4.aar 이었다.

이건 직접적으로 전달받은 거였다.

기존 버전의 버전 갭이 클수록 고쳐야할게 많다는 생각에 4.0.0을 먼저 시도한 것인데, 어제 잘 동작하지 않았으니 또 다시 지푸라기라도 잡는 심정으로 4.0.4 로 시작했다.

aar 을 추가할 때 모듈을 추가하는 방식을 사용하지 않고, 그냥 libs 폴더 안에 aar 파일을 넣는 방식을 사용했다.

그리고 기존 라이브러리(jar)를 지우고 진행을 하는데 아래 오류가 발생했다.

execution failed for task ‘:app:transformdexarchivewithexternallibsdexmergerfordebug’.

뭔가를 잘못했나 싶어서 롤백을 하고 다시 진행해도 똑같은 오류가 발생했다.

검색 결과 가장 도움이 된 포스트는 이것이다. https://miraclehwan.tistory.com/22

사용하는 라이브러리마다 참조하는 라이브러리 버전이 다 다를 경우, 메소드의 수가 계속 증가하여 64k개 이상을 가질 경우 위와 같은 에러가 발생한다.

(중략)

확실한 해결 방법은 버전이 다른 라이브러리를 사용할 경우 하나로 고정시키는 방법이다.

 

내가 이해한 바는, 결국 라이브러리 충돌이 난다는 얘기인 것이다.
분명히 기존 라이브러리를 지웠는데 말이다.

로그캣이었는지 디버그 콘솔이었는지 읽을 수 있는 것은 뭐든 꼼꼼히 읽어보니 못보던 패키지명이 있었다.

패키지명을 쫓아가보니 내가 모르는 jar에 속했다.

다시 말해 어떤 jar을 하나 더 의존하는 것처럼 보였다. 그 어떤 jar를 INI_4.1.2.jar 라고 하자.

아래 테스트를 통해 더 확실히 알 수 있었다.

기존 앱에서 2.1.7.jar 파일은 그대로 두고, INI_4.1.2.jar 를 삭제했다.

앱에 아무런 빨간줄도 나오지 않았지만, 실행해보면 앱은 오류가 발생됐다.

앱은 2.1.7.jar 만 의존하고 있지만, 2.1.7.jar 가 INI_4.1.2.jar 를 의존하고 있는 것이다(라고 추정했다).

그래서 프로젝트를 다시 전부 롤백하고 다시 시작했다.

(1) 안드로이드 스튜디오 4.0 으로 프로젝트를 열고, 빌드해서 실행했다.

(2) 기존 libs 폴더에서 2.1.7.jar 와 INI_4.1.2.jar 를 삭제했다.

(3) libs 폴더에 library_name_v4.0.4.aar 파일을 추가하고 build.gradle 파일을 알맞게 수정했다.

(4) 관련 코드를 수정했다.

이유는 모르겠지만 4.0.0 aar 모듈을 사용했을 때는 com.업체명~ 패키지를 전부 net.업체명~ 패키지명으로 바꿔야 했고 메서드도 많이 사라져있어서 난감했는데,

4.0.4.aar 을 libs에 추가해서 사용해보니 com.업체명~ 패키지가 전부 그대로였고 메서드도 거의 일치하는 모습을 보였다.

이게 모듈 사용 여부의 차이인지 버전의 차이(4.0.0, 4.0.4)인지는 불분명하다.

심증으로는 모듈을 사용한다고 패키지명이 바뀔리가 없다고 생각하는데

버전의 차이는 더 말이 안된다.

2.1.7 은 com 패키지를 쓰고, 4.0.0 은 net 패키지를 쓰고, 4.0.4 는 com  패키지를 쓴다는 말이기 때문이다.

아무튼 작업을 끝내고 실행해보니 이번에도 2차 시도 때처럼 앱 위변조검증에 통과하는 문제가 있었다.

또 롤백을 해야하나 고민하다가 API 문서를 읽어봤다.

4.0.0 과 4.0.4 API문서가 조금 달랐다.

4.0.0 은 verify 메서드를 쓰라고 했고, 4.0.4는 SimpleVerify 메서드를 쓰라고 했다.

2.1.7을 쓰던 기존 앱은 verify 메서드를 쓰고 있었다.

이걸 SimpleVerify 메서드로 고치니까 드디어 앱위변조 검증 결과 실패가 떴다.

(=> 나중에 알게된 사실인데 verify 를 써야한다. 그리고 앱위변조 검증은 서버에 따로 앱을 업로드해서 해시값을 만드는게 아니라, 첫번째로 앱위변조 요청(verify 메서드)을 했을 경우 해시값을 서버에 저장하고 그 값을 기준으로 검증하는 것이었다.)

이제 평일이 되면 서버에 앱 해시값을 등록해서 통과를 시킬 차례다…

이게 되어야 진짜 성공이고 아니면 또 롤백행일지도…

[Android] Could not connect to remote process. Aborting debug session.

[Android] Could not connect to remote process. Aborting debug session.

안드로이드 스튜디오에서 Run 또는 디버그를 수행했을 때 앱이 실행되지 않으면서 Debug 콘솔에 “Could not connect to remote process. Aborting debug session.” 메시지가 출력되는 문제.

안드로이드 스튜디오 우측상단 재생 버튼 왼쪽의 [app] 콤보박스를 클릭하고 [Edit Configurations…] 클릭 – Launch Options 의 Launch 콤보박스 값을 Nothing 에서 Default Activity 로 변경하여 다시 디버그 해본다.

참고사이트 : https://stackoverflow.com/questions/53962831/how-do-i-fix-could-not-connect-to-remote-process-while-trying-to-debug-the-app

[SpringBoot] 스프링부트 웹소켓(WebSocket) 예제

[SpringBoot] 스프링부트 웹소켓(WebSocket) 예제

1. 스프링부트 웹 프로젝트 생성

우선 스프링부트 웹 프로젝트가 있어야 한다.

새로 시작하려면 아래 포스트를 참고하면 된다.

https://blog.naver.com/bb_/222141978468

2. pom.xml 수정
아래 코드를 추가한다.

<!– websocket –>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

 

3. Websocket.java 파일 작성

원하는 패키지에 아래 파일을 작성한다.

package 원하는_패키지명;

import java.util.ArrayList;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Component;

@Component
@ServerEndpoint(“/websocket”)
public class Websocket {

    /**
     * 웹소켓 세션을 담는 ArrayList
     */

    private static ArrayList<Session> sessionList = new ArrayList<Session>();

    
    /**
     * 웹소켓 사용자 연결 성립하는 경우 호출
     */

    @OnOpen
    public void handleOpen(Session session) {
        if (session != null) {
            String sessionId = session.getId();
            
            System.out.println(“client is connected. sessionId == [“ + sessionId + “]”);
            sessionList.add(session);
            
            // 웹소켓 연결 성립되어 있는 모든 사용자에게 메시지 전송
            sendMessageToAll(“***** [USER-“ + sessionId + “] is connected. *****”);
        }
    }
    

    /**
     * 웹소켓 메시지(From Client) 수신하는 경우 호출
     */

    @OnMessage
    public String handleMessage(String message, Session session) {
        if (session != null) {
            String sessionId = session.getId();
            System.out.println(“message is arrived. sessionId == [“ + sessionId + “] / message == [“ + message + “]”);

            // 웹소켓 연결 성립되어 있는 모든 사용자에게 메시지 전송
            sendMessageToAll(“[USER-“ + sessionId + “] “ + message);
        }

        return null;
    }
    

    /**
     * 웹소켓 사용자 연결 해제하는 경우 호출
     */

    @OnClose
    public void handleClose(Session session) {
        if (session != null) {
            String sessionId = session.getId();
            System.out.println(“client is disconnected. sessionId == [“ + sessionId + “]”);
            
            // 웹소켓 연결 성립되어 있는 모든 사용자에게 메시지 전송
            sendMessageToAll(“***** [USER-“ + sessionId + “] is disconnected. *****”);
        }
    }

    
    /**
     * 웹소켓 에러 발생하는 경우 호출
     */

    @OnError
    public void handleError(Throwable t) {
        t.printStackTrace();
    }
    
    
    /**
     * 웹소켓 연결 성립되어 있는 모든 사용자에게 메시지 전송
     */

    private boolean sendMessageToAll(String message) {
        if (sessionList == null) {
            return false;
        }

        int sessionCount = sessionList.size();
        if (sessionCount < 1) {
            return false;
        }

        Session singleSession = null;

        for (int i = 0; i < sessionCount; i++) {
            singleSession = sessionList.get(i);
            if (singleSession == null) {
                continue;
            }

            if (!singleSession.isOpen()) {
                continue;
            }

            sessionList.get(i).getAsyncRemote().sendText(message);
        }

        return true;
    }
}

 

4. OOOApplication.java 파일 수정

@SpringBootApplication 가 붙어있는 자바 파일을 수정하면 된다. serverEndpointExporter 메서드를 만들고 @Bean 어노테이션을 붙여준다.

package 원하는_패키지명;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@SpringBootApplication
public class ProjectNameApplication {

    public static void main(String[] args) {
        SpringApplication.run(WebGameBaseApplication.class, args);
    }
    
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

}

 

5. chat.jsp 파일 작성
아래 파일을 적당한 위치에 작성한다.
여기서는 프로젝트/src/main/webapp/WEB-INF/views/chat.jsp 경로에 위치한다고 가정한다.

<%@ page contentType=“text/html; charset=utf-8” %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv=“Content-Type” content=“text/html; charset=UTF-8”>
<title>웹소켓 테스트 페이지</title>
<script type=“text/javascript”>
var g_webSocket = null;
window.onload = function() {
    g_webSocket = new WebSocket(“ws://localhost:8080/websocket”);
    
    
    /**
     * 웹소켓 사용자 연결 성립하는 경우 호출
     */

    g_webSocket.onopen = function(message) {
        addLineToChatBox(“Server is connected.”);
    };
    
    
    /**
     * 웹소켓 메시지(From Server) 수신하는 경우 호출
     */

    g_webSocket.onmessage = function(message) {
        addLineToChatBox(message.data);
    };

    /**
     * 웹소켓 사용자 연결 해제하는 경우 호출
     */

    g_webSocket.onclose = function(message) {
        addLineToChatBox(“Server is disconnected.”);
    };

    /**
     * 웹소켓 에러 발생하는 경우 호출
     */

    g_webSocket.onerror = function(message) {
        addLineToChatBox(“Error!”);
    };
}

/**
* 채팅 박스영역에 내용 한 줄 추가
*/

function addLineToChatBox(_line) {
    if (_line == null) {
        _line = “”;
    }
    
    var chatBoxArea = document.getElementById(“chatBoxArea”);
    chatBoxArea.value += _line + “\n”;
    chatBoxArea.scrollTop = chatBoxArea.scrollHeight;    
}

/**
* Send 버튼 클릭하는 경우 호출 (서버로 메시지 전송)
*/

function sendButton_onclick() {
    var inputMsgBox = document.getElementById(“inputMsgBox”);
    if (inputMsgBox == null || inputMsgBox.value == null || inputMsgBox.value.length == 0) {
        return false;
    }
    
    var chatBoxArea = document.getElementById(“chatBoxArea”);
    
    if (g_webSocket == null || g_webSocket.readyState == 3) {
        chatBoxArea.value += “Server is disconnected.\n”;
        return false;
    }
    
    // 서버로 메시지 전송
    g_webSocket.send(inputMsgBox.value);
    inputMsgBox.value = “”;
    inputMsgBox.focus();
    
    return true;
}

/**
* Disconnect 버튼 클릭하는 경우 호출
*/

function disconnectButton_onclick() {
    if (g_webSocket != null) {
        g_webSocket.close();    
    }
}

/**
* inputMsgBox 키입력하는 경우 호출
*/

function inputMsgBox_onkeypress() {
    if (event == null) {
        return false;
    }
    
    // 엔터키 누를 경우 서버로 메시지 전송
    var keyCode = event.keyCode || event.which;
    if (keyCode == 13) {
        sendButton_onclick();
    }
}
</script>
</head>
<body>
    <input id=“inputMsgBox” style=“width: 250px;” type=“text” onkeypress=“inputMsgBox_onkeypress()”>
    <input id=“sendButton” value=“Send” type=“button” onclick=“sendButton_onclick()”>
    <input id=“disconnectButton” value=“Disconnect” type=“button” onclick=“disconnectButton_onclick()”>
    <br/>
    <textarea id=“chatBoxArea” style=“width: 100%;” rows=“10” cols=“50” readonly=“readonly”></textarea>
</body>
</html>

 

6. OOOController.java 파일 수정
@Controller 가 붙어있는 아무 컨트롤러나 상관없다. @Controller 가 붙어있는 파일이 없다면 새로 생성하자.
도메인:포트/chat 을 주소창에 입력하면 chat.jsp 파일이 열리도록 컨트롤러를 내에 chat 메서드를 만들고 @RequestMapping 어노테이션을 붙여준다.

package 원하는_패키지명;

import java.util.Locale;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class MainController {

    @RequestMapping(value=“/”)
    public String main() {
        return “index”;
    }
    
    @RequestMapping(value = “/chat”, method = RequestMethod.GET)
    public String chat(Locale locale, Model model) {
        return “chat”;
    }

}

 

7. 테스트

브라우저 여러 개를 띄워, 도메인:포트/chat (예를 들어 localhost:8080/chat) 에 접속한 후 채팅을 해보자.

[JAVA] 특정 URL 헤더의 쿠키 가져오기 (getCookiesOnly)

[JAVA] 특정 URL 헤더의 쿠키 가져오기 (getCookiesOnly)

특정 URL의 내용(responseBody)을 얻기 위해서는 일반적으로 자바에서 기본 제공하는 java.net.HttpURLConnection 클래스를 사용한다. 그런데 해당 클래스로는 응답코드가 301, 302일 경우(Location 으로 리다이렉트하는 경우)에는 Header 내의 Cookie 값들을 제대로 가져올 수 없었다.

대신 아래와 같이 GetMethod 클래스를 사용해보니 Cookie 값부터 Locaion 값까지 Header 내용을 잘 가져올 수 있었다.

 1. 라이브러리 임포트

/WEB-INF/lib/ 경로에 commons-httpclient-3.1.jar, commons-logging-1.0.4.jar, commons-codec-1.10.jar 파일을 위치시키기

또는 pom.xml 에 아래 내용 입력

<!– https://mvnrepository.com/artifact/commons-httpclient/commons-httpclient –>
<dependency>
    <groupId>commons-httpclient</groupId>
    <artifactId>commons-httpclient</artifactId>
    <version>3.1</version>
</dependency>

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.10</version>
</dependency>

2. 특정 URL 의 쿠키 가져오기 예제

import java.io.IOException;

import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;

public class GetMethodTest {
   
   
    public static void main(String[] args) {
        try {
            GetMethodTest instance = new GetMethodTest();
            String cookies = instance.getCookiesOnly(“https://blog.naver.com/bb_”);
            System.out.println(“———-“);
            System.out.println(“cookies : ” + cookies);
           
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
   
   
    private String getCookiesOnly(String targetUrl) throws IOException, Exception {
        StringBuffer cookieBuff = new StringBuffer();
       
        HttpClient httpClient = null;
        GetMethod getMethod = null;
       
        try {
            httpClient = new HttpClient();
            getMethod = new GetMethod(targetUrl);
            getMethod.setFollowRedirects(false);

            httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(10 * 1000);
            httpClient.getHttpConnectionManager().getParams().setSoTimeout(60 * 1000);

            int statusCode = httpClient.executeMethod(getMethod);

            Header[] headers = getMethod.getResponseHeaders();
            if (headers != null && headers.length > 0) {
                int headerCount = headers.length;
                for (int i=0; i<headerCount; i++) {
                    Header header = headers[i];
                    if (header == null) {
                        continue;
                    }
                   
                    if (header.getName() == null) {
                        continue;
                    }
                   
                    if (header.getValue() == null) {
                        continue;
                    }
                   
                    System.out.println(“header (” + i + “) : ” + header.getName() + ” : ” + header.getValue());
                   
                    if (header.getName().equalsIgnoreCase(“Set-Cookie”)) {
                        String oneCookie = header.getValue();
                        int idxSemicolon = oneCookie.indexOf(“;”);
                        if (idxSemicolon > -1) {
                            oneCookie = oneCookie.substring(0, idxSemicolon + 1);
                        }
                       
                        // 빈값 세팅은 skip
                        if (oneCookie.endsWith(“=\”\”;”) || oneCookie.endsWith(“=”;”)) {
                            continue;
                        }
                       
                        if (cookieBuff.length() > 0) {
                            cookieBuff.append(” “);
                        }
                       
                        cookieBuff.append(oneCookie);
                    }
                }
            }
           
            System.out.println(“statusCode : ” + statusCode);
            // System.out.println(“responseBody : ” + getMethod.getResponseBodyAsString());
           
        } catch (IOException e) {
            throw e;

        } catch (Exception e) {
            throw e;

        } finally {
            try {
                if (getMethod != null) {
                    getMethod.releaseConnection();
                }
            } catch (Exception e) {
            } finally {
                getMethod = null;
            }

            httpClient = null;
        }

        return cookieBuff.toString();
    }
}

3. 실행결과

header (0) : Date : Tue, 17 Nov 2020 03:21:02 GMT
header (1) : Content-Type : text/html;charset=UTF-8
header (2) : Content-Length : 2671
header (3) : Connection : close
header (4) : Vary : Accept-Encoding
header (5) : Vary : Accept-Encoding
header (6) : Cache-Control : no-cache
header (7) : Expires : Thu, 01 Jan 1970 00:00:00 GMT
header (8) : Set-Cookie : JSESSIONID=2E502B130F6A70B9A92D812644EFAAF7.jvm1; Path=/; Secure; HttpOnly
header (9) : Server : nxfps
header (10) : Referrer-policy : unsafe-url
statusCode : 200
———-
cookies : JSESSIONID=2E502B130F6A70B9A92D812644EFAAF7.jvm1;

4. 쿠키의 활용 (특정 페이지의 내용 가져오기)

cookies 변수는 아래와 같은 형태를 갖는다.

name1=value1;name2=value2;name3=value3;

이렇게 얻은 쿠키를 세팅해서 특정 URL의 내용(responseBody)를 가져오기 위해서는 HttpURLConnection 클래스의 setRequestProperty 메서드를 사용하면 된다.

예를 들면 아래와 같다.

String strUrl = “https://blog.naver.com/bb_”;
URL urlObj = new URL(strUrl);
HttpURLConnection conn = (HttpURLConnection) urlObj.openConnection();

(중략)

String cookies = “name1=value1;name2=value2;name3=value3;”;
conn.setRequestProperty(“Cookie”, cookies);

(후략)

참고삼아 HttpURLConnection 클래스로 특정 URL의 내용(responseBody)를 가져오는 코드를 남겨둔다. (GET방식)

public String getResponseBody(String strUrl, String encoding, String cookies) throws IOException, Exception {

        URL urlObj = null;
        HttpURLConnection conn = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        StringBuffer response = new StringBuffer();

        try {
            urlObj = new URL(strUrl);
            conn = (HttpURLConnection) urlObj.openConnection();
            conn.setDoOutput(true);
            conn.setUseCaches(false);
            conn.setRequestProperty(“access-type”, “AJAX”);
            conn.setConnectTimeout(30 * 1000);
            conn.setReadTimeout(30 * 1000);

            // 쿠키 세팅

            if (cookies != null && cookies.length() > 0) {
                conn.setRequestProperty(“Cookie”, cookies);
            }

            isr = new InputStreamReader(conn.getInputStream(), encoding);
            br = new BufferedReader(isr);

            String oneLine = null;
            while ((oneLine = br.readLine()) != null) {
                response.append(oneLine);
            }

        } catch (IOException e) {
            throw e;

        } catch (Exception e) {
            throw e;

        } finally {
            try {
                if (isr != null) {
                    isr.close();
                }
            } catch (IOException e) {
            } catch (Exception e) {
            } finally {
                isr = null;
            }
           
            try {
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
            } catch (Exception e) {
            } finally {
                br = null;
            }
           
            try {
                if (conn != null) {
                    conn.disconnect();
                }
            } catch (NullPointerException e) {
            } catch (Exception e) {
            } finally {
                br = null;
            }
        }
       
        return response.toString();
    }

5. 쿠키의 활용 (특정 페이지로 페이지 리다이렉트)

cookies 변수는 아래와 같은 형태를 갖는다.

name1=value1;name2=value2;name3=value3;

이렇게 얻은 쿠키를 세팅해서 특정 페이지를 열 수 있다.

우선 백엔드 단에서는 해당 쿠키를 어트리뷰트에 담아서(ex : pageContext.setAttribute(“pageCookies”, cookies);) 프론트엔드로 내려주고, 이후 자바스크립트 단에서 document.cookie 값을 바꾸고 location.href 로 페이지를 이동시키면 된다.

아래는 jsp 페이지 예제다.

<%@page language=”java” %>
<%@page contentType=”text/html; charset=UTF-8″ %>

<html>

<script>

window.onload = function() {

    // document.cookie = “name1=value1;name2=value2;name3=value3;”;

    document.cookie = “${pageCookies}”;

    location.href = “http://이동하기_원하는_특정_페이지“;

}

</script>

</html>

[JAVA] json 파싱

[JAVA] json 파싱

1. 라이브러리 임포트

/WEB-INF/lib/ 경로에 json-20200518.jar 파일을 위치시키기

또는 pom.xml 에 아래 내용 입력

<!– https://mvnrepository.com/artifact/org.json/json –>
<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20200518</version>
</dependency>

2. 자바 json 파싱 예제

import org.json.JSONArray;
import org.json.JSONObject;

/**
 * org.json.JSONObject 라이브러리는 간편하게 json 파싱을 지원하나,
 * 해당하는 요소가 없을 경우 여지없이 Exception 을 발생시킨다.
 * 따라서 불필요한 오류가 발생하지 않도록 본 유틸 클래스로 감싸서 사용.
 */
public class JsonUtil {
   
   
    /**
     * 문자열을 json 객체로 파싱
     *
     * @param strJson
     * @return
     */
    public static JSONObject parseJsonObject(String strJson) {
        JSONObject result = null;
        try {
            result = new JSONObject(strJson);
           
        } catch (NullPointerException e) {
        } catch (Exception e) {}
       
        return result;
    }
   
   
    /**
     * json 객체에서 특정키로 json 객체 가져오기
     *
     * @param jsonObj
     * @param key
     * @return
     */
    public static JSONObject getJsonObject(JSONObject jsonObj, String key) {
        JSONObject result = null;
        try {
            result = jsonObj.getJSONObject(key);
           
        } catch (NullPointerException e) {
        } catch (Exception e) {}
       
        return result;
    }
   
   
    /**
     * json 객체에서 특정키로 json 배열 가져오기
     *
     * @param jsonObj
     * @param key
     * @return
     */
    public static JSONArray getJSONArray(JSONObject jsonObj, String key) {
        JSONArray result = null;
        try {
            result = jsonObj.getJSONArray(key);
           
        } catch (NullPointerException e) {
        } catch (Exception e) {}
       
        return result;
    }
   
   
    /**
     * json 객체에서 특정키로 문자열 가져오기
     *
     * @param jsonObj
     * @param key
     * @return
     */
    public static String getString(JSONObject jsonObj, String key) {
        String result = “”;
        try {
            result = jsonObj.getString(key);
            if (result == null) {
                result = “”;
            }
       
        } catch (NullPointerException e) {
        } catch (Exception e) {}
       
        return result;
    }
}

[JAVA] removeFirstSlice, removeLastSlice

[JAVA] removeFirstSlice, removeLastSlice

/**
     * 문자열(text) 안에 특정 문자열(slice)이 존재할 경우 앞에서부터 1개 제거
     *
     * @param text
     * @param slice
     * @return
     */
    public static String removeFirstSlice(String text, String slice) {
        if (text == null || text.length() == 0) {
            return “”;
        }
       
        if (slice == null || slice.length() == 0) {
            return text;
        }
       
        int idxSlice = text.indexOf(slice);
        if (idxSlice > -1) {
            text = text.substring(0, idxSlice) + text.substring(idxSlice + slice.length());
        }
       
        return text;
    }
   
   
    /**
     * 문자열(text) 안에 특정 문자열(slice)이 존재할 경우 뒤에서부터 1개 제거
     *
     * @param xml
     * @param slice
     * @return
     */
    public static String removeLastSlice(String text, String slice) {
        if (text == null || text.length() == 0) {
            return “”;
        }
       
        if (slice == null || slice.length() == 0) {
            return text;
        }
       
        int idxSlice = text.lastIndexOf(slice);
        if (idxSlice > -1) {
            text = text.substring(0, idxSlice) + text.substring(idxSlice + slice.length());
        }
       
        return text;
    }

[Tomcat] Apache 1개 Tomcat 2개 설정 (아파치 1개 톰캣 2개 설정)

[Tomcat] Apache 1개 Tomcat 2개 설정 (아파치 1개 톰캣 2개 설정)

Apache 1개에 Tomcat 2개 연결하는 방법. 기존에 톰캣과 연동되어 있는 아파치에, 포트를 다르게 하여 톰캣을 하나 추가하는 방법이다.

각각의 톰캣이 잘 동작하는 상태라고 전제하고, Apache 웹서버 설정 방법만 남겨둔다.

[AS-IS]

Apache 80 포트 => Tomcat(1)에 연결. 해당 톰캣의 포트는 8080, 리다이렉트 포트는 8443, AJP 포트는 8009, 셧다운 포트는 8005.

[TO-BE]

Apache 80 포트 => Tomcat(1)에 연결. 해당 톰캣의 포트는 8080, 리다이렉트 포트는 8443, AJP 포트는 8009, 셧다운 포트는 8005.

Apache 9090 포트 => Tomcat(2)에 연결. 해당 톰캣의 포트는 18080, 리다이렉트 포트는 18443, AJP 포트는 18009, 셧다운 포트는 18005.

1. conf/httpd.conf 파일 수정

[AS-IS]

Listen 80

[TO-BE]

Listen 80

Listen 9090

[AS-IS]

LoadModule jk_module modules/mod_jk.so
<IfModule mod_jk.c>
  JkWorkersFile conf/workers.properties
  JkLogFile logs/mod_jk.log
  JkLogLevel info

  JkMount /* worker1
</IfModule>

[TO-BE]

LoadModule jk_module modules/mod_jk.so
<IfModule mod_jk.c>
  JkWorkersFile conf/workers.properties
  JkLogFile logs/mod_jk.log
  JkLogLevel info

  JkMount /* worker1
</IfModule>

<VirtualHost *:9090>
  DocumentRoot “C:/tomcat2/webapps/ProjectName”
  JkLogFile logs/mod_jk.log
  JkLogLevel info


  JkMount /* worker2
</VirtualHost>

2. conf/workers.properties 파일 수정

[AS-IS]

worker.list=worker1
worker.worker1.port=8009
worker.worker1.host=localhost
worker.worker1.type=ajp13
worker.worker1.lbfactor=1


[TO-BE]

worker.list=worker1,worker2
worker.worker1.port=8009
worker.worker1.host=localhost
worker.worker1.type=ajp13
worker.worker1.lbfactor=1

worker.worker2.port=18009
worker.worker2.host=localhost
worker.worker2.type=ajp13
worker.worker2.lbfactor=1

 

[CSS] input border highlight

[CSS] input border highlight

HTML 인풋박스에 커서가 포커싱되어있을 때 테두리 하이라이트(border highlight) 수정하는 방법.

포커스된 인풋박스 테두리 없애기

<style>

input:focus {
    outline: 0px;
}

</style>

포커스된 인풋박스 테두리 수정 (ex : 하늘색 5px)

<style>

input:focus {
    outline: 5px solid #80dbff;
}

</style>

아이폰 14.2에서 인풋박스 테두리 하이라이트가 깨지는 현상이 있어서 위와 같이 css를 수정해봤는데 개선 효과가 있다.

[WebtoB/Tmax] WebtoB/Tmax 환경에서 자바스크립트 페이지 이동(location.href) 동작하지 않는 문제

[WebtoB/Tmax] WebtoB/Tmax 환경에서 자바스크립트 페이지 이동(location.href) 동작하지 않는 문제

WebtoB/Tmax 오류라고 하기는 어려운 문제이지만, 트러블 슈팅으로 며칠을 끌었던 문제이기에 여기에 기록해둠.

Apache/Tomcat 서버 구성에서 잘 동작하던 웹 어플리케이션을 WebtoB/Tmax 구성으로 변경했을 때 문제가 생겼음.

처음으로 인지했던 문제는, 첫화면에 해당하는 jsp 페이지가 하얗게 나오는 현상이었음.

여러가지 테스트 결과 웹 브라우저 주소창에 피지컬하게 주소를 입력하면 페이지가 보이지만, 자바스크립트(javascript, js) 단의 페이지 이동(location.href) 코드가 동작하지 않는 문제였음.

정확히 얘기하면 location.href = “http ://도메인주소:포트/test/page.jsp” 이러한 코드는 동작하는데, 도메인을 빼고 location.href = “/test/page.jsp” 라고 쓰여져 있는 경우 페이지 이동이 되지 않는 문제였음.

첫화면에 해당하는 jsp 페이지가 하얗게 나온 이유도, 해당 페이지가 로드되자마자(window.onload) location.href 코드를 사용하기 때문이었음.

WAS 엔지니어들도 자기들 문제가 아니라고 하면서 해결하지 못했음.

결국 며칠 동안 수정하지 못했던 이 문제는 다른 업체의 웹 어플리케이션에서도 동일한 현상이 재현되면서 해결됨.

WebtoB 설정을 고치면 되는 문제였음.

WebtoB 환경설정 파일인 http.m 파일에서 Headers 라는 부분을 주석처리하면 해결되었음.

아마도 도메인이 들어있지 않은 location.href 코드를 보안에 문제있는 코드로 인식한 것 같음.

http.m 파일

[AS-IS]

Headers = “security,X-XSS,X-Content,strict,X-Download”,

[TO-BE]

#Headers = “security,X-XSS,X-Content,strict,X-Download”,

아마 Headers 에 적혀있는 값 전부가 문제가 되진 않을 것 같음.

한 개 정도가 문제가 될테니 몇 개를 빼고 넣으면서 테스트해보면 알아냈을테지만, 운영 환경이고 그렇게까지 테스트할 상황이 안된다고 했기 때문에 Headers를 전체 주석처리 하였음.

이후 자바스크립트의 location.href 코드가 정상적으로 잘 동작함.

WAS 엔지니어도 모르는 현상이라고 하고, 고치고 나서도 모르겠다고 하는걸 보면 잘 알려지지 않은 속성들 같음.

끝.

[JAVA] AES256 암호화 예제

[JAVA] AES256 암호화 예제

자바에서 AES256 으로 평문을 암호화하고, 암호화된 값을 평문으로 복호화하는 예제이다.

Secret Key 가 “0123456789abcdefghij0123456789ab”일 때 encryptAES 메서드를 사용하면 평문 “Hello World!” 가 아래와 같이 AES256 암호화 된다.

Secret Key : 0123456789abcdefghij0123456789ab

입력 : Hello World!
결과 : YanblGzXpM13KWrqVqhMYA==

(만약 Base64로 만들 때 Base64.encodeBase64URLSafeString 을 사용하면, 결과는 YanblGzXpM13KWrqVqhMYA)

여기서 Secret Key는 필자가 임의로 정한 것이다. 원하는 임의의 32자리 문자열을 사용하면 된다.

암호화할 때의 Secret Key와 복호화할 때의 Secret Key가 일치하기만 하면 된다.

아래 메서드에서 키의 길이는 16, 24, 32 만 지원한다.

키의 길이가 32 이면 AES-256 이라 부르고, 키의 길이가 24 이면 AES-192, 키의 길이가 16 이면 AES-128 이라 부른다.

참고로 Base64 는 org.apache.commons.codec.binary.Base64 패키지를 import 해야 한다.

import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

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

public class AES256Util {

        public static void main(String[] args) {
        AES256Util aesUtil = new AES256Util();
       
        String originText = “Hello World!”;
        System.out.println(“originText : ” + originText);
       
        String encText = aesUtil.encryptAES(“0123456789abcdefghij0123456789ab”, originText, false);
        System.out.println(“encText (encodeBase64) : ” + encText);
       
        encText = aesUtil.encryptAES(“0123456789abcdefghij0123456789ab”, originText, true);
        System.out.println(“encText (encodeBase64URLSafeString) : ” + encText);
       
        String decText = aesUtil.decryptAES(“0123456789abcdefghij0123456789ab”, encText);
        System.out.println(“decText : ” + decText);
    }
    
    
    public String encryptAES(String keyString, String plainText, boolean bUrlSafe) {
        String cipherText = “”;
        if ((keyString == null) || keyString.length() == 0 || (plainText == null) || plainText.length() == 0) {
            return cipherText;
        }
       

        // 키의 길이는 16, 24, 32 만 지원
        if ((keyString.length() != 16) && (keyString.length() != 24) && (keyString.length() != 32)) {
            return cipherText;
        }
       
        try {
            byte[] keyBytes = keyString.getBytes(“UTF-8”);
            byte[] plainTextBytes = plainText.getBytes(“UTF-8”);

            Cipher cipher = Cipher.getInstance(“AES/CBC/PKCS5Padding”);
            int bsize = cipher.getBlockSize();
            IvParameterSpec ivspec = new IvParameterSpec(Arrays.copyOfRange(keyBytes, 0, bsize));
           
            SecretKeySpec secureKey = new SecretKeySpec(keyBytes, “AES”);
            cipher.init(Cipher.ENCRYPT_MODE, secureKey, ivspec);
            byte[] encrypted = cipher.doFinal(plainTextBytes);

            if (bUrlSafe) {
                cipherText = Base64.encodeBase64URLSafeString(encrypted);
            } else {
                cipherText = new String(Base64.encodeBase64(encrypted), “UTF-8”);
            }
           
        } catch (Exception e) {
            cipherText = “”;
            e.printStackTrace();
        }

        return cipherText;
    }
   
   
    public String decryptAES(String keyString, String cipherText) {
        String plainText = “”;
        if ((keyString == null) || keyString.length() == 0 || (cipherText == null) || cipherText.length() == 0) {
            return plainText;
        }
       
        if ((keyString.length() != 16) && (keyString.length() != 24) && (keyString.length() != 32)) {
            return plainText;
        }

        try {
            byte[] keyBytes = keyString.getBytes(“UTF-8”);
            byte[] cipherTextBytes = Base64.decodeBase64(cipherText.getBytes(“UTF-8”));

            Cipher cipher = Cipher.getInstance(“AES/CBC/PKCS5Padding”);
            int bsize = cipher.getBlockSize();
            IvParameterSpec ivspec = new IvParameterSpec(Arrays.copyOfRange(keyBytes, 0, bsize));
           
            SecretKeySpec secureKey = new SecretKeySpec(keyBytes, “AES”);
            cipher.init(Cipher.DECRYPT_MODE, secureKey, ivspec);
            byte[] decrypted = cipher.doFinal(cipherTextBytes);

            plainText = new String(decrypted, “UTF-8”);
           
        } catch (Exception e) {
            plainText = “”;
            e.printStackTrace();
        }

        return plainText;
    }
}

실행결과

originText : Hello World!
encText (encodeBase64) : YanblGzXpM13KWrqVqhMYA==
encText (encodeBase64URLSafeString) : YanblGzXpM13KWrqVqhMYA
decText : Hello World!

문제해결

만약 AES256 암호화 메서드 실행 시 java.security.InvalidKeyException: Illegal key size 오류가 발생하는 경우

이유는 자바가 기본적으로 키 길이를 128bit까지 제한하기 때문이다.
제한을 풀기 위해서는 번들로 제공하는(따로 제공하는) JCE Unlimited Strength 정책 파일을 다운받아서 적용해야 한다.

* JCE Unlimited Strength 정책 파일 다운로드
Java6 : jce_policy-6.zip
http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html

Java7 : UnlimitedJCEPolicyJDK7.zip
http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html

Java8 : jce_policy-8.zip
http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

* JCE Unlimited Strength 정책 파일의 적용
Java8 을 예로 들겠다.

오라클 사이트에서 jce_policy-8.zip 파일을 다운받아서 압축을 풀면 UnlimitedJCEPolicyJDK8 폴더가 나온다.
UnlimitedJCEPolicyJDK8 폴더 안에는 local_policy.jar, US_export_policy.jar, README.txt 이렇게 파일 3개가 있다.

해당 jar 파일 2개를 복사해서 C:\[jdk1.8경로]\jre\lib\security 폴더 안에 붙여넣기(덮어쓰기) 하면 된다.
ex) C:\Java\jdk1.8.0_112\jre\lib\security\local_policy.jar 덮어쓰기

및 C:\Java\jdk1.8.0_112\jre\lib\security\US_export_policy.jar 덮어쓰기
(당연히 파일 덮어쓰기 전 기존 파일은 백업해둘 것)

AES256 검증

아래 사이트에서 AES256 암호화 결과 및 복호화 결과를 검증해볼 수 있다.

검증 사이트 : https://www.devglan.com/online-tools/aes-encryption-decryption 

Select Mode : CBC
Key Size in Bits : 256 bit
IV : 0123456789abcdef
Secret Key : 0123456789abcdefghij0123456789ab
Output Text Format : base64

참고로 IV 값은 Secret Key 값의 절반(16자리)을 입력하면 된다.

참고사이트 : https://hongsii.github.io/2018/04/05/java-aes256-error/

[SpringBoot] 이클립스(STS) 에서 스프링부트(Spring Boot) 시작하기

[SpringBoot] 이클립스(STS) 에서 스프링부트(Spring Boot) 시작하기

1. STS를 실행한다.

 

2. 원하는 워크스페이스 경로를 적고 [Launch] 버튼을 클릭한다.

 

3. STS 상단메뉴 [File] – [New] – [Spring Starter Project] 메뉴를 클릭한다.

 

4. Name 에 프로젝트 명을 적는다. (ex : TestProject)

Type 콤보박스는 Maven 을 선택한다.

Packaging 콤보박스는 Jar 를 선택한다.

Java Version 콤보박스는 원하는 버전을 선택한다.

Language 콤보박스는 Java 를 선택한다.

Group 은 패키지의 상위경로를 적는다.(ex : com.company)  보통 도메인 주소의 역순이다. 예를 들어 도메인이 company.com 일 경우 패키지 상위경로는 com.company 가 된다.

Atrifact 에는 프로젝트약칭을 적는다. (ex : test-project) 라이브러리화 됐을 때 jar에 들어가는 이름이라고 생각하면 된다.

Version 은 그대로 두거나 버전값을 적는다. (ex : 1.0)

Description 은 프로젝트 설명을 적는다. (ex : Spring Boot Project)

Package 에는 패키지 경로를 적는다. 패키지 상위경로 뒤에 프로젝트명을 붙인다. (ex : com.company.project)

하단의 [Next] 버튼을 클릭한다.

 

5. 검색창에 키워드를 입력해서 4가지를 추가한다. (1) Spring Boot DevTools (2) MyBatis Framework (3) MySQL Driver (4) Spring Web 을 추가하면 된다.

하단의 [Next] 버튼을 클릭한다.

 

6. 하단의 [Finish] 버튼을 클릭한다.

 

7. src/main/resources 하위의 application.properties 파일을 열고 아래와 같이 작성한다.

spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/SchemaName
spring.datasource.username=username
spring.datasource.password=password
server.servlet.encoding.charset=utf-8
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true

위의 MySQL 정보는 현재 프로젝트에 MySQL Driver 를 추가했기 때문에 오류가 나지 않도록 작성하는 것이다.

일단은 실제 MySQL 정보가 아니어도 좋고, 위와 똑같이 입력해도 프로젝트는 정상적으로 기동할 수 있다.

 

8. 프로젝트 폴더 하위의 pom.xml 파일을 열고 아래 내용을 추가한다.

    <!– TOMCAT –>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>

    <!– JSP –>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
    </dependency>

    <!– JSTL –>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
    </dependency>

닫는 태그인 </dependencies> 태그 바로 위에 붙여넣기 하면 된다.

 

9. 계속해서 pom.xml 파일을 수정한다. STS 하단의 Problems 탭을 봤을 때 “Maven Configuration Problem” 이 발생해서, 이를 해결하기 위해 아래 내용을 추가한다.

    <!– Maven Configuration Problem 해결 –>
    <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>

닫는 태그 </java.version> 밑에 추가하면 된다.

(참고사이트 : https://stackoverflow.com/questions/56212981/eclipse-showing-maven-configuration-problem-unknown)

 

10. 만약 STS 하단 Problems 탭에 “Project configuration is not up-to-date with pom.xml. Select Maven->Update Project… from the project context menu or use Quick Fix.” 오류 메시지가 표시되는 경우.

해당 항목을 마우스 우클릭하고 [Quick Fix] 메뉴를 클릭해서 관련 오류를 제거한다.

 

11. src/main/java 하위 com.company.project 패키지 안에 MainController.java 파일을 만들고 아래와 같이 내용 작성한다.

package com.company.project;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class MainController {

    @RequestMapping(value=”/”)
    public String main() {
        return “index”;
    }
}

 

12. src/main 폴더 아래에 webapp 폴더 생성, 그 아래에 WEB-INF 폴더 생성, 그 아래에 views 폴더를 생성, 그 아래에 index.jsp 파일을 생성한다.

다시 말해 index.jsp 의 경로가 src/main/webapp/WEB-INF/views/index.jsp 가 되도록 관련 폴더 및 파일을 생성한다.

index.jsp 파일 내용은 다음과 같이 작성한다.

<html>
<head>
</head>
<body>
Hello World!
</body>
</html>

 

13. 프로젝트 폴더에서 마우스 우클릭 – [Run As] – [Spring Boot App] 으로 서버를 기동한다.

 

14. 크롬 등 웹 브라우저에서 localhost:8080 로 접속하면 Hello World! 가 표시된다.

 

스프링 부트 기본 프로젝트 구성이 정상적으로 완료되었다.

참고사이트 : https://badstorage.tistory.com/10


[HTML/CSS] CSS 점점점 말줄임표 효과 ellipsis

[HTML/CSS] CSS 점점점 말줄임표 효과 ellipsis

<html>
<head>
    <style>
    .ellipsis_test {
        width: 300px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    </style>
</head>
<body>
    <div class=”ellipsis_test”>문자열을 길게 입력해본다 문자열을 길게 입력해본다 문자열을 길게 입력해본다 문자열을 길게 입력해본다 문자열을 길게 입력해본다 문자열을 길게 입력해본다 문자열을 길게 입력해본다 문자열을 길게 입력해본다 문자열을 길게 입력해본다 문자열을 길게 입력해본다</div>
</body>
</html>

[JAVA] heap dump 파일 생성하기 (jmap 명령어 사용방법)

[JAVA] heap dump 파일 생성하기 (jmap 명령어 사용방법)

리눅스 또는 윈도우 운영체제에 JDK 가 설치된 상태여야 한다. (JRE 만 설치한 경우 jmap 없음)

1. JVM 의 PID 알아내기

jps -v

2. 특정 PID에 대한 heap dump 파일 생성하기

jmap -dump:format=b,file=test_20201105.hprof [PID]

ex) jmap -dump:format=b,file=test_20201105.hprof 19368

[iOS] 아이폰 ipa 다운로드 링크 방법 (plist 파일 작성방법)

[iOS] 아이폰 ipa 다운로드 링크 방법 (plist 파일 작성방법)

아이폰으로 접속한 특정 웹페이지에서 ipa 파일을 다운로드 및 설치하게 하려면 어떻게 해야할까?

전체적인 이해를 돕기 위해 안드로이드 먼저 알아보자.

1. 안드로이드 apk 파일 다운로드 링크 방법


안드로이드의 앱 설치파일 확장자는 apk 다. apk 파일은 html 상에서 a 태그로 링크를 걸면 안드로이드 기기에서 해당 링크 클릭 시 apk 파일을 다운로드 받을 수 있고, 이어서 앱을 설치할 수 있다.

예를 들어 <a href=”https://특정도메인/test.apk“>클릭</a> 이라고 html 을 작성했다면 안드로이드 기기에서 “클릭” 버튼을 눌렀을 때 apk 파일 다운로드 및 설치가 잘 이루어진다는 뜻이다.

2. 아이폰 ipa 파일 다운로드 링크 방법

한편, 아이폰의 앱 설치파일 확장자는 ipa 다. ipa 파일은 안드로이드와 달리, html 상에서 a 태그로 링크를 걸어도 소용없다. 아이폰에서 해당 링크 클릭 시 ipa 파일을 다운로드 받을 수 없고, 설치를 진행할 수 없다.

예를 들어 <a href=”https://특정도메인/test.ipa“>클릭</a> 이라고 html 을 작성했다면 아이폰에서 “클릭” 버튼을 눌렀을 때 ipa 파일 다운로드 및 설치는 진행되지 않는다.

아이폰에서 특정 링크를 클릭 시 ipa 파일을 다운로드 및 설치하려면, 우선 plist 라는 확장자로 파일을 작성해야 한다. plist 파일을 만들고, 해당 plist 파일 안에 ipa 정보를 입력해야 한다. 그리고 a 태그에는 itms-services 라는 프로토콜로 plist 를 링크시켜야 한다.

예를 들어 plist 를 다운받을 수 있는 주소가 https://특정도메인/test.plist 라면, a 태그는 다음과 같이 작성한다.

<a href=”itms-services://?action=download-manifest&url=https://특정도메인/test.plist“>

그리고 plist 확장자 파일은 아래 예시와 같이 작성한다.

test.plist 예시

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE plist PUBLIC “-//Apple//DTD PLIST 1.0//EN” http://www.apple.com/DTDs/PropertyList-1.0.dtd>
<plist version=”1.0″>
<dict>
    <key>items</key>
    <array>
        <dict>
            <key>assets</key>
            <array>
                <dict>
                    <key>kind</key>
                    <string>software-package</string>
                    <key>url</key>
                    <string>https:// 특정도메인/test.ipa</string>
                </dict>
            </array>
            <key>metadata</key>
            <dict>
                <key>bundle-identifier</key>
                <string>kr.co.ddoc.project</string>
                <key>kind</key>
                <string>software</string>
                <key>title</key>
                <string>테스트앱</string>
            </dict>
        </dict>
    </array>
</dict>
</plist>

1. <key>url</key> 다음에 위치한 <string> 태그 내용으로는 ipa 파일의 URL 경로를 입력한다.

2. <key>bundle-identifier</key> 다음에 위치한 <string> 태그 내용으로는 ipa 파일의 해당하는 앱 패키지명을 입력한다.

3. <key>title</key> 다음에 위치한 <string> 태그 내용으로는 앱의 제목을 입력한다.

여기서 주의할 점은 plist 파일을 바라보는 URL이 https 프로토콜을 사용해야 한다는 점이다.

참고로 웹서버(ex : 아파치 웹서버) 또는 WAS(ex : 톰캣) 에 SSL 인증서를 입히면 http 프로토콜로 동작하던 사이트가 https 프로토콜로 동작한다.

만약 업로드할만한 마땅한 서버가 없거나 https 인증서를 입힐 상황이 안된다면 드랍박스(dropbox)라는 웹사이트를 이용할 수 있다. 드랍박스에 파일 업로드 및 다운로드 링크를 만드는 방법은 아래 글을 참고하면 된다.

드랍박스(dropbox) 파일 다운로드 주소 만드는 방법 : https://blog.naver.com/bb_/221581346975

[Oracle] 오라클 Comment 설정(추가 또는 수정), 삭제, 조회

[Oracle] 오라클 Comment 설정(추가 또는 수정), 삭제, 조회

오라클에서는 COMMENT ON 명령어를 사용하여 테이블 또는 컬럼에 참고용으로 설명을 부여할 수 있다.

1. Comment 설정(추가 또는 수정)

테이블 : COMMENT ON TABLE 테이블명 IS ‘설명내용’;

컬럼 : COMMENT ON COLUMN 테이블명.컬럼명 IS ‘설명내용’;​

2. Comment 삭제

테이블 : COMMENT ON TABLE 테이블명 IS ”;

컬럼 : COMMENT ON COLUMN 테이블명.컬럼명 IS ”;

3. Comment 조회

테이블 : SELECT * FROM ALL_TAB_COMMENTS;

컬럼 : SELECT * FROM ALL_COL_COMMENTS;

참고사이트 : https://jhnyang.tistory.com/309

[Eclipse] 이클립스에서 _jsp.java 파일 위치

[Eclipse] 이클립스에서 _jsp.java 파일 위치

로컬환경 이클립스로 톰캣을 기동했을 때 .jsp 파일은 _jsp.java 파일로 변환되고, _jsp.java 파일은 .class 파일로 컴파일된다.

이 때 jsp 파일에서 자바 익셉션이 발생하면 콘솔 또는 로그에 찍힌 StackTrace 의 라인넘버와 jsp 파일의 라인넘버가 불일치하는 것을 볼 수 있다.

StackTrace 에 기록된 라인넘버는 jsp의 라인넘버가 아니라 _jsp.java 의 라인넘버와 매칭되기 때문이다.

따라서 _jsp.java 의 위치를 알아낼 필요가 있다.

작업 중인 프로젝트의 워크스페이스로 가면 .metadata 폴더가 있다.
.metadata 폴더 내의 .plugins\org.eclipse.wst.server.core 폴더 하위에서 검색해보면 _jsp.java 파일을 찾을 수 있다.

ex) c:\프로젝트_워크스페이스\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\_\org\apache\jsp\파일명_jsp.java

[JAVA] getOutputStream() has already been called for this response

[JAVA] getOutputStream() has already been called for this response

jsp 에서 java.lang.IllegalStateException: getOutputStream() has already been called for this response 오류 발생하는 경우.

아웃풋스트림(ex : ServletOutputStream)을 사용하기 전에 out.clear() 로 JspWriter 객체를 비워주면 오류가 사라진다.

참고사이트 : https://kooremo.tistory.com/entry/javalangIllegalStateException-getOutputStream-has-already-been-called-for-this-respons

[JAVA] 멀티파트 폼(multipart/form-data)으로 넘긴 파라미터 request.getParameter 로 받기

[JAVA] 멀티파트 폼(multipart/form-data)으로 넘긴 파라미터 request.getParameter 로 받기

멀티파트 폼(<form enctype=”multipart/form-data”>)으로 넘긴 파라미터는 단순 request.getParameter 메서드로 받으면 null 이 나오고, multipartRequest.getParameter 메서드로 받아야 한다.

예를 들어 아래와 같은 form 으로 데이터를 전송했다면,

<form id=”test_form” target=”_blank” action=”/upload_test.jsp” method=”post” enctype=”multipart/form-data”>
    <input type=”file” multiple=”multiple” id=”file_input” name=”fileobj[]”>
    <input type=”hidden” name=”param1″ value=”value1″>
    <input type=”hidden” name=”param2″ value=”value2″>
    <input type=”hidden” name=”param3″ value=”value3″>
</form>

아래와 같이 데이터를 받아야 한다.

// 예 : upload_test.jsp 파일의 내용

// 100MB
int maxSize = 1024*1024*100;

MultipartRequest multipartRequest = new MultipartRequest(request, “C:\\test\\”, maxSize, “UTF-8”, new DefaultFileRenamePolicy());

String param1 = multipartRequest.getParameter(“param1”);
String param2 = multipartRequest.getParameter(“param2”);
String param3 = multipartRequest.getParameter(“param3”);

그런데 단순 request.getParameter 메서드로 파라미터를 받고 싶은 경우가 있다.  DefaultFileRenamePolicy 클래스를 사용하지 않고 FileRenamePolicy 인터페이스를 직접 구현(Implement)하고 싶을 때, 그 안에서 직전 페이지로부터 넘겨받은 파라미터를 사용하고 싶으면 그럴 수 있다.

이 때는 action 뒤쪽에 파라미터를 붙여서 get 으로 보내면 된다.

예를 들어 action=”/upload_test.jsp” 이 아니라, action=”/upload_test.jsp?param1=value1″ 과 같은 식으로 수정하면 된다. (cf : document.getElementById(“test_form”).action = “/upload_test.jsp?param1=value1”;)

전달받는 쪽에서는 request.getParameter(“param1”); 로 받으면 된다.

[Tomcat] 윈도우 톰캣 System.out.println 이 기록되지 않는 경우

[Tomcat] 윈도우 톰캣 System.out.println 이 기록되지 않는 경우

보통 자바에서 System.out.println 또는 System.err.println 으로 찍은 내용은 톰캣 catalina.out 파일에 찍힌다.

그런데 윈도우에서 톰캣을 구동하는 경우(cmd 콘솔에서 .bat 파일로 톰캣을 실행하는 경우), System.out.println 또는 System.err.println 내용이 콘솔에 출력되지만 로그 파일로 남지 않는 경우가 있다.

${catalina.base}/conf/context.xml 파일의 아래 한 줄을 추가하고 재기동한다.

<Context swallowOutput=”true”>

이 때 해당 내용은 catalina.out에 찍히는게 아니라 localhost-날짜.log 파일에 찍힌다.

참고로 swallowOutput 는 true인 경우에 system.out과 system.err로 출력한 바이트가 웹애플리케이션의 logger로 리다이렉션 되는 옵션값이며, 기본값은 false다.

참고사이트 1 : https://crazythink.github.io/categories/Tomcat/

참고사이트 2 : https://esysop.tistory.com/11

[JAVA] 특정 폴더 하위의 모든 파일 경로 가져오기

[JAVA] 특정 폴더 하위의 모든 파일 경로 가져오기

    /**
     * 특정 폴더 하위의 모든 파일 경로 가져오기
     *
     * @param target
     * @return
     */
    public static StringList getFilePathList(File target) {
        StringList resultList = new StringList();
        getFilePathListCore(resultList, target);
        return resultList;
    }
   
   
    /**
     * 특정 폴더 하위의 모든 파일 경로를 가져오기 (재귀)
     *
     * @param resultList
     * @param target
     */
    private static void getFilePathListCore(StringList resultList, File target) {
        if (target == null || !target.exists()) {
            return;
        }
       
        if (target.isDirectory()) {
            File[] fileArr = target.listFiles();
            if (fileArr != null && fileArr.length > 0) {
                int fileCount = fileArr.length;
                for (int i=0; i<fileCount; i++) {
                    getFilePathListCore(resultList, fileArr[i]);
                }
            }
           
        } else if (target.isFile()) {
            resultList.add(target.getAbsolutePath());
        }
    }

[JAVA] 쓰레드 덤프보는 JSP

[JAVA] 쓰레드 덤프보는 JSP

https://greatkim91.tistory.com/167

[Windows] 윈도우 업데이트 끄기(Windows Update 끄기)

[Windows] 윈도우 업데이트 끄기(Windows Update 끄기)

1. 시작 – 실행 – services.msc 입력 후 엔터 (또는 제어판 – 서비스)


 

2. [서비스] 창이 뜨면 우측 목록에서 [Windows Update] 항목 찾아서 마우스 우클릭 – 속성(R)

3. [Windows Update 속성] 창이 뜨면 [일반] 탭에서 [시작 유형]을 [자동]에서 [수동] 또는 [사용 안 함]으로 변경

하단의 서비스 상태 항목에서 [중지] 버튼 클릭

 

참고사이트 : https://gbworld.tistory.com/1184

[JAVA] 특정폴더 하위의 모든 파일 삭제

[JAVA] 특정폴더 하위의 모든 파일 삭제

    public void deleteFilesInRootDir(File rootDir) {
        deleteFilesInRootDir(rootDir, rootDir);
    }
   
   
    private void deleteFilesInRootDir(File rootDir, File target) {
        if (rootDir == null) {
            return;
        }
       
        if (target == null || !target.exists()) {
            return;
        }
       
        if (target.isDirectory()) {
            File[] files = target.listFiles();
            for (File oneFile : files) {
                if (oneFile != null && oneFile.isFile() && oneFile.exists()) {
                    try {
                        oneFile.delete();
                        // System.out.println(“delete… [” + oneFile.getAbsolutePath() + “]”);
                    } catch (Exception e) {
                    }
                } else if (oneFile != null && oneFile.isDirectory()) {
                    deleteFilesInRootDir(rootDir, oneFile);
                }
            }
           
            // delete without root folder
            if (!rootDir.getAbsolutePath().equals(target.getAbsolutePath())) {
                try {
                    target.delete();
                    // System.out.println(“delete… [” + target.getAbsolutePath() + “]”);
                } catch (Exception e) {
                }
            }
        }
    }

[Android] 안드로이드 웹뷰(WebView) 파일선택, 여러개 파일선택

[Android] 안드로이드 웹뷰(WebView) 파일선택, 여러개 파일선택

아이폰(iOS) 하이브리드 앱에서는 <input type=”file”> 을 사용하면 해당 요소를 클릭 시 파일선택 창(FileChooser)이 잘 뜨지만, 안드로이드 웹뷰에서는 <input type=”file”> 요소를 클릭해도 아무 반응이 없다.

안드로이드 하이브리드앱에서 파일을 선택하는 기능은 아래와 같이 구현 가능하다.

1. mFilePathCallback 변수를 전역변수로 선언한다.

webView 를 사용할 Activity 클래스(또는 Activity 를 상속받은 클래스) 에 선언하면 된다.

    // 안드로이드 웹뷰에서 파일 첨부하기
    ValueCallback mFilePathCallback = null;

2. WebChromeClient 클래스의 onShowFileChooser 메서드를 오버라이딩해서 아래와 같이 작성한다.

파일 n개 선택(파일 여러개 선택, 파일 다중선택) 하려면 intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); 코드를 포함시키자.

    webView.setWebChromeClient(new WebChromeClient() {
        // 안드로이드 웹뷰에서 파일 첨부하기
        @Override
        public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams) {
            mFilePathCallback = filePathCallback;

            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType(“image/*”);

            // 파일 n개 선택 가능하도록 처리
            intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);

            startActivityForResult(intent, 0);
            return true;
        }
    });

만약 WebChromeClient 를 상속받아 별개의 자바파일로 구현했다면(ex : public class OOOWebChromeClient extends WebChromeClient {}), startActivityForResult 메서드를 곧바로 사용할 수 없을 것이다.

이 경우 WebChromeClient 생성자에서 activity 를 받아 thisActivity 라는 멤버변수에 저장해놓으면 thisActivity.startActivityForResult(intent, 0); 식으로 사용할 수 있다.

public class OOOWebChromeClient extends WebChromeClient {
    private final Activity thisActivity;

    public OOOWebChromeClient(Activity thisActivity) {
        super();
        this.thisActivity = thisActivity;
    }

    (중략)

}   

3. mFilePathCallback 변수가 선언된 클래스, 다시 말해서 Activify 클래스(또는 Activity를 상속한 클래스) 하단에 아래와 같이 작성한다.

참고로 파일을 n개 선택(여러개 선택, 다중선택)한 경우 data.getClipData() 값이 not null이며, 파일을 1개 선택한 경우 data.getData() 값이 not null이다.

    // 안드로이드 웹뷰에서 파일 첨부하기
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        Log.e(“resultCode:: “, String.valueOf(resultCode));
        if (requestCode == 0 && resultCode == Activity.RESULT_OK) {

            // 파일 n개 선택한 경우
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && data != null && data.getClipData() != null && data.getClipData().getItemCount() > 0) {
                int count = data.getClipData().getItemCount();

                Uri[] uriArr = new Uri[count];
                for (int i=0; i<count; i++) {
                    uriArr[i] = data.getClipData().getItemAt(i).getUri();
                }

                mFilePathCallback.onReceiveValue(uriArr);

            } else if (data != null && data.getData() != null) {
                // 파일 1개 선택한 경우
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    mFilePathCallback.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
                } else {
                    mFilePathCallback.onReceiveValue(new Uri[]{data.getData()});
                }
            }

            mFilePathCallback = null;

        } else {
            mFilePathCallback.onReceiveValue(null);
        }
    }

만약 WebChromeClient 를 상속받아 별개의 자바파일로 구현했다면(ex : public class OOOWebChromeClient extends WebChromeClient {}), mFilePathCallback 변수를 사용할 수 없을 것이다. OOOWebChromeClien 클래스 내에 mFilePathCallback 의 getter, setter 메서드를 만들어서 접근하도록 하자.

참고사이트 1 : https://g-y-e-o-m.tistory.com/115

참고사이트 2 : https://medium.com/@kyle_seongwoo_jun/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-webview-filechooser-%EC%97%AC%EB%9F%AC-%ED%8C%8C%EC%9D%BC-%EC%84%A0%ED%83%9D%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-8da48465ada3 

[Javscript] 자바스크립트 post 로 전송하는 함수

[Javscript] 자바스크립트 post 로 전송하는 함수

function postUrl(_url) {
    if (_url == null || _url == “”) {
        return false;
    }
   
    var strAction = “”;
    var idxQuestion = _url.indexOf(“?”);
    if (idxQuestion > -1) {
        strAction = _url.substring(0, idxQuestion);   
    }
   
    var targetForm = document.createElement(“FORM”);
    targetForm.setAttribute(“id”, “targetForm”);
    targetForm.setAttribute(“name”, “targetForm”);
    targetForm.setAttribute(“action”, strAction);
    targetForm.setAttribute(“target”, “_self”);
    targetForm.setAttribute(“method”, “POST”);
    targetForm.setAttribute(“accept-charset”, “UTF-8”);
    targetForm.style.display = “none”;
   
    if (idxQuestion > -1) {
        var params = _url.substring(idxQuestion + 1);
       
        while (params.length > 0) {
            var idxEqual = params.indexOf(“=”);
            if (idxEqual > -1) {
                var key = params.substring(0, idxEqual);
                var value = “”;
               
                var idxAmp = params.indexOf(“&”, idxEqual + 1);
                if (idxAmp > -1) {
                    value = params.substring(idxEqual + 1, idxAmp);
                    params = params.substring(idxAmp + 1);
                } else {
                    value = params.substring(idxEqual + 1);
                    params = “”;
                }
               
                var inputElem = document.createElement(“INPUT”);
                inputElem.name = key;
                inputElem.value = value;
               
                targetForm.appendChild(inputElem);
            }
        }
    }
   

    // 기존객체 삭제
    var oldObj = document.getElementById(“targetForm”);
    if (oldObj != null) {
        document.getElementById(“targetForm”).parentNode.removeChild(oldObj);
    }

    document.body.appendChild(targetForm);
    targetForm.submit();
}

[JAVA] 다음날(1일후, 내일), 다음달(내달), 다음연도(내년) 날짜시간 구하기

[JAVA] 다음날(1일후, 내일), 다음달(내달), 다음연도(내년) 날짜시간 구하기

1. 자바에서 현재 날짜시간 구하기

기준 : 현재 날짜시간

=> 20201008160222 (2020년 10월 08일 16시 02분 22초)

    try {
        SimpleDateFormat sdf = new SimpleDateFormat(“yyyyMMddHHmmss”);

        // 현재 날짜시간 구하기
        Calendar cal = Calendar.getInstance();

       

        // 출력
        String resultDate = sdf.format(cal.getTime());

        
        String year = resultDate.substring(0, 4);
        String month = resultDate.substring(4, 6);
        String day = resultDate.substring(6, 8);
        String hour = resultDate.substring(8, 10);
        String minute = resultDate.substring(10, 12);
        String second = resultDate.substring(12, 14);

​       

        System.out.println(resultDate + ” (” + year + “년 ” + month + “월 ” + day + “일 “
        + hour + “시 ” + minute + “분 ” + second + “초)”);

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

2. 자바에서 특정일의 날짜시간 구하기

기준 : 20200101092030 (2020년 01월 01일 09시 20분 30초)

=> 20200101092030 (2020년 01월 01일 09시 20분 30초)

     try {
        SimpleDateFormat sdf = new SimpleDateFormat(“yyyyMMddHHmmss”);
       
        // 특정일의 날짜시간 구하기
        // 2020년 01월 01일 09시 20분 30초
        String strDate = “20200101092030”;
        Date date = sdf.parse(strDate);

        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        

        // 출력
        String resultDate = sdf.format(cal.getTime());

        String year = resultDate.substring(0, 4);
        String month = resultDate.substring(4, 6);
        String day = resultDate.substring(6, 8);
        String hour = resultDate.substring(8, 10);
        String minute = resultDate.substring(10, 12);
        String second = resultDate.substring(12, 14);

        System.out.println(resultDate + ” (” + year + “년 ” + month + “월 ” + day + “일 “
        + hour + “시 ” + minute + “분 ” + second + “초)”);

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

3. 자바에서 특정일 다음날(1일 후) 날짜시간 구하기

기준 : 20200101092030 (2020년 01월 01일 09시 20분 30초)

=> 20200102092030 (2020년 01월 02일 09시 20분 30초)

    try {
        SimpleDateFormat sdf = new SimpleDateFormat(“yyyyMMddHHmmss”);
       
        // 특정일 다음날(1일 후) 날짜시간 구하기
        // 2020년 01월 01일 09시 20분 30초의 다음날(1일 후)
        String strDate = “20200101092030”;
        Date date = sdf.parse(strDate);

        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
       
        cal.add(Calendar.DATE, 1); // 다음날(1일 후)

        // 출력
        String resultDate = sdf.format(cal.getTime());

        String year = resultDate.substring(0, 4);
        String month = resultDate.substring(4, 6);
        String day = resultDate.substring(6, 8);
        String hour = resultDate.substring(8, 10);
        String minute = resultDate.substring(10, 12);
        String second = resultDate.substring(12, 14);

        System.out.println(resultDate + ” (” + year + “년 ” + month + “월 ” + day + “일 “
        + hour + “시 ” + minute + “분 ” + second + “초)”);

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

위와 같이 cal.add(Calendar.DATE, 1); 명령어를 사용하면 다음날(1일 후)의 날짜를 가져온다.

해당 라인을 수정하면 이전날(1일 전, 어제)/다음날(1일 후, 내일), 이전달(지난달)/다음달(내달), 이전연도(작년)/다음연도(내년)의 날짜를 구할 수 있다.

기준 : 20200101092030 (2020년 01월 01일 09시 20분 30초)

이전날(1일 전, 어제) : cal.add(Calendar.DATE, -1);

=> 20191231092030 (2019년 12월 31일 09시 20분 30초)

다음날(1일 후, 내일) : cal.add(Calendar.DATE, 1);

=> 20200102092030 (2020년 01월 02일 09시 20분 30초)

이전달(지난달) : cal.add(Calendar.MONTH, -1);

=> 20191201092030 (2019년 12월 01일 09시 20분 30초)

다음달(내달) : cal.add(Calendar.MONTH, 1);

=> 20200201092030 (2020년 02월 01일 09시 20분 30초)

이전연도(작년) : cal.add(Calendar.YEAR, -1);

=> 20190101092030 (2019년 01월 01일 09시 20분 30초)

다음연도(내년) : cal.add(Calendar.YEAR, 1);

=> 20210101092030 (2021년 01월 01일 09시 20분 30초)

만약 시간(시), 분, 초를 조정하고 싶다면 cal.add  명령어의 인자를 바꾸면 된다. 시간은 Calendar.HOUR_OF_DAY, 분은 Calendar.MINUTE, 초는 Calendar.SECOND 를 사용하면 된다. (1시간전/1시간후, 1분전/1분후, 1초전/1초후 등)

참고로 Calendar.HOUR_OF_DAY 는 24시간제(00:00 ~ 23:59)를 뜻하고, Calendar.HOUR 는 12시간제(AM 00:00 ~ 11:59, PM 00:00 ~ 11:59)를 뜻한다.

[JAVA] 시작일과 종료일 사이의 날짜 가져오기

[JAVA] 시작일과 종료일 사이의 날짜 가져오기

    /**
     * beginDate 부터 endDate 사이의 날짜 가져오기
     *
     * ex) beginDate == 20200930, endDate == 20201004 일 때,
     *     [20200930, 20201001, 20201002, 20201003, 20201004] 리턴
     * @param beginDate
     * @param endDate
     * @return
     * @throws Exception
     */
    private ArrayList<String> getDaysBetweenDates(String beginDate, String endDate) throws Exception {
        if (beginDate != null && beginDate.length() >= 8) {
            beginDate = beginDate.substring(0, 8);
        } else {
            return null;
        }
       
        if (endDate != null && endDate.length() >= 8) {
            endDate = endDate.substring(0, 8);
        } else {
            return null;
        }
       
        int iBeginDate = Integer.parseInt(beginDate);
        int iEndDate = Integer.parseInt(endDate);
        if (iBeginDate > iEndDate) {
            return null;
        }
       
       
        // 시작날짜 세팅
        int beginYear = Integer.parseInt(beginDate.substring(0, 4));
        int beginMonth = Integer.parseInt(beginDate.substring(4, 6));
        int beginDay = Integer.parseInt(beginDate.substring(6, 8));
       
        Calendar cal = Calendar.getInstance();
        cal.set(beginYear, beginMonth – 1, beginDay);
       
       
        ArrayList<String> resultList = new ArrayList<String>();
       
        SimpleDateFormat sdf = new SimpleDateFormat(“yyyyMMdd”);
        String oneDay = “”;
       
        // beginDate 부터 endDate 사이의 날짜 담기
        while (Integer.parseInt(sdf.format(cal.getTime())) <= iEndDate) {
            oneDay = sdf.format(cal.getTime());
            resultList.add(oneDay);
           
            // 다음날로 날짜 조정
            cal.add(Calendar.DATE, 1);
        }
       
        return resultList;
    }

참고사이트 : ​https://bugnote.tistory.com/26

 

[Tibero] 티베로 테이블명 조회, 컬럼명 조회, 테이블 상세정보 조회

[Tibero] 티베로 테이블명 조회, 컬럼명 조회, 컬럼상세정보 조회

티베로에서 테이블명 조회, 컬럼명 조회, 컬럼상세정보 조회/보기/보는 방법.

1. 티베로 테이블명 조회

SELECT * FROM ALL_TAB_COMMENTS;


SELECT * FROM ALL_TAB_COMMENTS WHERE TABLE_NAME = ‘테이블명’;

테이블명, 테이블 종류, 테이블 주석 확인 가능

2. 티베로 컬럼명 조회

SELECT * FROM ALL_COL_COMMENTS WHERE TABLE_NAME = ‘테이블명’;

테이블명, 컬럼명, 컬럼 주석 확인 가능

3. 티베로 테이블 상세정보 조회

SELECT * FROM ALL_TAB_COLUMNS WHERE TABLE_NAME = ‘테이블명’; 

테이블명, 컬럼명, 데이터타입, 컬럼수정자, 컬럼의 데이터타입 오너, 데이터 길이, NULLABLE, 컬럼ID, 열의 기본값 길이 등 확인 가능

참고사이트 : https://domoyosi.tistory.com/6

[AWS] Travis CI ./gradlew: Permission denied

[AWS] Travis CI ./gradlew: Permission denied

Travis CI 에서 ./gradlew: Permission denied 오류 메시지가 발생하는 경우.

.travis.yml 파일에 아래 코드를 추가하고 다시 commit/push 해본다.

before_install:

    – chmod +x gradlew


참고사이트 : https://m.blog.naver.com/ggomjae/221778504421

[JAVA] PDFBox 암호(패스워드)가 걸려있는 파일인지 확인하는 방법

[JAVA] PDFBox 암호(패스워드)가 걸려있는 파일인지 확인하는 방법

PDFBox 라이브러리 사용 시 document.isEncrypted() == true 이면 암호가 걸려있는 파일로 판단했으나, 암호입력 없이 정상적으로 열리는 파일인데도 true 가 나오는 경우가 있었다.

구글링을 해보니 암호가 빈값이어도 isEncrypted() == true 가 나올 수 있다고 했다.

결론은 isEncrypted() 로 암호유무를 판단해낼 수 없다.

새로 찾은 해결책은 PDFBox 버전을 2.0.4 버전 이상으로 올리는 것이다. (pdfbox-app-2.0.4.jar)

1. AS-IS 코드 (PDFBox 1.8.9 버전)

public boolean isPDFReadable(String filePath) throws IOException {
    boolean result = false;
    PDDocument document = null;
   
    try {
        document = PDDocument.load(filePath);
        if (!document.isEncrypted()) {
            result = true;
        }
       
    } catch (Exception e) {
        result = false;

    } finally {
    }

    return result;
}

PDFBox 1점대 버전에서는 암호가 걸려있는 PDF도 PDDocument.load 가 가능하다.

그런데 패스워드가 걸려있지 않은 PDF 문서 임에도 불구하고 document.isEncrypted() == true 가 나오는 문제가 있었다.

이에 따라 아래와 같이 라이브러리를 버전업하고 코드를 수정했다.

2. TO-BE 코드 (PDFBox 2.0.4 버전 이상)

public boolean isPDFReadable(String filePath) throws IOException {
    boolean result = false;
    PDDocument document = null;
   
    try {
        document = PDDocument.load(new File(filePath));
        if (document != null) {
            result = true;
        }
       
    } catch (Exception e) {
        result = false;

    } finally {
    }

    return result;
}

PDFBox 2.0.4. 버전 이상에서는 패스워드가 걸려있는 PDF를 PDDocument.load 할 경우 load 가 되지 않고 Exception 이 발생한다. 이를 통해 암호가 걸려있는지 여부를 알아낼 수 있다.

참고사이트 : https://stackoverflow.com/questions/15896691/how-to-check-if-a-pdf-is-password-protected-or-not 

[AWS] FileZilla 에서 AWS EC2 접속하는 방법

[AWS] FileZilla 에서 AWS EC2 접속하는 방법 

root 계정과 비밀번호로 접속하는 방법은 아니고, ppk 파일(개인키)로 접속하는 방법이다.

1. 상단메뉴의 [파일(F)] –  [사이트 관리자(S)] 클릭

2. [사이트 관리자] 창이 뜨면 하단의 [새 사이트(N)] 버튼을 클릭하고 정보 입력

프로토콜 : [SFTP – SSH File Transfer Protocol] 선택

호스트 : AWS ES2 탄력적 IP 입력 ex) 3.34.119.***

포트 : 22 입력

로그온 유형 : [키 파일] 선택

사용자 : [ec2-user] 입력

키 파일 : 확장자 ppk 파일 선택

[JAVA] 자바 순열 조합

[JAVA] 자바 순열 조합

직접 짠 순열 조합.

public class TestGetCombination {

    public static void main(String[] args) {
        TestGetCombination testGetCombination = new TestGetCombination();
        testGetCombination.start();
    }
   
   
    public void start() {
        // 인덱스 4개 중 3개 선택하기 예제
        // ex) 0, 1, 2, 3, 4
        int totalCount = 4;
        int countToGet = 3;
       
        ArrayList<ArrayList<Integer>> resultList = null;
       
        // 조합 구하기
        System.out.println(totalCount +  “개 중 ” + countToGet + “개 조합 경우의 수 구하기”);
        resultList = getCombination(totalCount, countToGet);
        if (resultList != null && resultList.size() > 0) {
            int count = resultList.size();
            System.out.println(“count : ” + count);
            for (int i=0; i<count; i++) {
                System.out.println(i + ” : ” + resultList.get(i));
            }
        }
       
        System.out.println();
       
        // 순열 구하기
        System.out.println(totalCount +  “개 중 ” + countToGet + “개 순열 경우의 수 구하기”);
        resultList = getPermutation(totalCount, countToGet);
        if (resultList != null && resultList.size() > 0) {
            int count = resultList.size();
            System.out.println(“count : ” + count);
            for (int i=0; i<count; i++) {
                System.out.println(i + ” : ” + resultList.get(i));
            }
        }
    }
   
   
    /**
     * 조합 구하기
     *
     * ex 1) totalCount == 4
     *          countToGet == 1
     *       resultList == [[0],
     *                       [1],
     *                       [2],
     *                       [3]]
     *
     * ex 2) totalCount == 4
     *       countToGet == 2
     *       resultList == [[0, 1],
     *                       [0, 2],
     *                       [0, 3],
     *                       [1, 2],
     *                       [1, 3],
     *                       [2, 3]]
     *      
     * ex 3) totalCount == 4
     *       countToGet == 3
     *       resultList == [[0, 1, 2],
     *                       [0, 1, 3],
     *                       [0, 2, 3],
     *                       [1, 2, 3]]
     *            
     *      
     *      
     * @param totalCount
     * @param countToGet
     * @return
     */
    public ArrayList<ArrayList<Integer>> getCombination(int totalCount, int countToGet) {
        ArrayList<ArrayList<Integer>> resultList = new ArrayList<ArrayList<Integer>>();
        getCombinationCore(resultList, null, 0, totalCount, countToGet);
        return resultList;
    }
   
   
    /**
     * 조합 구하기 재귀메서드
     * 넘겨받은 resultList 객체에 경우의 수를 담는다. resultList 가 사실상의 리턴값이다.
     *
     * @param resultList
     * @param inputResult
     * @param axisIndex
     * @param totalCount
     * @param countToGet
     */
    private void getCombinationCore(ArrayList<ArrayList<Integer>> resultList, ArrayList<Integer> inputResult, int axisIndex, int totalCount, int countToGet) {
        for (int i=axisIndex; i<totalCount; i++) {
            ArrayList<Integer> oneResult = null;
            if (axisIndex == 0) {
                oneResult = new ArrayList<Integer>();
            } else {
                oneResult = (ArrayList<Integer>) inputResult.clone();
            }
           
            // 1개씩 인덱스를 담는다.
            oneResult.add(i);
           
            if (oneResult.size() == countToGet) {
                // countToGet 개 만큼 담았으면 resultList 객체에 추가한다.
                resultList.add(oneResult);
               
            } else if (oneResult.size() < countToGet) {
                // countToGet 개 만큼 담을 때까지 재귀한다.
                getCombinationCore(resultList, oneResult, i + 1, totalCount, countToGet);
               
            } else {
                break;
            }
        }
    }
   
   
    /**
     * 순열 구하기
     *
     * ex 1) totalCount == 4
     *          countToGet == 1
     *       resultList == [[0],
     *                       [1],
     *                       [2],
     *                       [3]]
     *      
     * ex 2) totalCount == 4
     *       countToGet == 2
     *       resultList == [[0, 1], [1, 0],
     *                       [0, 2], [2, 0],
     *                       [0, 3], [3, 0],
     *                       [1, 2], [2, 1],
     *                       [1, 3], [3, 1],
     *                       [2, 3], [3, 2]]
     *
     * ex 3) totalCount == 4
     *       countToGet == 3
     *       resultList == [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0],
     *                       [0, 1, 3], [0, 3, 1], [1, 0, 3], [1, 3, 0], [3, 0, 1], [3, 1, 0],
     *                       [0, 2, 3], [0, 3, 2], [2, 0, 3], [2, 3, 0], [3, 0, 2], [3, 2, 0],
     *                       [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
     *
     * @param totalCount
     * @param countToGet
     * @return
     */
    public ArrayList<ArrayList<Integer>> getPermutation(int totalCount, int countToGet) {
        // 1. 조합 구하기
        ArrayList<ArrayList<Integer>> combinationList = getCombination(totalCount, countToGet);
        if (combinationList == null || combinationList.size() == 0) {
            return null;
        }

        // 2. 모든 조합에 대해 순열 구하기. 다시 말해, 각 조합에 대해 순서 바꾸기.
        ArrayList<ArrayList<Integer>> resultList = new ArrayList<ArrayList<Integer>>();
        int count = combinationList.size();
        for (int i=0; i<count; i++) {
            // 특정 조합에 대해 순열 구하기
            getPermutationCore(resultList, combinationList.get(i));
        }
       
        return resultList;
       
    }
   
   
    /**
     * 특정 조합에 대해 순열 구하기. 다시 말해, 각 조합에 대해 순서 바꾸기.
     * 넘겨받은 resultList 객체에 경우의 수를 담는다. resultList 가 사실상의 리턴값이다.
     *
     * ex 1) inputList ==  [0]
     *       resultList 객체에 [[0]] 추가
     *      
     * ex 2) inputList ==  [0, 1]
     *       resultList 객체에 [[0, 1], [1, 0]] 추가
     *
     * ex 3) inputList == [0, 1, 2]
     *       resultList 객체에 [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]] 추가
     *      
     * ex 4) inputList == [1, 2, 3]
     *          resultList 객체에 [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]] 추가
     *
     * @param resultList
     * @param inputList
     */
    private void getPermutationCore(ArrayList<ArrayList<Integer>> resultList, ArrayList<Integer> inputList) {
       
        // 인덱스리스트 구하기
        ArrayList<ArrayList<Integer>> suffledIndexList = getSuffledIndexList(inputList.size());
        if (suffledIndexList == null || suffledIndexList.size() == 0) {
            return;
        }
       
        int count = suffledIndexList.size();
        for (int i=0; i<count; i++) {
            ArrayList<Integer> oneResult = new ArrayList<Integer>();
           
            ArrayList<Integer> indexList = suffledIndexList.get(i);
            for (int j=0; j<indexList.size(); j++) {
                oneResult.add(inputList.get(indexList.get(j)));
            }
           
            resultList.add(oneResult);
        }
    }
   
   
    /**
     * 인덱스리스트 구하기
     *
     * ex 1) totalCount == 1 일 경우, [[0]] 리턴
     * ex 2) totalCount == 2 일 경우, [[0, 1], [1, 0]] 리턴
     * ex 3) totalCount == 3 일 경우, [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]] 리턴
     *
     * @param count
     * @return
     */
    private ArrayList<ArrayList<Integer>> getSuffledIndexList(int count) {
        ArrayList<ArrayList<Integer>> suffledIndexList = new ArrayList<ArrayList<Integer>>();
        shuffleRecursively(suffledIndexList, null, count, null);
        return suffledIndexList;
    }
   
   
    /**
     * 인덱스리스트 구하기 재귀메서드
     * 넘겨받은 resultList 객체에 경우의 수를 담는다. resultList 가 사실상의 리턴값이다.
     *
     * @param resultList
     * @param inputResult
     * @param totalCount
     * @param exceptList
     */
    private void shuffleRecursively(ArrayList<ArrayList<Integer>> resultList, ArrayList<Integer> inputResult, int totalCount, ArrayList<Integer> exceptList) {
        if (exceptList == null) {
            exceptList = new ArrayList<Integer>();
        }
       
        for (int i=0; i<totalCount; i++) {
            if (exceptList.contains(i)) {
                continue;
            }
           
            ArrayList<Integer> oneResult = null;
            if (exceptList.size() == 0) {
                oneResult = new ArrayList<Integer>();
            } else {
                oneResult = (ArrayList<Integer>) inputResult.clone();
            }
           
            if (oneResult.size() < totalCount) {
                oneResult.add(i);
               
                if (oneResult.size() == totalCount) {
                    resultList.add(oneResult);
                   
                } else if (oneResult.size() < totalCount) {
                    ArrayList<Integer> newExceptList = (ArrayList<Integer>) exceptList.clone();
                    newExceptList.add(i);
                   
                    shuffleRecursively(resultList, oneResult, totalCount, newExceptList);
                }
            }
        }
    }
}

[JAVA] HashMap Key To Array (HashMap KeySet To Array)

[JAVA] HashMap Key To Array (HashMap KeySet To Array)

해시맵(HashMap)의 키(Key, KeySet)을 배열(Array)로 바꾸는 코드.

KeySet To Array

String[] array = hashMap.keySet().toArray(new String[hashMap.size()]);

예제

    public static void main(String[] args) {
        HashMap<String, Integer> hashMap = new HashMap<String, Integer>();
        hashMap.put(“a”, 1);
        hashMap.put(“b”, 2);
        hashMap.put(“c”, 3);
        hashMap.put(“d”, 4);
       
        hashMap.put(“키1”, 5);
        hashMap.put(“키2”, 6);
        hashMap.put(“키3”, 7);
       
        hashMap.put(“키3”, 10);
        hashMap.put(“키3”, 20);
       
        String[] array = hashMap.keySet().toArray(new String[hashMap.size()]);
       
        int len = array.length;

        System.out.println(“len : ” + len);

        System.out.println();
        for (int i=0; i<len; i++) {
            System.out.println(i + ” : “+ array[i]);
        }
    }

결과

len : 7

0 : a
1 : b
2 : c
3 : d
4 : 키1
5 : 키3
6 : 키2


[Excel] Excel 2007 xlsx에 읽을 수 없는 내용이 있습니다. 이 통합 문서의 내용을 복구하시겠습니까?

[Excel] Excel 2007 xlsx에 읽을 수 없는 내용이 있습니다. 이 통합 문서의 내용을 복구하시겠습니까?

Excel 2007 (Microsoft Office 2007)을 사용하면서, 일반적인 PC에서 잘 열리는 엑셀 문서인데, 특정 PC에서 열면 <‘~~~~~.xlsx’에 읽을 수 없는 내용이 있습니다. 이 통합 문서의 내용을 복구하시겠습니까? 이 통합 문서의 원본을 신뢰할 수 있는 경우 [예]를 클릭하십시오.> 메시지가 발생하고 [예] 버튼을 클릭해야만 문서가 열리는 경우.

(주의 : 문서가 열리지 않는 경우가 아님. [예] 버튼을 클릭하면 문서가 잘 열리는 상황임.)

해결방법

1. 엑셀 실행  – 좌측 상단 마이크로소프트 오피스 아이콘 클릭 – 하단의 [Excel 옵션] 버튼 클릭 – [Excel 옵션] 창이 뜨면 좌측 메뉴의 [리소스] 클릭 – 우측 [Microsoft Office 진단 실행] 항목의 [진단(D)] 버튼 클릭

=> 별 효과 없었음.

2. 2007 Microsoft Office 제품군 SP3(서비스 팩 3) 설치

=> 설치 후 엑셀이 메시지 없이 깨끗하게 열리게 되었음.

Office 2007 SP3 x86 Hotfix171011 Final 2017.10.11 최종버전 다운로드 :  https://m.blog.naver.com/ilovegaz/221338214664

원 출처는 https://support.microsoft.com/ko-kr/help/20171010/security-update-deployment-information-october-10-2017 이라고 함.

참고로 Office 2007은 32 비트까지만 존재함(64비트는 2010부터 지원함). 따라서 현재 Office 2007을 사용하고 있다면 컴퓨터 비트수와 상관없이 설치하면 됨.

참고사이트 1 : https://saysensibility.tistory.com/m/1001?category=740679

참고사이트 2 : https://m.blog.naver.com/ilovegaz/221338227086

[MySQL] MySQL root 패스워드 재설정 방법

[MySQL] MySQL root 패스워드 재설정 방법

MySQL 에서 root 계정의 패스워드/비밀번호를 잊어버렸을 때/분실했을 때/까먹었을 때/기억나지 않을 때 패스워드/비밀번호를 재설정/다시 설정하는 방법.

1. 서비스 중지

우분투 : service mysql stop

CentOS6 : service mysqld stop

2. 인증 생략 옵션 및 안전 모드로 데몬 실행

/usr/bin/mysqld_safe –skip-grant-tables &

3. 콘솔 접속

/usr/bin/mysql -u root mysql

4. 패스워드 변경

Mysql5.7 버전 미만

UPDATE mysql.user SET password=PASSWORD(‘패스워드’) WHERE user=’root’;

FLUSH PRIVILEGES;

quit

Mysql5.7 버전 이상

UPDATE mysql.user SET authentication_string=PASSWORD(‘패스워드’) WHERE user=’root’;

FLUSH PRIVILEGES;

quit

5. 서비스 재시작

우분투 : service mysql restart

CentOS6 : service mysqld restart

6. root 계정으로 로그인

변경한 패스워드를 입력하여 로그인 되면 성공.

mysql -u root -p

[AWS] 소유중인 도메인을 AWS EC2 서비스로 연결하기 (AWS 도메인 연결 방법)

[AWS] 갖고 있는 도메인을 AWS EC2 서비스로 연결하기 (AWS 도메인 연결 방법)

구입한 도메인이 있을 경우, 해당 도메인 주소로 접속했을 때 AWS EC2 서비스로 연결하는 방법이다.

조건 1) 소유하고 있는 도메인이 있음

조건 2) AWS EC2 에 띄워져있는 서비스가 있음

1. Route 53 (http://console.aws.amazon.com/route53) 에 접속한다.

좌측 메뉴의 [호스팅 영역] 클릭 – 화면의 [호스팅 영역 생성] 버튼을 클릭한다.

 

2. [도메인 이름] 항목에 갖고 있는 도메인 이름을 적는다.

참고로 필자는 ddoc.kr 이라는 도메인을 갖고 있다.

[유형]은 [퍼블릭 호스팅 영역]을 선택한다.

이어서 [호스팅 영역 생성] 버튼을 클릭한다.

 

3. 생성된 호스팅 영역(도메인 이름)을 클릭한다.

 

4. 레코드 목록을 볼 수 있다.

[값/트래픽 라우팅 대상] 이라고 해서 아래처럼 4개의 주소가 보일 것이다.

이 값들은 도메인 호스팅 사이트에 입력해야 하는 네임서버 값들이다.

 

예를 들어 가비아에 도메인을 등록했다면, [네임서버] 항목의 [설정] 버튼을 클릭하고 해당 네임서버 4개를 기입하면 된다.

아래 스크린샷을 참고할 것.

5. 다시 레코드 목록 화면으로 돌아와서, [레코드 생성] 버튼을 클릭한다.

6. [라우팅 정책] 중에서 [단순 라우팅] 을 선택하고 [다음] 버튼을 클릭한다.

 

7. [단순 레코드 정의] 버튼을 클릭한다.

 

8. [레코드 이름] 항목은 비워둔다. 서브 도메인을 사용할 경우만 기입하면 된다.

[값/트래픽 라우팅 대상] 콤보박스는 [레코드유형에 따라 IP 주소 또는 다른 값]을 선택하고, IP주소를 입력한다. (포트번호는 넣을 수 없음)

[레코드 유형은] [A – IPv4 주소 및 일부 AWS 리소스로 트래픽 라우팅]을 선택한다.

[TTL(초)]는 기본값 그대로 둔다.

이어서 [단순 레코드 정의] 버튼을 클릭한다.

 

9. [레코드 생성] 버튼을 클릭한다.




 참고사이트 : http://makebct.net/aws-%EC%99%B8%EB%B6%80-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%97%B0%EA%B2%B0-%EB%B0%A9%EB%B2%95-1/?cat=989/

[AWS] 아마존 AWS EC2 root 계정 접속하는 방법

[AWS] 아마존 AWS EC2 root 계정 접속하는 방법

EC2 (Elastic Compute Cloud) 의 기본 계정명은 ec2-user 이다.

초기에는 root 계정의 비밀번호가 설정되어있지 않으므로, ec2-user 계정으로 접속해서 root 계정의 패스워드를 세팅하면 된다.

1. root 계정의 새 패스워드 설정

sudo passwd root

2. root 계정으로 접속

su

참고사이트 : https://goddaehee.tistory.com/193

[SpringBoot] 스프링부트 포트 8080 에서 80 으로 변경하는 방법

[SpringBoot] 스프링부트 포트 8080 에서 80 으로 변경하는 방법

스프링부트는 특별한 설정을 하지 않았을 경우 기본 포트가 8080 이다.

application.properties 파일에 아래 내용을 추가한다.

server.port=80

또는 스프링부트 프로젝트를 기동할 때 -Dserver.port 옵션을 부여하면 된다고 한다.

java -Dserver.port=80 -jar spring-boot-application.jar

참고로 80 포트는 root 계정으로 기동해야 정상적으로 기동된다.

참고사이트 : https://stackoverrun.com/ko/q/10724065

[Android] 안드로이드에서 javascript(js) 함수 호출

[Android] 안드로이드에서 javascript(js) 함수 호출

안드로이드에서 자바스크립트 함수 호출 방법.

WebView webView = (WebView) findViewById(R.id.webView);
if (webView != null) {
    webView.loadUrl(“javascript:myFunctionName()”);
}


[Javascript] iframe innerHTML

[Javascript] iframe innerHTML

var x = document.getElementsByTagName(“iframe”)[0];

​var y = null;

if (x.contentWindow != null) {

    y = x.contentWindow;

} else if (x.contentDocument != null) {

    y = x.contentDocument;

}

if (y != null && y.document != null) {

    y = y.document;

}

y.getElementsByTagName(“html”)[0].innerHTML = “contents”;

위의 코드를 조금 수정해서, 아이프레임의 document 를 가져오는 코드 함수화

function getFrameDocument(_iframeId) {

    var frameObj = document.getElementById(_iframeId);

    var frameDoc = null;

    if (frameObj.contentWindow != null) {

        frameDoc = frameObj.contentWindow;

    } else if (frameObj.contentDocument != null) {

        frameDoc = frameObj.contentDocument;

    }

    

    if (frameDoc != null && frameDoc.document != null) {

        frameDoc = frameDoc.document;

    }

    

    return frameDoc;

}

이어서 html 태그 내의 내용을 innerHTML 함수로 가져오기

var frameDoc = getFrameDocument(“draftActionFrame”);

            

if (frameDoc != null && frameDoc.getElementsByTagName(“html”) != null) {

    alert(frameDoc.getElementsByTagName(“html”)[0].innerHTML);

}

[JAVA] reviseAmpersand (이미 “&”인 경우를 제외하고, “&” 기호를 “&”로 치환)

[JAVA] reviseAmpersand (이미 “&amp;”인 경우를 제외하고, “&” 기호를 “&amp;”로 치환)

ex 1) &abcde& => &amp;abcde&amp;

ex 2) &abcde&amp;&&& => &amp;abcde&amp;&amp;&amp;&amp;

    public static void main(String[] args) {
        String strTest1 = “&abcde&”;
        strTest1 = reviseAmpersand(strTest1);
        System.out.println(“strTest1 : ” + strTest1);

        // 결과 : strTest1 : &amp;abcde&amp;
        
        String strTest2 = “&abcde&amp;&&&”;
        strTest2 = reviseAmpersand(strTest2);
        System.out.println(“strTest2 : ” + strTest2);

        // 결과 strTest2 : &amp;abcde&amp;&amp;&amp;&amp;
    }
   
    /**
     * 이미 “&amp;”인 경우를 제외하고, “&” 기호를 “&amp;”로 치환한다.
     *
     * @param str
     * @return
     */
    public static String reviseAmpersand(String str) {
        if (str == null || str.length() == 0) {
            return “”;
        }
       
        String oneChar = “”;
        StringBuffer buff = new StringBuffer();
        int len = str.length();
        for (int i=0; i<len; i++) {
            oneChar = str.substring(i, i+1);
            if (oneChar.equals(“&”) && (i+5 > len || !str.substring(i, i+5).equals(“&amp;”))) {
                buff.append(“&amp;”);
                continue;
            }
           
            buff.append(oneChar);
        }
       
        return buff.toString();
    }

[JAVA] Image File to Base64 String (이미지 파일을 Base64 문자열로 변환)

[JAVA] Image File to Base64 String (이미지 파일을 Base64 문자열로 변환)

    String strBase64 = “”;

   

    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;
           
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
            } catch (Exception e) {
        }
    }

[HTML] Base64 이미지를 HTML img 태그로 표시하기

[HTML] Base64 이미지를 HTML img 태그로 표시하기

html 파일 내용에 <img src=”data:image/png;base64,베이스64코드”> 형식으로 쓰면 그림이 된다.

예를 들어 아래와 같이 쓴다.

<img src=”data:image/png;base64,/9j/4AAQSkZJRgABAQEASABIAAD/4SuURXhpZgAATU0AKgAAAAgACAEaAAUAAAABAAAIegEbAAUAAAABAAAIggEoAAMAAAABAAIAAAEyAAIAAAAUAAAIigE7AAIAAAAHAAAInodpAAQAAAABAAAIppydAAEAAAAOAAARWuocAAcAAAgMAAAAbgAAEWgc6gAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAABAAAASAAAAAEyMDA5OjAzOjEyIDEzOjQ4OjI4AENvcmJpcwAAAAqQAAAHAAAABDAyMTCQAwACAAAAFAAAETCQBAACAAAAFAAAEUSSkQACAAAAAzE3AACSkgACAAAAAzE3AACgAAAHAAAABDAxMDCgAQADAAAAAf//AACgAgAEAAAAAQAAAvygAwAEAAAAAQAAAj3qHAAHAAAIDAAACSQAAAAAHOoAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyMDA4OjAyOjExIDExOjMyOjQzADIwMDg6MDI6MTEgMTE6MzI6NDMAAABDAG8AcgBiAGkAcwAAAAAGAQMAAwAAAAEABgAA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ZDpmYWY1YmRkNS1iYTNkLTExZGEtYWQzMS1kMzNkNzUxODJmMWIiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyI+PGRjOmNyZWF0b3I+PHJkZjpTZXEgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj48cmRmOmxpPkNvcmJpczwvcmRmOmxpPjwvcmRmOlNlcT4NCgkJCTwvZGM6Y3JlYXRvcj48L3JkZjpEZXNjcmlwdGlvbj48L3JkZjpSREY+PC94OnhtcG1ldGE+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIDw/eHBhY2tldCBlbmQ9J3cnPz7/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAEfAX4DASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA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”>

 

참고사이트 : https://pilot376.tistory.com/3

[Linux/Ubuntu] 우분투 사용자 생성, 사용자 조회, 사용자 삭제

[Linux/Ubuntu] 우분투 사용자 생성, 사용자 조회, 사용자 삭제

우선 root로 로그인한다.

1. 사용자 만들기 (계정 생성)

sudo useradd -m [사용자계정]

ex) sudo useradd -m user01

useradd 명령의 -m 옵션을 사용하면 사용자의 홈 디렉토리도 함께 만든다.

2. 사용자 조회 (계정 조회)

모든 사용자 조회 : cat /etc/passwd

모든 사용자 조회 (아이디만) : cut -f1 -d: /etc/passwd

useradd 를 통해서 추가한 사용자만 조회 : grep /bin/bash /etc/passwd

useradd 를 통해서 추가한 사용자만 조회 (아이디만) : grep /bin/bash /etc/passwd | cut -f1 -d:

3. 특정사용자로 로그인 (해당 계정으로 로그인)

su – [사용자계정]

ex) su – user01

특정 사용자 아이디(여기서는 user01)로 로그인하는 명령어.

su 뒤에 대시(-)를 붙여줘야 환경변수를 물고 제대로 로그인된다.

참고로 su와 su – 는 다르다. su – 를 써야 환경변수와 워킹디렉토리가 변경된다. (참고 : https://storycompiler.tistory.com/44)

4. 특정사용자 삭제 (계정 삭제)

userdel [사용자계정]

ex) userdel user01

사용자를 잘못 생성했을 경우 위 명령어로 삭제 가능하다.

만약 “userdel: user [사용자계정] is currently logged in” 이라는 메시지가 나오고 삭제가 안되는 경우 아래 명령어를 사용하면 된다.

userdel -r -f [사용자계정]

ex) userdel -r -f user01

참고사이트 : https://withcoding.com/101

[MySQL/MariaDB] 문자열 결합, 문자열 합치기

[MySQL/MariaDB] 문자열 결합, 문자열 합치기

오라클에서는 파이프(“||”)를 이용해서 문자열을 결합하면 되지만, MySQL에서는 CONCAT이라는 함수를 사용해야 한다.

오라클 문자열 결합, 문자열 합치기

SELECT ‘a’ || ‘b’ || ‘c’ FROM DUAL;

=> abc

MySQL/MariaDB 문자열 결합, 문자열 합치기

SELECT CONCAT(‘a’, ‘b’, ‘c’);

=> abc

[MySQL/MariaDB] MySQL의 dual (오라클의 dual)

[MySQL/MariaDB] MySQL의 dual (오라클의 dual) 

MySQL은 dual이 없다.

만약 오라클에서 실행한 쿼리가 “SELECT 1+1 FROM DUAL;” 이라면,

MySQL에서는 “SELECT 1+1;” 라고 쓰면 충분하다.

확인해보니 MariaDB에서는 “SELECT 1+1 FROM DUAL;” 도 작동하고 “SELECT 1+1;” 도 작동한다.

[MySQL/MariaDB] 현재시간 가져오기 (오라클의 sysdate)

[MySQL] 현재시간 가져오기 (오라클의 sysdate)

오라클에서 현재일자 가져오기

SELECT sysdate FROM DUAL;

=> 20/09/09

오라클에서 현재시간(현재일시) 가져오기

SELECT to_char(sysdate, ‘yyyymmdd hh24miss’) FROM DUAL;

=>20200909 111105

MySQL/MariaDB에서 현재시간(현재일시) 가져오기

select NOW();

=> 2020-09-09 11:12:11

MySQL에서 현재시간(현재일시)을 가져올 때 SYSDATE()를 쓸 수도 있는데 NOW()를 쓰는 것을 권장한다.

NOW()는 하나의 쿼리 안에서 동일한 값을 리턴하지만 SYSDATE()는 쿼리 실행시점에 따라 값이 바뀐다.

예를 들어 매우 느린 쿼리가 있어서 레코드를 읽을 때 1시간이 걸린다면, SYSDATE() 값은 하나의 쿼리 안에서도 계속 바뀔 수 있다.

(참고사이트 : http://intomysql.blogspot.com/2010/12/sysdate-now.html)

[DBeaver] 오토커밋(Auto-commit) 해제 방법

[DBeaver] 오토커밋(Auto-commit) 해제 방법

DBeaver로 MsSQL을 붙어서 몇 가지 작업을 했는데 오토커밋(Auto-commit)이 기본적으로 켜져 있었다.

방법 : DBeaver 상단 메뉴의 [윈도우(w)] – [설정] – 환경 설정 창이 뜨면 좌측 트리의 [연결 유형] – Auto-commit by default 체크박스를 해제해주면 된다.

참고사이트 : https://pro-pennek.tistory.com/entry/DBeaver-Auto-commit-%EC%98%A4%ED%86%A0%EC%BB%A4%EB%B0%8B-%EC%84%A4%EC%A0%95-%EB%B0%8F-%ED%95%B4%EC%A0%9C-%EA%B8%80%EA%BC%B4-%EB%B3%80%EA%B2%BD

[DBeaver] 유용한 무료 DB 툴 dbeaver (MySQL, MsSQL, PostgreSQL 등)

[DBeaver] 유용한 무료 DB 툴 dbeaver (mysql, mssql 등)

엄청나게 다양한 SQL 벤더를 제공하고 있어서 MySQL, MsSQL, PostgreSQL 등 안되는 것 없이 다 된다.

JAVA jdk 1.8 버전에서 구동된다.

https://dbeaver.io/