redis를 이용해서 httpSession을 공유하는 방식이 좀 더 많이 활용되지만,

 

이미 mongoDB를 사용하고 있다면, mongoDB를 활용한 session공유가 더 좋을 수 있다.

특히 요즘엔 HDD대신에 SSD를 많이 사용하므로  SSD기반의 mongoDB라면 redis에 가까운 속도를 낼 것으로 예상된다.

 

 

spring-boot에서 사용하려면

gradle방식의 경우 dependency를 아래와 같이 추가하고

      compile('org.springframework.session:spring-session-data-mongodb')

 

 

 

HttpSessionConfig 클래스만 만들면 된다. ( default가 30분이라서 1시간으로 바꾼 예제이다. )

@EnableMongoHttpSession(maxInactiveIntervalInSeconds = 3600) //default 1800
public class HttpSessionConfig {
    @Bean
    public JdkMongoSessionConverter jdkMongoSessionConverter() {
        return new JdkMongoSessionConverter(Duration.ofMinutes(60)); //default 30
    }
}
Posted by yongary
,

1. char -> AsciiCode
   'A'.charCodeAt()  => 65  ,    'AB'.charCodeAt(1) => 66

 

2. AsciiCode -> char
   String.fromCharCode(65) => 'A'

 

 

 

 

//Ascii를 이용한 간단한 암호화 알고리듬. 

function encrypt(str) {   //입력이 length=7자리 정도는 된다고 보면  'ABCDEFG'

    //ascii값에 (index+1)더하기.   A+1, B+2, C+3..  G+7

   let rotatedStr = '';

   for (let i = 0; i < str.length; i ++) {
          rotatedStr = rotatedStr + String.fromCharCode(str.charCodeAt(i) + ( i +1 ))
   } 
    
   //로테이션 시키고    //중간에 양념넣기
   let tempStr = '0xe0' + rotatedStr.substring(3) + 'T2n0' + rotatedStr.substring(0,3);  //(4) + 4 + (4) +[3] : DEFG + TEMP + ABC

   return tempStr;

}


function decrypt(tempStr) {  //length:11  

  //양념빼면서 로테이션 해제  //3+4로 복귀

  let rotatedStr = tempStr.substring(tempStr.length - 3) + tempStr.substring(4, tempStr.length-7 )  //뒤 + 앞. 

   

  let str = '';
  for (let i = 0; i < rotatedStr.length; i ++) {
          str = str + String.fromCharCode(rotatedStr.charCodeAt(i) - ( i +1 ));
  } 

  return str;

}

 

Posted by yongary
,

JSON Document

mongoDB, redis 2019. 12. 18. 23:52

Java class를 이용해서 mongoDB에 저장하면서 spring에서 지원하는 mongoTemplate을 쓰는게 가장 편한데,

 

가끔은 이 방법이 불편할 때가 있다.

 

Class가 Collection에 1:1 대응되지만,  Colletion에 필드가 너무 만은데

몇개만 front-End로 리턴해야 한다던지 하는 경우에 매우 불편할 수 있는데, 이럴때 좋은게 Json Document 이다.

 

주로 사용하게 되는 class는

      JSONObject, JSONArray   (net.minidev.json 패키지)

      Document  (mongoDB 저장된 record  org.bson 패키지)

이렇게 3가지 이며,

 

JSONObject <-> Document간 변환을 주로 하게된다.

 

1. Doc으로 변환 후 mongoDB에 저장시에는 

      (MongoDBConnection mongoConn). getCollection("컬렉션명").insertOne( oneDoc );      과 같이 하면 된다.

      Document doc = mongoConn.getCollection("...").find();  //or filter(new FIlter....).find()

2. Doc을 다룰 때 많이 쓰는 함수는 

    Document 생성.  doc.append

                    doc.get("fieldName") => Document가 되기도 하고 List<Document>가 되기도 하고 자동.  

 

 

기타: (JSONObject <-> Document간 변환용 함수들)

   
    public static Document jsonToDoc(JSONObject json) {
        try {
            Document doc = Document.parse(json.toString());
            return doc;
        } catch(Exception ex) {
            return null;
        }
    }

    public static ArrayList<Document> jsonArrayToDoc(JSONArray json) {
        try {
            final ArrayList<Document> result = new ArrayList<Document>();
            json.stream().map(obj -> (JSONObject)obj).forEach(item->result.add(jsonToDoc(item)));
            return result;
        } catch(Exception ex) {
            return null;
        }
    }
   public static JSONObject docToJson(Document doc) {
        JsonWriterSettings settings = JsonWriterSettings.builder()
                .int64Converter((value, writer) -> writer.writeNumber(value.toString()))
                .doubleConverter((value, writer) -> writer.writeNumber(Long.toString(Math.round(value))))
                .objectIdConverter((value, writer) -> writer.writeString(value.toHexString()))
                .build();
        return (JSONObject)JSONValue.parse(doc.toJson(settings));
    }

    public static JSONArray docToJsonArray(List<Document> docs) {
        JSONArray array = new JSONArray();
        for (Document doc : docs) {
            array.add(docToJson(doc));
        }
        return array;
    }

 

 

========  BigDecimal을 Document이용해  저장하는 경우 ============

- BigDecimal amount 몽고DB 저장 시
   document.append("amount", new Decimal128(amount)));

- BigDecimal amount 몽고DB 읽기 시
   amount = ((Decimal128) document.get("amount")).bigDecimalValue();

 

========vs. BigDecmial을  mongoTemplate을 이용해 저장하는 경우========

그냥 필드를 BigDecimal로 해 놓으면 자동으로 String처럼 변환되면서 mongoTemplate사용 가능할 것으로 예상.
안되면 https://stackoverflow.com/questions/37950296/spring-data-mongodb-bigdecimal-support참조. 

Posted by yongary
,

Kafka vs. RabbitMQ

network개발 2019. 12. 2. 19:31

둘다 속도가 엄청 좋지만,

kafka와 rabbitMQ는 큰차이점이 있다.  REF
 

1. kafka는 pull 방식, rabbit MQ는 push 방식.

2. rabbitMQ는 in Memory cluster를 많이 쓰지만, kafka는 sequential Disk I/O를 많이 쓰므로
  H/W 비용이 kafka 가 저렴하다.

 

그 외 차이점 몇가지를 표로 보면: 

 

 

Posted by yongary
,

DFS with Stack

algorithm & type 2019. 11. 14. 21:48

BinaryTree를 DFS(depth first search)하기에는 recursion이 간편하다.

하지만 recursion 없이 stack을 이용하는 방법도 있는데, java코드로 표현하면 다음과 같다.

 

 

static void printDFS(Node node) {

        Stack<Node> stack = new Stack<>();

        Node temp = node;
        while (temp != null || !stack.isEmpty()) {

            //(THIS + Left)푸쉬 => left,this,right 출력.
            while (temp != null) {
                //this push
                stack.push(temp);
                //left traverse
                temp = temp.left;
            }

            //start print
            temp = stack.pop();
            print(temp); /////////////////////////////////////

            //right point : goto TOP
            temp = temp.right;
        }
    }
Posted by yongary
,

openzeppelin SDK를 사용해서 solidity를 upgradable하게 작성하는 방법이 있다.

 

기존 truffle환경에서 추가할 부분은..

1. npm install -g @openzeppelin/cli

2. Contract 코드 작성 

import "@openzeppelin/upgrades/contracts/Initializable.sol";

contract Logic is Initializable {

function initialize() public initializer {
 //생성자없이 여기서 필요한 변수 초기화.

}

//기타 필요 변수/함수 작성

}

 

 

3. oz init .  (truffle 환경에서 실행) -> .openzeppelin/project.json 생성 

4. oz compile  (이 때, upgradable 하고싶은 contract 만 contracts 밑에 있는게 편함)

5. oz create Logic --network beta  --init --args 50000 

 

   >>> create되면, build/contracts/Logic.json이 기존 truffle 수준으로 생성됨. => 이걸 이용해 서비스.

 

=== 여기까지 proxy 1차 배포 완료 ====> 3~5과정을 다시하고 싶으면  .openzeppelin 폴더 제거 후 진행.  rm -rf ./build도 하는게 좋음.

6 test

truffle console --network beta
let abi = require("./build/contracts/Logic.json").abi
let contract = new web3.eth.Contract(abi, "your-proxy-address")
contract.methods.getMaxDeposit().call();

 

===Upgrade
1. Logic.sol 제일 뒷부분에 getV2MaxDeposit() 함수 추가.

2. $oz push --network beta
   => Logic을 space바  로 select

 

3. $oz update Logic --network beta

    >>> update되면, build/contracts/Logic.json이 기존 truffle 수준으로 update됨. => 이걸 이용해 서비스.


4. test 

truffle console --network beta
let abi = require("./build/contracts/Logic.json").abi 

let contract = new web3.eth.Contract(abi, "previous-proxy-address")

contract.methods.getV2MaxDeposit().call();

 

Posted by yongary
,

spring MongoDB

mongoDB, redis 2019. 9. 8. 12:47

 spring(boot)에서 mongoDB를 사용할 때, mongoTemplate으로 사용하면 controller와 service만으로 개발이 되므로 간단해서 주로 이 방법을 사용 중이다.

 

하지만, Repository를 사용할 경우 더 편리한 경우도 존재한다.

특히 @Query를 이용해 json형태의 query를 바로 사용할 수 있는 점이 가장 매력적이다.

 

기본적으로 mongoRepository를 상속만하면, 여러 조회함수들이 지원된다. 아래 링크 참조.

=> findByField + 조건

https://docs.spring.io/spring-data/mongodb/docs/1.2.0.RELEASE/reference/html/mongo.repositories.html 

 

6. MongoDB repositories

Most of the data access operations you usually trigger on a repository result a query being executed against the MongoDB databases. Defining such a query is just a matter of declaring a method on the repository interface The first method shows a query for

docs.spring.io

그 외 간단한 설정은 https://mommoo.tistory.com/79 참조.

 

@Query 사용방식은 https://www.devglan.com/spring-boot/spring-data-mongodb-queries 참조.

 

 

 

#spring #mongodb #@Query

Posted by yongary
,

ReactNative Navigation

React.js 2019. 8. 7. 10:56

참고: https://reactnavigation.org/docs/en/navigation-prop.html 

 

기본이동:

  this.props.navigation.navigate('화면Tag', {

     url: newUrl,
     onGoBack: this.goBackCallback //callBack지정 가능

  });

   수신화면에서는: constructor에서

    this.state = {
           url: this.props.navigation.getParam('url', 'default url');
    }
   이전화면으로 복귀시:
   this.props.navigation.goBack(); //popup닫기.
   this.props.navigation.state.params.onGoBack(data);

    


화면생성하면서 이동:

  const params = {data, userDefined}

  this.props.navigation.push('화면Tag', params);

  이동후 getParam: this.props.navigation.getParam('data'); 

 

back:
  this.props.navigation.goBack();


Posted by yongary
,

 

1. URL 방식으로 파라미터 전달

 

보내는 쪽에선

url = 'buy.js?order=' + JSON.stringify(order) 로 보내고

 

받는 쪽에선  

const params = new URLSearchParams(this.props.location.search);
const order = JSON.parse(params.get('order'));

 

 

2. push 방식으로 파라미터 전달

 

this.props.history.push('/joinComplete?name='+state.name+'&email='+state.email)

받는 쪽은 동일.

Posted by yongary
,

#!/bin/bash

while sleep 5; do
PROCESS_NUM=`ps -ef | grep -v grep | grep -v attach | grep geth | wc -l`
if [ $PROCESS_NUM -ge 1 ]; then
echo $PROCESS_NUM"process"
else
echo "not running ! RESTARTING" $(date)
./start.sh
fi
done

 

 

단, 실제로 $ps -ef | grep -v grep | grep -v attach | grep geth | wc -l 한 결과보다
스크립트에서 찍는 결과가 1이 더 큰 값이 나오는데.. 왜 그런지 조사 중.

Posted by yongary
,