[1.기본설치 - mongoDB 5.0 기준]

 

MongoDB 저장소 추가하기

1. MongoDB는 CentOS의 기본 저장소에 포함되어 있지 않으므로, 별도의 저장소를 추가해야 합니다. 다음 명령어를 터미널에서 실행하여 MongoDB 저장소를 추가합니다

 

$ sudo vi /etc/yum.repos.d/mongodb-org-5.0.repo

아래내용 입력 저장.

[mongodb-org-5.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/5.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-5.0.asc
 
2. 그 다음에 진짜 설치.
- $sudo yum install mongo-org

 

3. 설치 완료후 설정 수정.

- /etc/mongod.conf 에  bindIp를 0.0.0.0 으로 수정.

 

4. 시작 

- $sudo systemctl start mongod 
=> (start를  status로 고치거나, restart로 고치면, 상태조회, 재시작 가능.)

 

 

 

 

[2. replicaSet 설정 법]

https://docs.mongodb.com/manual/tutorial/deploy-replica-set/

  - /etc/mongod.conf 에 replication 추가 필요. [기본 3서버 설정 기준, =>  2서버 1가상 arbiter설정은 아래 참조]
replication:
   replSetName: "rs0" 

 

  • (sudo) service mongod start
  • 3대가 다 시작되면 그 중에 한대에 mongo 로 접속해서 아래명령 실행필요,
arbiter없을 경우:
  rs.initiate({
   _id : "rs0",
   members: [
      { _id: 0, host: "172.31.47.103:27017" },
      { _id: 1, host: "172.31.46.185:27017" },
      { _id: 2, host: "172.31.43.168:27017" }
   ]
})

arbiter있을 경우:
  rs.initiate({
   _id : "rs0",
   members: [
      { _id: 0, host: "172.31.47.103:27017" },
      { _id: 1, host: "172.31.46.185:27017" }
   ]
})

rs.conf() 및 rs.status()로 확인가능.

 

[2서버 1 아비터 설정시]

arbiter 세팅시에는, member2개로 rs.initiate하고 rs.addArb(“host:port”)를 수행.

https://thomassileo.name/blog/2012/03/08/how-to-mongodb-replica-sets/

그전에 arbiter 기동은 https://docs.mongodb.com/manual/tutorial/add-replica-set-arbiter/ 

1. $sudo mkdir -p /var/lib/mongodb/arb

2. $sudo mongod --dbpath /var/lib/mongodb/arb --replSet rs0 --bind_ip 0.0.0.0

 

 

priority변경 은: PRIMARY서버에 붙은 후

cfg = rs.conf()
cfg.members[0].priority = 0.5
cfg.members[1].priority = 1.0
cfg.members[2].priority = 0.5
rs.reconfig(cfg) 

 

Posted by yongary
,

1. aggregation시 조건부 sum을 하는 방법입니다.

https://stackoverflow.com/questions/41218321/grouping-and-sum-with-conditions

 

ConditionalOperators.Cond cond = when(Criteria.where("status").is("PRESENT")).then(1)
                .otherwise(when(Criteria.where("status").is("ABSENT")).then(2)
                .otherwise(100));
                
//ond operatorNbS = ConditionalOperators.when("scst").thenValueOf(1).otherwise(0);

Aggregation agg = newAggregation(
    match(Criteria.where("bid").is("build_1481711758"),
    project("bid") 
        .and("scst")                            
        .applyCondition(cond, field("nbE"))

 

2. aggregation시 substring을 이용한 조건부 sum을 하는 방법입니다.

https://recordsoflife.tistory.com/463

Posted by yongary
,

WebGL은 OpenGL기반으로 만들어진 javascript용 라이브러리이다.

react에서 활용가능한 webGL 라이브러리가 여러가지 있으나 three.js가 괜찮아 보인다.

지원 브라우저에 주의하여야 한다.

 

저장포맷으로는 JSON기반인 glTF 를 많이 사용한다. 


(webGL 관련 예제)
https://code-masterjung.tistory.com/m/101?category=928099 

 

React로 Threejs 예제 따라 구현하기

 css를 공부하다 보니 자연스레 WebGL에 관심이 생겨 기본 개념을 익힐 겸 공식 문서를 따라 만들어 보았다(openGL은 일단 조금 나중에 다시 보는 걸로..). 사실 문서가 너무 잘 돼있어 예제를 단순히

code-masterjung.tistory.com

 

Posted by yongary
,

//summaryStatistics 를 이용한 통계방식 적용.
DoubleSummaryStatistics tpStat = list.stream().mapToDouble( log -> log.getTemp()).summaryStatistics();

 

이렇게 하면 다음과 같은 값들을 한번에 구할 수 있다. 사용법은 tpStat.getCount(), getSum() 등등

private long count;
private double sum;
private double min;
private double max;

Posted by yongary
,

기본적인 서버구성이 끝났다면.. (여기서는 2대의 서버에, route53을 통해 도메인 하나 공급을 가정)
  - 기본서버설정(jdk설정) : www.liquidweb.com/kb/install-java-8-on-centos-7/ 

  - ulimit설정    : https://www.baluna.ro/increasing-file-descriptors-and-open-files-limit-in-centos-7/

  - 혹시 efs연동시에는 : docs.aws.amazon.com/efs/latest/ug/efs-onpremises.html 참조. 

  - 타임존 설정: $sudo timedatectl set-timezone Asia/Seoul

  - 로케일 설정: ma.ttias.be/warning-setlocale-lc_ctype-cannot-change-locale-utf-8-no-such-file-or-directory/ 

 

(zooKeeper서버 설정시에는 /root/zookeeper/conf/zoo.cfg 에 자기IP만 0.0.0.0 다른 2서버  IP기재 + /var/zookeeper/myid 를 각각 1,2,3으로 설정)

 

1.    AWS의 ACM을 통해 인증서를 발급 받는다.              (참고: jojoldu.tistory.com/434

 

AWS의 Certificate Manager 로 SSL 인증서 발급 받기

보통 서비스가 소규모라면 1대의 서버에 Nginx를 설치하고 Let's Encrypt 를 설치해서 SSL을 등록합니다. 다만 이럴 경우 트래픽이 늘어 로드밸런서 + 여러 서버 구성으로 확장하기가 쉽지 않습니다.

jojoldu.tistory.com

  - 진행 중, [Route53에서 레코드 생성]버튼이 안나올 경우. 

      =>1방법(잘안됨) :  도메인 구매한 사이트의, 도메인 구성에 가서 CNAME 레코드를 추가한다.
         CNAME :  _990122b262bc3ecxxxx.acm-domainname.com 형태로 key와 value를 추가한다. 
             (hostname은 _990122b262bc3ecxxxx 까지만, . TTL은 3600정도..)
      => 2방법: route53으로 직접가서 호스팅영역(mydomain.com)을 먼저추가하고, AWS에 알려주는 4개
              (예: ns-620.awsdns-1.net.
ns-222.awsdns-31.com.ns-333.awsdns-26.co.uk. ns-444.awsdns-50.org.)
          를 도메인 구매한 사이트의, 도메인 구성에 가서 네임서버 1차,2차,3차,4차 로 설정한다.
           ==> 2방법 이후에 [Route53에서 레코드 생성]버튼이 보이므로, 누르면 된다.

       
     (30분 가량 대기하면 인증서 발급이 된다)

2. 그 후, 로드밸런서를 생성한다.

   로드밸런서 설정에서 타겟그룹을 구성하고, 서버2대를 추가.

 

   로드밸런서의 인증서 선택은 1에서 생성한 인증서를 선택한다. 
   보안그룹은 하나 만들어서 넣거나, 미리 만들어 둔 후 고르면 되고(후자 권장)

 

   라우팅 구성, 대상그룹 선택에서 앞서만든 타겟그룹을 추가하면 된다.  프로토콜은 HTTP로 된다. 

 

3. 로드밸런서 stickiness

   - 로드밸런서로 서버 2대에 부하를 분산할 경우,  접속자가 동일한 서버로 계속 접속되는 게 세션관리나 log측면에서 편하다.

  - 이 기능을 stickiness라고 하는데, AWS에서는 stickiness 세팅을 로드밸런서에 하지 않고,  Target Group에서 한다.


  아래 그림과 같이 Attribute에서 stickiness와 stickiness duration을 세팅하면 된다.    

   

 

4. 마지막으로, route53에 가서 A.레코드 세트를 추가하면서, Alias사용을 선택하면 로드밸런서를 선택할 수 있다.
  이름은 안넣고 하나생성, www 넣고 하나생성 .. 이렇게 A레코드 2개 세트 권장.

Posted by yongary
,

CSRF, JWT 토큰

IT 2020. 7. 29. 15:09

csrf 는 웹서비스에서 cross-site-request-forgery를 막기위해

백엔드에서 토큰을 발행하고 프론트엔드에서 이를 사용하여 최종적으로는 유효한 요청인지를 확인하는 방식.

 

 

JWT토큰은 인증에 사용되는 방식으로서 REF

OAuth와 연동해서 사용할 수도 있고 독립적으로 사용할 수도 있다.

 

 OAuth1과 OAuth2의 가장 큰 차이는 OAuth2의 경우 refresh 토큰이 가능. 

 

 

 

JWT를 구현하면서 마주치게 되는 고민들

최근 모바일, 웹 등 다양한 환경에서 서버와 통신하면서 많은 사람들이 JWT 토큰 인증 방식을 추천합니다. 이 포스팅에서는 JWT를 이해하고 구현하면서 마주치게 되는 고민들에 대해 정리해보려 �

swalloow.github.io

 

Posted by yongary
,

spring boot2에서부터는  controller에서 @Async에서도

completableFuture를 리턴할 수 있다..

( 그 전에도 Async와 EnableAsync는 있었는데 completableFuture를 리턴하지는 못한것 같은데, 확인 중)

 

<사전지식>

1. Future(Java5 에 등장) 와 Observable간에 전환.  (마찬가지로 CompleatbleFuture와  Single간에 전환도 유사)

Observable<String> source = Observable.fromFuture(future);

source.subscribe(System.out::println);

 

2. Future vs CompletableFuture (Java8에 등장)  : ref
    CompletableFuture.complete() 함수를 호출해  Future를 수동으로 종료할 수 있음. 

    그 외 runAysnc, supplyAsync, thenApply, thenAccept, thenRun 등 함수들이 제공됨.

  

 


출처: https://12bme.tistory.com/570 [길은 가면, 뒤에 있다.]

 

[RxJava] RxJava 프로그래밍(1) - 리액티브 프로그래밍

서버 다수와 통신하게 되면 API 호출 각각에 콜백을 추가하게 된다. 콜백이 늘어나면 애플리케이션의 복잡성도 증가(callback hell)하게 된다. RxJava는 자바로 리액티브 프로그래밍을 할 수 있는 라이

12bme.tistory.com

https://12bme.tistory.com/570 

 

 

 

참고: https://howtodoinjava.com/spring-boot2/rest/enableasync-async-controller/#:~:text=1.-,Spring%20%40Async%20rest%20controller,application%20classes%20for%20asynchronous%20behavior.&text=The%20%40Async%20annotated%20methods%20can,result%20of%20an%20asynchronous%20computation.

 

Spring @Async rest controller example - Spring @EnableAsync

Spring @Async non blocking rest controller example. Learn to use spring async behavior with @EnableAsync annotation. Spring async completablefuture example.

howtodoinjava.com

 

Posted by yongary
,

Test Code 관련

springBoot gradle 2020. 7. 13. 17:19

 

 Stub/ Mock/Fake 등을 묶어‘테스트 더블(Test Double)' 이라고 한다. (여기서 Double=대역)

 

SpringBoot에선 BDDMockito를 지원해 B(Behavior) Driven Test를 지원한다.

 

 

MockMVC 과 Mockito의 차이.

- mockito가 좀 더 general하고 더 많은 case를 지원하고, 여러가지 mock도 지원한다. (mockObject.when()  등등...)

- MockMVC는 spring 전용.  

 

Posted by yongary
,

격리수준

BACK-END 2020. 7. 11. 22:15

DB의 트랜잭션은 ACID를 보장해야 한다. (참고: https://feco.tistory.com/45

 - 원자성, 일관석, 격리성, 지속성

Atomicity: 한트랜잭션이 여러query로 이루어질 수 있는데, 한 트랜잭션의 모든 query가 성공하거나, 혹은 part of transaction이 실패하면 전체 transaction이 실패/혹은 rollback해야한다. 
Consistency: 트랜잭션후에도 DB는 항상 valid state 를 유지해야 한다.(for각종 constraint들 enabled in DB)
Isolation : 동시에 여러개의 transaction이 실행되더라도 하나씩 고립되어 순차적으로 실행되어야한다.
Durability: 트랜잭션이 commit되고 나면, 항상 available해야한다. server가 꺼졌다 켜지더라도...

 

 

이중, "I"인 Isolation(격리성의) 수준은 (참고: https://m.blog.naver.com/PostView.nhn?blogId=blueaian&logNo=220636152759&proxyReferer=https:%2F%2Fwww.google.com%2F )

 

- READ UNCOMMITED (dirty read 발생가능 + 아래들)

   : 일반적인 Database에서는 사용하지 않음

- READ COMMITED (none-repeatable read 발생가능 + 아래 )

   : Oracle 트랜잭션 격리 수준 ( OLTP에서 많이 채택 )

   : commit된 데이터에 대해 다른 세션에서 읽을 수 있음

- REPEATABLE READ  (Phantom Read발생가능)

  : Mysql 기본 격리수준

  : select 에 대해서도 MVCC 수준 유지

- SERIALIZABLE

  : 동시성이 중요한 Database에서는 사용하지 않음

 

Posted by yongary
,

점을 V(Vertex)
edge를 E라고 하면..

 

처음에 V를 쭉 더해놓고

다음부터는 BFS (혹은 DFS도 가능)

 

따라서 complexity는 O (V + E) 

 

https://www.geeksforgeeks.org/detect-cycle-undirected-graph/

cycle find 코드예제:

더보기
import java.util.*;

class Graph {
    private int V;
    private LinkedList<Integer>[] adj;

    Graph(int v) {
        V = v;
        adj = new LinkedList[v];
        for (int i = 0; i < v; ++i)
            adj[i] = new LinkedList();
    }

    void addEdge(int v, int w) {
        adj[v].add(w);
        adj[w].add(v);
    }

    boolean isCyclicUtil(int v, boolean[] visited, int parent) {
        visited[v] = true;
        for (Integer i : adj[v]) {
            if (!visited[i]) {
                if (isCyclicUtil(i, visited, v))
                    return true;
            } else if (i != parent) {
                return true;
            }
        }
        return false;
    }

    boolean isCyclic() {
        boolean[] visited = new boolean[V];
        for (int i = 0; i < V; ++i)
            if (!visited[i])
                if (isCyclicUtil(i, visited, -1))
                    return true;

        return false;
    }
}

public class CycleDetectionExample {
    public static void main(String[] args) {
        Graph g1 = new Graph(5);
        g1.addEdge(1, 0);
        g1.addEdge(0, 2);
        g1.addEdge(2, 1);
        g1.addEdge(0, 3);
        g1.addEdge(3, 4);
        
        if (g1.isCyclic())
            System.out.println("Graph contains cycle");
        else
            System.out.println("Graph doesn't contain cycle");
    }
}

코드예제임.

 

Digikstra 알고리듬.  근접한 distance 부터 하나씩 추가하는 알고리듬.

더보기
import java.util.*;

class Node implements Comparable<Node> {
    int id;
    int distance;
    
    public Node(int id, int distance) {
        this.id = id;
        this.distance = distance;
    }
    
    @Override
    public int compareTo(Node other) {
        return Integer.compare(this.distance, other.distance);
    }
}

public class DijkstraAlgorithmWithClass {
    public static void dijkstra(int[][] graph, int start) {
        int n = graph.length;
        int[] distance = new int[n];
        Arrays.fill(distance, Integer.MAX_VALUE);
        distance[start] = 0;
        
        PriorityQueue<Node> pq = new PriorityQueue<>();
        pq.offer(new Node(start, 0));
        
        while (!pq.isEmpty()) {
            Node curr = pq.poll();
            int node = curr.id;
            int dist = curr.distance;
            
            if (dist > distance[node]) continue;
            
            for (int neighbor = 0; neighbor < n; neighbor++) {
                int weight = graph[node][neighbor];
                if (weight > 0 && distance[node] + weight < distance[neighbor]) {
                    distance[neighbor] = distance[node] + weight;
                    pq.offer(new Node(neighbor, distance[neighbor]));
                }
            }
        }
        
        // 출력: 각 노드까지의 최단 경로 길이
        System.out.println("Node\tDistance");
        for (int i = 0; i < n; i++) {
            System.out.println(i + "\t" + distance[i]);
        }
    }
    
    public static void main(String[] args) {
        int[][] graph = {
            {0, 4, 0, 0, 0, 0, 0, 8, 0},
            {4, 0, 8, 0, 0, 0, 0, 11, 0},
            // 나머지 그래프 데이터도 입력
        };
        
        dijkstra(graph, 0);
    }
}
Posted by yongary
,

간단한 @StreamListener  annotation만으로 stream 통신을 할 수 있으므로, MSA에서 유리하다.

 

https://coding-start.tistory.com/139

 

Kafka - Spring cloud stream kafka(스프링 클라우드 스트림 카프카)

Kafka - Spring cloud stream kafka(스프링 클라우드 스트림 카프카) 이전 포스팅까지는 카프카의 아키텍쳐, 클러스터 구성방법, 자바로 이용하는 프로듀서,컨슈머 등의 글을 작성하였다. 이번 포스팅은 �

coding-start.tistory.com

 

그 외에
 SpringCloud Eureka : MSA환경에서 서버들을 registry 해놓고, 로드밸런서와 같은 역할 가능.

 

 springcloud zuul : MSA환경에서 G/W를 이용해 token 체크등을 한 곳에서  모아서 할 수 있다.

 

 

 

Posted by yongary
,

Arrays (feat Stream)

java8~ 2020. 7. 4. 20:41

1. Arrays.stream     

 

int[] arr = new int[] { 3, 5, 8} 

Arrays.stream( arr).filter(x -> x <=5).sum();

 

==> 근데 딱 한군데, arr -> List로 바꿀때는 잘 안됨.

List<Integer> list = IntStream.of(arr).boxed().collect(Collectors.toList())

           (boxed()가 primitive array를 단일 element로 잘라 줌)

 

참고: Stream<String> st = Stream.of("A", "B","C"); 등  다양한 Stream생성 방식:  https://codechacha.com/ko/stream-creation/

 

2. Arrays.sort 

int[][] arr = new int[][]{ {1,2,3} {4,5,2}}

Arrays.sort(arr,  (a, b) -> (a[2] - b[2]) ) ;   //Comparator를 functional로 바로 넣음..

3. Arrays.binSearch (arr, target)

  -> 찾으면 idx리턴, 못 찾으면 들어갈 자리  -idx-1 리턴..  :항상 음수를 리턴하기 위해..


 

====stream 통계=====


min/max/avg 등을 한꺼번에 구할때..

DoubleSummaryStatistics stat =  arr.stream().mapToDouble(x -> x).summaryStatistics();


stat = {counnt:10.0, sum:120.0, min:1.0, aveerage:10.11, max:19.0}

 

 

Posted by yongary
,

 

기본적으로 설치해서  fabric-samples/fabcar/startFabric.sh 를 하면

 

/network.sh up createChannel -ca -s couchdb 로 실행이 된다,.

 

이 때

./organizations/peerOrganizations 를 참조하면서. (아래 3개 파일 이용)

    org1.example.com/fabric-ca-client-config.yaml*
    org1.example.com/connection-org1.json
    org1.example.com/connection-org1.yaml

 

 

노드1, 노드2를 물리적으로 분리할 경우 (https://www.slideshare.net/hlkug/201903-hyperledger-fabric)

<노드 1>
- 채널생성 (peer channel create),

- 채널Join  (peer channel join),

- Anchor Peer 업데이트 (peer channel update)

- 체인코드 설치(peer chaincode install),

- 체인코드 Instantiate(peer chaincode instantiate),

- 체인코드 Query(peer chaincode query)

<노드 2>

- 제네시스 Block Fetch (peer channel fetch 0...)

- 채널Join  (peer channel join),

- Anchor Peer 업데이트 (peer channel update) 

- 체인코드 설치(peer chaincode install),

- 체인코드 Query(peer chaincode query)

 

 

개인이 만든 fabric-starter.git 참고 (https://www.altoros.com/blog/deploying-a-multi-node-hyperledger-fabric-network-in-5-steps/ ) - 테스트 필요.

Posted by yongary
,

 

<spring 에서 fabric G/W를 이용한 컨트랙트 실행>

implementation 'org.hyperledger.fabric:fabric-gateway-java:2.0.0'  추가 후 아래소스 참조.

https://hyperledger.github.io/fabric-gateway-java/

 

 

 

<유저 생성 후 실행 example>

https://newtechstax.com/2019/11/12/integrating-fabric-blockchain-with-springboot-application/

Posted by yongary
,

CA는

- ID를 등록하고 LDAP과 연결해서 사용자 등록수행

- ECert 발행 (Enrollment Certi)

- Certi 갱신과 철회

 

CA_server와  CA_client로 구성.

<CA server>

$fabric-ca-server start -b <admin>:<adminpw>

 

<CA client>

$export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/admin 
$fabric-ca-client register --id.name admin2 --id.affiliation org1.department1 --id.attrs 'hf.Revoker=true,admin=true:ecert'

 

 

 

<참고 사이트>

https://hyperledger-fabric-ca.readthedocs.io/en/release-1.4/users-guide.html

 

Fabric CA User’s Guide — hyperledger-fabric-cadocs master documentation

This section describes how to configure the Fabric CA server to connect to PostgreSQL or MySQL databases. The default database is SQLite and the default database file is fabric-ca-server.db in the Fabric CA server’s home directory. If you don’t care about

hyperledger-fabric-ca.readthedocs.io

 

 

Posted by yongary
,

 

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
,

클레이튼

블록체인 2019. 6. 11. 20:32

2019/8/27 Cypress(메인넷)상황

  4,000  TPS

  1/10 gas cost of MIN Ethereum gas

  23 node, 50+ partner

  

Layer 2 서비스체인 : side-chain을 클레이튼에선 서비스체인이라고 부름

Aspen(private geth) -> Baobab(testNet) -> Cypress(mainNet) 19년8월.

 

Klaytn EOA (Externally Owned Account) = Role based Key (역할에 따라 한 account에 여러 키를 매핑 가능)

 - keys가 이더리움과 좀 다름.  이더리움은 offLine에서 keyPair를 만들 수 있지만.. 분실문제가 심각해서, 클레이튼에서 개선함.

 - key와 account를 분리해서 update Key와 Sigining Key로 분리함. update Key만 잘 보관하고 있으면 새로운 Sigining 키를 만들 수 있음.

 - 즉, public key 2개를 만들어서.. update key를 유지하면서 사이닝키를 여러개 쓸 수도 있음. 

 ==> keyType:1 이면 기존 ETH방식 키이며 default 키타입. 

 

transaction에도 type이 존재 :  VALUE_TRANSFER, ACCOUNT_UPDATE( keyType을 role base 로 바꿀수 있음) 등.

 

Fee Delegation 모델: 서비스에서 대신 gas 내 줌.

 - Fee Paying Key를 이용해서 내줌.

 - Transaction type: FEE_DELEGATED_VALUE_TRANSFER 을 이용함.

 - 서버에서  feePayerAddress를 이용해서 wrap해서 gas를 내주는 방식의 예제가 있음. (docs.klaytn.com에 있음)

 

클레이튼 창구: facebook을 주로 이용.

 

klay를 시중에서 구할 수 없기 때문에, PoC(contribute)를 통해 소량 받는 방법이 있다. - 현재 문제가 있어서 그러한 것으로 보임.

 

BApp의 경우 developer.klaytn.com 추가채널이 있긴하나 답변이 좀 늦다.

 

 

---------2019.6--------------

카카오 계열 그라운드X에서 만든 클레이튼은 IBFT 합의 알고리듬을 이용한다.

 

코어 네트웍이 있어, 프라이빗 처럼 합의를 하며, 서비스가 사용하는 레이어인  Endpoint노드는 별도레이어로 존재한다.

 

서비스 개발사는 Endpoint노드를 하나 구동하던가 아니면

이더리움의 infura와 같이 조회위주로 간단하게 서비스 해주는 EndPoint노드를 이용하면 된다.

 

개발시 이더리움의 truffle은 그대로 이용이 가능하며,

web3.js대신에 caver-js를 이용하게 된다.

 

아직 caver-js의 개발수준이 높지 않다는 얘기가 있던데,
필자도 직접 확인해 보려고 하는 중이다.

이더리움과의 또 다른 차이는 gasPrice가 고정이라는 점이다. 클레이튼의 gasPrice는 항상 25ston(wei)으로 고정.

 

 

클레이튼 개발자센터:  https://www.facebook.com/groups/klaytndevelopers 

 

클레이튼 IDE: http://ide.klaytn.com 

 

caver-js DOC: https://docs.klaytn.com/toolkit/caverjs 

 

클레이튼 소개영상:  https://www.inflearn.com/course/클레이튼

 

SCOPE(이더스캔): https://baobab.klaytnscope.com/ 

테스트넷(바오밥)지갑: http://baobab.klaytnwallet.com 

Posted by yongary
,

솔리디티로 스마트 계약을 한번 배포하고 나면, 이를 수정해서 배포하기에 어려운 경우가 있다.

예를 들면, 토큰을 10억개 발행했다면 이를 다시 배포하면 새로운 토큰이 되므로 수정배포할 수가 없다.

 

한번 배포한 토큰 10억개를 계속해서 사용할 수 있도록, 로직만 재배포 하면서 업그레이드 해야한다.

 

이를 위해서 고려할 만한 몇가지 방법이 있는데, 현재까지 파악한 수준에서 나열해 보면 다음과 같다.

 

1. 다른 컨트랙트에서 특정 컨트랙트를 호출 : REF

 

Contract A를 배포하고,

Contract B에서 A를 이용만하는 구조이다.

 

Contract A에 storage변수 및 몇몇 함수 저장하고, Contract B에서 지속적으로 이용할 수 있다.

 

<필요사항>

Contract B 생성자에서 Contract A의 배포된 주소가 필요.

Contract B 에서 Contract A를 호출하기 위해, A의 간단한 ABI가 필요 -> 즉 A의 함수만 포함한 간단한 껍데기 Contract 필요.

 

 

2. Library 사용

라이브러리는 컨트랙트와 유사하지만, 한번 배포 후 다양한 컨트랙트에서 재사용하는것이 목적이다.

단점은 라이브러리는 상태변수(storage변수)를 가질 수 없다.

- 따라서 토큰의 재활용과 같은 기능은 구현하기 어렵다.

 

3. deletegateCall  : REF

- fallback함수를 이용해서, 자기 컨트랙트에 없는 함수를 실행하는 방법이다. 

 

proxy 컨트랙트를 이용해, 항상 proxy컨트랙트를 호출하지만 proxy컨트랙트에 함수가 없는 경우

다른 컨트랙트를 자동으로 호출하는 방법이다.

 

사용법:

 - contract.at( proxy Address) 를 해서 instance를 가져온 후, instance.함수 호출 방법으로 실행한다. 

 

단점:

- 상태변수(storage 변수)가 재대로 관리되는지 확인이 필요한다. 아직 이 부분이 잘 되는지 의심이 가서

테스트 중에 있다.

 

 

총평:

현재로서는 1번 방식이 가장 간단한 방법이다.

단, 1번 방식의 경우 Contract A안에 있는 mapping등을 Contract B에서 마음껏 사용하기가 어렵기 때문에

 

3번 방식을 사용하는 것이 좋아 보인다.

3번방식이 상속된 컨트랙트가 부모 컨트랙트의 상태변수를 재사용하지 못하고 새로 만드는 문제는 있으므로,

3번 방식의 경우에도 Contract A안에 모든 mapping변수들을 넣어놓고, Cotract A-> Contract B함수 호출시
Contract A안의 mapping 및 상태변수들이 제대로 이용되는지 확인이 필요하다. 
즉 A의 Context를 이용해 B를 이용하는 것인데, truffle test에서는 잘 되는 걸 확인했으나, web3.js를 이용해서는

아직 잘 호출이 안되고 있다. (호출 확인시 update예정)

 

 

 

 

Posted by yongary
,

(수정)

react-native-webview를 쓸 경우에는 frontEnd에서 RN으로 데이타를 보낼때,

window.postMessage 대신에 => window.ReactNativeWebView.postMessage 를 쓰면 됩니다. 

 

==============

import { WebView, NativeModules } from 'react-native';

(react-native-webview가 별도로 나오고 있지만, 아직은 쓰기가 좀 어려운 듯합니다)

 

  • react-native WebView에서 웹페이지로 부터 데이터 주고 받을 때.

    doMyCode = () => {
    	this.myWebView.postMessage(data);   //프런트엔드로 메시지 송신
     }
     
    render() {
        return (
            <WebView
                ref={webview => { this.myWebView = webview; }}
                source = {{uri: "http://localhost:3000/userPhone/main"}}
                style = {{marginTop : 65}}
                onMessage = {(event) => this.doMyCode()}   //프런트엔드에서 메시지 수신
            />
        )
    }

 

  • webView 뒤로가기가 잘안되므로, 코딩으로 추가 방법  : test필요
 
onNavigationStateChange = (navState) => {
  this.setState({
    canGoBack: navState.canGoBack
  });
}

//back버튼시 아래 호출,
onBack = () => {
  if (this.state.canGoBack)
    this.refs[WEBVIEW_REF].goBack();
  else
    app종료.
}

<View style={styles.container}>
  <WebView
    ref={WEBVIEW_REF}
    style={{flex: 1}}
    onNavigationStateChange=
      {this.onNavigationStateChange}
    /> 
 </View>

 

 

Adding a Back Button for React Native WebView

Sometimes when writing an app, we need to show some web page to the user. We may want them to be able to interact with the page, but also…

blog.defining.tech

 

Posted by yongary
,

sub-array를 일반document처럼 $unwind해서 사용하는 방법 추천.

 

그 외에는 아래 명령들을 사용하고

$elemMatch

$slice

 

(필요시) 최종적으로는 projection을 통해 sub-array가 있더라도 원하는 data를 조회할 수 있다.

 

 

마지막으로는 

variants.attrs 를 통해 추가적인 filter가 설정이 가능하다.  REF

 

Posted by yongary
,

온톨로지 블록체인은 중국에서 Neo기반으로 만들어진 블록체인으로서,

대규모의 투자유치를 한 것으로 유명하다.


온톨로지의 특징을 살펴보면 다음과 같다. (참고: 영문개발자 사이트)



1. VBFT 알고리듬을 사용한다.    

   BFT계열의 알고리즘들은 DCS (Decentralize, Consensus, Scale) 중에 SC를 취한 방식이다.

   즉, 속도가 빠르고 정합성도 좋지만 노드의 수는 작은 편이다.  

   그 중  PBFT는 전체 노드의 동의가 아닌 일부노드(2/3)의 동의로 합의한다.   (pbft 상세)

   온톨로지의 VBFT는  VRF(Vertifiable Random Function)와 BFT를 결합한 것이다.

   - 즉 BFT이지만 랜덤의 특성을 통해 합의알고리듬의 공정성을 보장한다.


2. 개발환경 

  - Solo Chain 제공 : 이더리움의 ganache 클라이언트와 같은 개발용 블록체인이다. 모양도 비슷하다.


  - dAPI  :  이더리움의 web3와 유사한 js 기반 


  - cyano Wallet :  메타마스크와 유사하다. android와 ios버전이 벌써 존재하는 점은 이더리움보다 빠르다.
     (NEO와 ONT 계좌가 지원된다 : ONT는 암호화폐, ONG는 GAS)


  - SmartX라는 스마트컨트랙트 개발툴 지원.


  - Ontology Client : 이더리움의 geth Client 라고 보면 됨.


  - 스마트컨트랙트는 python, 부수적으로는 C#


  - Punica 슈트: dApp개발 framework. 

     = Punica CLI (punica-python, punica-typescript)  : 이더리움의 truffle과 유사. 

        + Punica BOX (tutorialtoen-box, tokenexchange-box, oep4-box) 

        + Solo Chain 



3.온톨로지 기본 소개

온톨로지 소개:

- 퍼블릭, OnChain이라는 솔루션기업이 중국정부최초인가 업체

- OnChain아래 Neo와 온톨로지.

- Neo의 댑으로 시작했다가, 온톨로지 플랫폼으로 작년에 메인넷 론칭.

- 대표:다홍페이-네오대표, 리준(리쥔). 코파운더

- 분산신원인증 체계를 독보적으로 보유하고 있음. ONT ID가 대표적.

   (개인, 사물, 인증을 ID 밑으로 연동해서 DATA공유 플래폼을 목표로 함.), 알리바바 결제는 엔트파이넨셜이 운용.

   데이터 주권을 개개인으로 이동.

   데이터를 필요로 하는 사람들에게는 DDFD로 전달하게 됨.

   

- ONG라는 가스. 0.01 ONG로 고정되어 있음. 10원정도. 

- dApp은 30여개.  한국은 무비블록, 뮤지카(는 돌고 있음)


- OEP4(ERC-20), OEP5 (NFT) 토큰 존재  --> 두개특성 섞은 OEP-8

- 실제 6000 TPS 수준 (EOS는 3천)


- 한국파트너: Hashed가 노드운영. 체인어스


- incentive 모델 A (가스비 50% 리턴), B (top 50위에 들면 ONT를 줌.)

  C (대출, 70%개발시 반, 완료시 반 대출)

  D (기술 마케팅 서포트)

- HyperDragons Go 게임 론칭시 이벤트등도 지원해줬다


Posted by yongary
,