반응형

내가 순서대로 동기처리하고 싶었던 코드

ajax1
code1
code2
ajax2
code3

위의 로직이 이처럼 순차적으로 처리되길 바랐음...

promise를 사용하여 아래와 같이 짜보았다.

//promise 생성 시 resolve, reject 콜백함수를 인자로 넘김.
//작업 성공 시 resolve를, 실패 시 reject를 호출하면 됨.
let func1 = new Promise((resolve,reject)=>{ 
	ajax1
	ajax1 성공 시 resolve(); 호출하고 code1
});

//promise 결과를 사용하기.
//promise.then은 콜백이 resolve()인 경우에,
//promise.catch는 reject()인 경우에 실행하게된다.
func1.then({
	code2
	ajax2
	ajax2 성공 시 code3
}).catch({})

 

아래는 사용한 코드 예시임.

let func1 = new Promise((resolve,reject)=>{ //new Promise() 메서드로 생성되면 대기(pending) 상태                           
	$.ajax({
		url: "/api/test/get1",
		type: "get",
		async : false, //동기처리방식. 응답 완료 후 다음 로직 실행
		data: $('#data').val(),
		success: function (param) {
			let data = param.data;
			console.log("code1");
			resolve(data); //성공 시 resolve 콜백으로 리턴 값을 보내면 이행(fulfilled)상태
		},
		error : function(){                      
			reject(); //이행실패시 reject 콜백.
		}
	});
});

func1.then(function(data){ //promise.then : promise의 resolve 를 받는다.
	console.log("code2");
	$.ajax({
		url: "/api/test/get2",
		type: "get",
		async : false,
		success: function (param) {
        	console.log("code3");
 		}
	});
}).catch({console.log("실패"!)}); //catch : promise의 reject 를 받는다.
반응형
반응형

 jQuery에서 $를 alias로 사용하지 않도록 하는 방법

//jquery의 alias변경
var $aa = jQuery.noConflict();

$aa.ajax({});

$aa('#test').html("test입니다");

다른 라이브러리나

다른 버전의 jquery와의 충돌을 피할 수 있다.

반응형
반응형

reverse proxy ?

- 외부에서 내부 서버가 제공하는 서비스에 접근할 경우, proxy server(nginx)를 통해서 들어오는 방식
- 클라이언트 -> 프록시 -> 서버

reverse proxy 왜 사용?

- 사용자 요청 분산 역할(로드밸런싱)
- 서버로 직접 접근하는 것을 막는다. (IP및 포트 숨김 가능) 

예) http://www.test.com/web1 접근 시 1.2.3.4:8080 으로,                                                                            http://www.test.com/web2 접근시 1.2.3.4:8081 로 연결해줄 수 있게 함

forward proxy는?

- 일반적인 프록시
- 클라이언트 -> 프록시 -> 서버 
- 정해진 사이트만 연결하게 설정하는 등 웹 사용 환경을 제한할수 있으므로 보안이 매우 중요한 기업 환경등에서 많이 사용함

 

NGINX에서 설정하기

설정파일 : /etc/nginx/sites-enabled/default 

파일을 열어보면 대략 이렇게 생겼다.

기본적인 설정은 아래와 같다.

location / { //경로 설정
     proxy_pass http://123.45.678.90:8080;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header HOST $http_host;
}
  • proxy_pass
    기본 설정. 들어온 요청을 어디로 포워드 해줄건지 설정함.
    현재 서버에 / 로 시작하는 path로 접근하면, http://123.456.78.90:8080 으로 접근하게 됨.
  • proxy_set_header
    프록시 서버에 특정 헤더를 전달하기 위한 설정
  • X-Forwarded-For
    HTTP 프록시를 통해 웹 서버에 접속하는 클라이언트의 IP 주소를 식별하는 표준 헤더
    클라이언트와 서버 중간에서 트래픽이 프록시나 로드 밸런서를 거치면, 서버 접근 로그에는 프록시나 로드 밸런서의 IP 주소만을 담고 있다. 
    클라이언트의 원 IP 주소를 보기위해 X-Forwarded-For 요청 헤더가 사용된다.
    Apache는 ProxyPass를 사용할 경우 기본으로 X-Forwarded-For 헤더를 구성하지만 nginx는 직접 구성해줘야 한다.
  • $proxy_add_x_forwarded_for
    $http_x_forwarded_for,$remote_addr 와 동일함
    클라이언트의 IP 주소를 담고있는 $remote_addr 를 X-Forwarded-For Header의 값으로 추가해 줌
  • HOST $http_host;
    HTTP Request 의 Host 헤더값
    http 요청이 들어 왔을 시 호스트 명

 

location /web1 {
     proxy_pass http://1.2.3.4:8080;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header HOST $http_host;
}

location /web2 { 
     proxy_pass http://1.2.3.4:8081;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header HOST $http_host;
}
반응형
반응형
  • tomcat 버전 : 8.5.55

예를 들어 http://localhost:8080 가 웹서버 url인데

http://localhost:8080/IMAGES 로 접근하면

프로젝트 내부가 아닌 D:\IMAGES와 같은 외부 경로 폴더로 연결되게 하고 싶다?


tomcat 디렉터리의  conf 밑의 server.xml 파일을 수정한다.

Service 하위에 Host 라고 된 부분 밑에 한 줄 추가해준다.

<Context docBaase="실제외부경로" path="접근URL" reloadable="false">

 <Service name="MyService">
      <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" maxPostSize = "-1"/>
      <Engine name="MyService" defaultHost="localhost">
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
      </Realm>
      <Host name="localhost" appBase="mchch" unpackWARs="true" autoDeploy="true">
      <!-- Host 밑에 추가해준다.-->
        <Context docBase="D:\IMAGES" path="/IMAGES" reloadable="false"/>
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
    </Engine>
  </Service>

설정 저장 후 톰캣 재시작.

* reloadable : true면 15초마다 루트경로의 class파일 변경여부를 확인하고 자동으로 재가동하여 반영한다. 일반적으로 개발환경에선 true, 운영환경에선 false로 하는 듯함.

* 결과 : http://localhost:8080/IMAGES/test.jpg 로 접근하면 D:\IMAGES\test.jpg 를 볼 수 있음.

 

반응형
반응형

SHA256 알고리즘을 사용한 해시함수.

메시지 다이제스트를 문자열로 return 하는 경우의 메소드와

바이트 배열로 return 하는 두 가지 경우를 생성함.

public class Sha256EncryptUtil {

public static String ShaEncoder(String userPw) {
    try {
	//알고리즘은 SHA256으로 하여 MessageDigest 객체 생성
      MessageDigest digest = MessageDigest.getInstance("SHA-256");
      //해시된 데이터는 바이트 배열의 바이너리 데이터임.
      byte[] hash = digest.digest(userPw.getBytes(StandardCharsets.UTF_8));

      StringBuilder hexString = new StringBuilder();
	  //바이트 배열을 16진수(hex) 문자열로 변환
      for (byte b : hash) {
      	//byte 8비트 ->int 32bit 형변환 시 앞의 18비트가 19번째 비트와 같은 값으로 채우는데 
        //이 경우에 원본 값과 다른 경우가 되는 것을 방지하기 위한 연산
        String hex = Integer.toHexString(0xff & b);
        if (hex.length() == 1) {
          hexString.append('0');
        }
        hexString.append(hex);
      }
      return hexString.toString();
    } catch (Exception ex) {
      throw new RuntimeException(ex);
    }
}


public static byte[] shaEncoderByte(String message){
//이 메소드는 바이트배열을 16진수 문자열로 변환하지 않음
    try {
      MessageDigest digest = MessageDigest.getInstance("SHA-256");
      byte[] hash = digest.digest(message.getBytes(StandardCharsets.UTF_8));
      return hash;
    }catch(Exception ex){
      throw new RuntimeException(ex);
    }

  }
}
반응형
반응형

우선 위경도 표현에는 두 가지 방식이 있다..

  • 소수점표현(DD,Decimal Degree) : 예) 37.397
  • 도분초 표현(DMS, Degree Minutes Seconds) 예) 37º 23' 49.2"

소수점 표현같은 경우에는 구글지도에서 쉽게 확인 가능..


1. 소수점 표현 방식 -> DMS 표현방식 변환

예) 37.397 을 DMS 표현으로 변환

  • 도 :  소수점 좌표 값의 정수(37)
  • 분 : 37을 제외한 0.397 X 60 = 23.82 에서 소수점 앞의 정수(23)
  • 초 : 0.82 X 60 = 49.2 에서 소수점 포함 앞의 4자리(49.2)

=> 37º 23' 49.2"

//소수점 표현 위도,경도를 DMS 표현으로 변환
public HashMap<String ,Object> getDmsByLatLon(Object data) throws Exception{
//data = 37.397

    HashMap<String,Object> result = new HashMap<>();
    
    try {
    
      String[] dataArray = data.toString().split("\\.");
      //도 : 소수점 좌표 값의 정수
      String dataDegree = dataArray[0];

      String dataMinutesFull = String.valueOf(Double.parseDouble("0." + dataArray[1]) * 60);
      //분
      String dataMinutes = dataMinutesFull.split("\\.")[0];
      
      
      //초
      String dataSeconds;
      if(String.valueOf(Double.parseDouble("0." + dataMinutesFull.split("\\.")[1]) * 60).length()<5){
        dataSeconds = String.valueOf(Double.parseDouble("0." + dataMinutesFull.split("\\.")[1]) * 60);
      }else {
        dataSeconds = String.valueOf(Double.parseDouble("0." + dataMinutesFull.split("\\.")[1]) * 60).substring(0, 5);
      }
      
      result.put("degree", dataDegree);
      result.put("minutes", dataMinutes);
      result.put("seconds", dataSeconds);

    }catch(Exception e){
      e.printStackTrace();
    }
    
    return result;
}
//result = {seconds=49.19, minutes=23, degree=37}

 

 

2. DMS  표현 방식 ->  소수점 표현 방식 변환

예) 37º 23' 49.2" 를 DD 표현으로 변환하기

식은 다음과 같다..

도 + ( 분 + (초 / 60 ) ) / 60

37 + ( 23 + (49.2/60) ) /60 = 37.397

double latDD = MaxDeg + (latMin + latSec / 60) / 60;

 

 

3. 두 좌표간의 거리

두 좌표간의 거리를 구하려면 두 좌표는 DMS표현 방식이어야 함..

도는 도, 분은 분, 초는 초끼리 연산을 한다.

  37° 33′ 58.97″ N , 126° 58′ 39.78″ E (서울시청)
- 37° 33′ 56.08″ N , 126° 58′ 41.10″ E (서울광장)

= 0 ° 0 ′ 2.89" , 0 ° 0 ′ -1.32"

//지리좌표간 두 점의 거리 계산을 위한 DMS연산
public HashMap<String, Double> DMSCalculationForDistance(Double targetDeg, Double targetMin, Double targetSec, Double opDeg, Double opMin, Double opSec)throws Exception{
    HashMap<String, Double> result = new HashMap<>();
    result.put("resultDeg",targetDeg-opDeg);
    result.put("resultMin",targetMin-opMin);
    result.put("resultSec",targetSec-opSec);

    return result;
}


//DMS 연산 결과로 거리 구하기
public Double getDistanceByDms(Double latDeg,Double latMin, Double latSec,Double lonDeg, Double lonMin, Double lonSec) throws Exception{
    Double result;
    result = Math.sqrt(Math.pow(latDeg*88.9036+latMin*1.4817+latSec*0.0246,2) + Math.pow(lonDeg*111.3194+lonMin*1.8553+lonSec*0.0309,2));
    return result;
}

 

4. 특정지점에서 특정 거리의 좌표 구하기

이 경우도 DMS 표현방식의 좌표로 계산하였다.

예를 들어   37° 33′ 58.97″  , 126° 58′ 39.78″ 좌표에서 서쪽으로 5km 떨어진 지점의 좌표를 구한다거나 하는 경우,

5km 만큼의 경도 수치를 구해서 빼준다.

동쪽으로 5km 떨어진 지점이라면  수치를 더해주고, 북쪽으로 5km 떨어진 지점이라면 5km만큼의 위도 수치를 더해준다.

위경도 1분, 1초 값은 아래 수치로 계산하였다.

  • 위도 1분 = 1.85km, 1초 = 30.8m
  • 경도 1분 = 1.48km, 1초 = 25m
 //위도 5km = 약 2분 42.2초(1분=1.85km, 1초=30.8m로 계산)
int latDistanceMin = 2;
Double latDistanceSec = 42.2D;

//경도 5km = 약 3분 22.4초(1분=1.48km, 1초=25m로 계산)
int lonDistanceMin = 3;
Double lonDistanceSec = 22.4D;
//DMS 표현 위경도에 특정 거리를 더하는 연산
public HashMap<String,Double> latlonCalDistance (Double targetDeg, Double targetMin, Double targetSec, Double opDeg, Double opMin, Double opSec,String operator) throws Exception{
    HashMap<String,Double> result = new HashMap<>();
    Double resultSec;
    Double resultMin;
    Double resultDeg;

    //더하기 연산
    if(operator =="+"){
      if(targetSec+opSec>=60){
        resultSec = targetSec+opSec-60;
        resultMin = targetMin+opMin+1;
        if(resultMin >=60){
          resultMin = resultMin -60;
          resultDeg = targetDeg + opDeg + 1;
        }else{
          resultDeg = targetDeg + opDeg;
        }
      }else{
        resultSec = targetSec+opSec;
        resultMin = targetMin+opMin;
        if(resultMin >=60){
          resultMin = resultMin -60;
          resultDeg = targetDeg + opDeg + 1;
        }else{
          resultDeg = targetDeg +opDeg;
        }
      }

    //빼기 연산
    }else{
      if(opSec > targetSec){
        resultSec = 60-opSec+targetSec;
        resultMin = targetMin-1;
        if(opMin > targetMin){
          resultMin = 60-opMin+resultMin;
          resultDeg = targetDeg -1 - opDeg;
        }else{
          resultMin = resultMin-opMin;
          resultDeg = targetDeg - opDeg;
        }
      }else{
        resultSec = targetSec - opSec;
        if(opMin > targetMin){
          resultMin = 60-opMin+targetMin;
          resultDeg = targetDeg -1 - opDeg;
        }else{
          resultMin = targetMin-opMin;
          resultDeg = targetDeg - opDeg;
        }
      }
    }
    result.put("resultDeg",resultDeg);
    result.put("resultMin",resultMin);
    result.put("resultSec",resultSec);
    return result;
}

 


참고 링크

 

 

위도 경도 계산법

위도 경도를 아래 공식에 대입해서 d(거리)값을 구한 상태 입니다. ==========점(x1, y1)과 직선(ax+by+c=0) 사이의 거리(d) 구하는 공식 ====================== d = |ax1 + by1 + c | / sqrt(a^2 + b^2) =======..

lovestudycom.tistory.com

 

 

지리좌표 거리 - 위키백과, 우리 모두의 백과사전

지리좌표 거리(Geographical distance)는 경위도좌표계를 기반으로 하는 좌표체계에서 얻어지는 두 지점의 좌표로 부터 측정되는 거리측량을 가리킨다. GPS로 부터 좌표값을 얻어 두 지점간의 지리좌

ko.wikipedia.org

 

반응형
반응형
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.springframework.stereotype.Component;

public class AES256 {
	//AES256은 256bit=32byte의 암호화 키가 필요함.
    private final String key = "1234567890123456789012"; 
    private final String iv = key.substring(0, 16); // 16byte의 초기화벡터값

//암호화메소드
    public String encrypt(String plainText) throws Exception {
    	//암호화 모드는 CBC를, 패딩은 PKCS5을 사용
        Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
        IvParameterSpec ivParamSpec = new IvParameterSpec(iv.getBytes());
        c.init(Cipher.ENCRYPT_MODE, keySpec, ivParamSpec);

        byte[] encrypted = c.doFinal(plainText.getBytes("UTF-8"));
        //base64로 인코딩
        return String(Base64.encodeBase64(encrypted));
    }

//복호화메소드
    public String decrypt(String cipherText) throws Exception {
        Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
        IvParameterSpec ivParamSpec = new IvParameterSpec(iv.getBytes());
        c.init(Cipher.DECRYPT_MODE, keySpec, ivParamSpec);

        byte[] decodedBytes = Base64.decodeBase64(cipherText);
        byte[] decrypted = c.doFinal(decodedBytes);
        return new String(decrypted, "UTF-8");
    }

}

 

* 패딩

암복호화 할 때 인풋이 암호 블럭 사이즈의 배수와 맞지 않는 경우 배수에 맞춰 빈공간을 채우는 것을 패딩이라고 함.

* IV

CBC모드에서 최초의 평문블록을 암호화 할 때 '한 단계 앞의 암호문블록' 역할을 할 비트열


패딩 참고

 

OKKY | PKCS#5 패딩과 PKCS#7 패딩의 차이점

암복호화 할 때 인풋이 암호 블럭 사이즈의 배수와 맞지 않으면 배수에 맞춰 빈공간을 채워주게 됩니다. 이 채워주는 방법을 패딩이라고 부르는데 여기서 PKCS#5와 PKCS#7의 차이를 설명하겠습니

okky.kr

 

반응형
반응형

objectMapper 사용 중 다음과 같은 에러가 났다.

com.fasterxml.jackson.core.JsonParseException: Unexpected character ('s' (code 115)): was expecting double-quote to start field name

 

에러난 코드부분은 이부분.

String timestring = {startTime=08:00, endTime=20:00}

objMapper.readValue(timestring,HashMap.class)

 

결론부터 말하자면 readValue의 파라미터로 JSON형태의 String과 Classtype을 넣어줘야함.

나는 JSON형태의 스트링을 넣지 않았기 때문에 에러가 남.



저 timestring 자리가 JSON형태의 String이 들어가는 자리

objMapper.readValue(timestring,HashMap.class)
//objMapper.readValue(JSONString,변환할type)

objMapper.readValue가 JSON형태의 String을 원하는 CLASS 타입으로 변환할 수 있도록 하는데

JSON 형태의 String 은 {"key이름" : "value"} 으로 생겼다.
근데 내가 넣은 String은  {startTime=08:00, endTime=20:00} 이렇게 생겼으니...

double quote (쌍따옴표)를 찾는데 없어서 에러가 난 것...

반응형
반응형

JSON 데이터를 dto 객체로 맵핑할 때 선언되지 않은 property가 있는경우 

이런 에러가 뜬다...

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException

 

예를 들어 json 데이터에는 name, color, size 프로퍼티가 있는데

{
    "name" : "apple",
    "color" : "green",
    "size" : "small"
}

dto 클래스에는 size 프로퍼티가 없다? 그러면 에러 나는 거임..

public static class fruitDto {
    public String name;
    public String color;
}

 

해결 방법 : 

@JsonIgnoreProperties(ignoreUnknown = true)

를 추가 해주자.

 

 

반응형
반응형

 빌드 중 아래 에러가 뜨는 경우

package javax.xml.bind does not exist

 

java 11을 이용중인경우에 뜨는 듯 하다.

java 11에서는 JavaEE 와  CORBA 모듈이 포함되어 있지 않다고 한다.

해결법 :

java 8 버전을 이용하거나

java11을 계쏙 이용하고 싶으면 아래처럼 해당 모듈을 손수 추가해 주면 되겠다.

<dependency>
  <groupId>javax.xml.bind</groupId>
  <artifactId>jaxb-api</artifactId>
  <version>2.3.0</version>
</dependency>
<dependency>
  <groupId>com.sun.xml.bind</groupId>
  <artifactId>jaxb-core</artifactId>
  <version>2.3.0</version>
</dependency>
<dependency>
  <groupId>com.sun.xml.bind</groupId>
  <artifactId>jaxb-impl</artifactId>
  <version>2.3.0</version>
</dependency>

 

java8을 사용중인데 위와 같은 에러가 뜬다면

cmd에서 java -version 으로 자바 버전을 확인해보자... 

나는 java11과 java8이 둘 다 설치되어 있었는데 java11로 잡혀있어서 에러가 떴던 것이었다... 

 


참고 페이지 

 

Java 11 package javax.xml.bind does not exist

I'm trying to deserialize XML data into a Java content tree using JAXB, validating the XML data as it is unmarshalled: try { JAXBContext context = JAXBContext.newInstance("com.acme.foo");

stackoverflow.com

 

반응형

+ Recent posts