Middleware/Kafka&RabbitMQ 2020. 7. 1. 17:10

 

<exchange가 queue로 메시지를 쏘는 전략>

  • Direct Exchange
    • Message의 Routing Key와 정확히 일치하는 Binding된 Queue로 Routing
  • Fanout Exchange
    • Binding된 모든 Queue에 Message를 Routing
  • Topic Exchange
    • 특정 Routing Pattern이 일치하는 Queue로 Routing
  • Headers Exchange
    • key-value로 정의된 Header 속성을 통한 Routing

 

<exchange options>

  • Durability
    • 브로커가 재시작 될 때 남아 있는지 여부
    • durable -> 재시작해도 유지가능
    • transient -> 재시작하면 사라집니다.
  • Auto-delete
    • 마지막 Queue 연결이 해제되면 삭제

 

<개발 흐름?>

  1. Producer app은 Exchange 만들어 준다. (ex: com.levi.exchange) - 주체 producer app
  2. Queue를 Exchange에 Binding한다. - 주체 consumer app

 

 

 

 

https://jonnung.dev/rabbitmq/2019/02/06/about-amqp-implementtation-of-rabbitmq/

 

조은우 개발 블로그

 

jonnung.dev

https://velog.io/@hellozin/Spring-Boot%EC%99%80-RabbitMQ-%EC%B4%88%EA%B0%84%EB%8B%A8-%EC%84%A4%EB%AA%85%EC%84%9C

 

Spring Boot와 RabbitMQ 초간단 설명서

이번 포스트에서는 Spring boot 프로젝트에서 RabbitMQ를 사용하는 간단한 방법을 알아보겠습니다. Consumer 코드와 Producer 코드는 GitHub에 있습니다. 먼저 RabbitMQ 서버를 실행해야 하는데 Docker를 사용하�

velog.io

https://nesoy.github.io/articles/2019-02/RabbitMQ

 

RabbitMQ에 대해

 

nesoy.github.io

 

posted by 코딩초보 여성게

댓글을 달아 주세요

Web/Spring 2020. 6. 25. 16:03

 

오늘 다루어볼 내용은 spring data mongo + querydsl 연동 및 간단한 예제를 다루어볼 것이다. 예제 환경은 아래와 같다.

 

- gradle : 6.4.1
- spring boot : 2.3.1.RELEASE

 

모든 코드는 아래 깃헙을 참고하자.

 

yoonyeoseong/spring-mongo-querydsl

Contribute to yoonyeoseong/spring-mongo-querydsl development by creating an account on GitHub.

github.com

 

<gradle 설정>

아래는 spring data mongo와 querydsl 연동을 위한 gradle 설정이다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
buildscript {
    ext {
        queryDslVersion = '4.3.0'
    }
    repositories {
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.3.1.RELEASE")
    }
}
 
plugins {
    id 'org.springframework.boot' version '2.3.1.RELEASE'
    id 'io.spring.dependency-management' version '1.0.9.RELEASE'
    id "com.ewerk.gradle.plugins.querydsl" version '1.0.10'
    id 'java'
    id 'idea'
}
 
group = 'com.levi'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '14'
 
repositories {
    mavenCentral()
}
 
dependencies {
    compile 'org.springframework.boot:spring-boot-starter-data-mongodb-reactive'
    compile 'org.springframework.boot:spring-boot-starter-webflux'
    compile('org.springframework.boot:spring-boot-configuration-processor')
 
    compile "com.querydsl:querydsl-mongodb:${queryDslVersion}"
 
    compile 'org.projectlombok:lombok'
 
    annotationProcessor(
            'org.springframework.boot:spring-boot-configuration-processor',
            "com.querydsl:querydsl-apt:${queryDslVersion}",
            'org.projectlombok:lombok'
    )
 
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
    testImplementation 'io.projectreactor:reactor-test'
}
 
test {
    useJUnitPlatform()
}
 
def querydslSrcDir = 'src/main/querydsl'
 
querydsl {
    springDataMongo = true
    querydslSourcesDir = querydslSrcDir
}
 
sourceSets {
    main {
        java {
            srcDirs = ['src/main/java', querydslSrcDir]
        }
    }
}
 
compileQuerydsl{
    options.annotationProcessorPath = configurations.querydsl
}
 
configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
    querydsl.extendsFrom compileClasspath
}
 
project.afterEvaluate {
    project.tasks.compileQuerydsl.options.compilerArgs = [
            "-proc:only",
            "-processor", project.querydsl.processors() + ',lombok.launch.AnnotationProcessorHider$AnnotationProcessor'
    ]
}
 
cs

 

작성중...

 

 

<참고>

 

Spring Data MongoDB - Reference Documentation

As of version 3.6, MongoDB supports the concept of sessions. The use of sessions enables MongoDB’s Causal Consistency model, which guarantees running operations in an order that respects their causal relationships. Those are split into ServerSession inst

docs.spring.io

 

gradle 프로젝트에서 querydsl 설정하기

gradle 4.6 / querydsl 4.2.1 / spring-data-jpa 1.11.13.RELEASE / spring-data-mongodb 1.10.8.RELEASE이 환경을 어떻게 gradle 설정으로 푸는지 정리힙니다.

mingpd.github.io

 

ewerk/gradle-plugins

A collection of Gradle plugins. Contribute to ewerk/gradle-plugins development by creating an account on GitHub.

github.com

posted by 코딩초보 여성게

댓글을 달아 주세요

Web/Spring 2020. 6. 25. 15:56

 

Spring Data MongoDB - Reference Documentation

As of version 3.6, MongoDB supports the concept of sessions. The use of sessions enables MongoDB’s Causal Consistency model, which guarantees running operations in an order that respects their causal relationships. Those are split into ServerSession inst

docs.spring.io

 

posted by 코딩초보 여성게

댓글을 달아 주세요

Web/Gradle 2020. 6. 23. 23:46

> $HOME/.gradle/caches/modules-2/files-2.1/
> rm -rf <삭제할 스냅샷 혹은 라이브러리>
> ./gradlew --refresh-dependencies
posted by 코딩초보 여성게

댓글을 달아 주세요

https://github.com/robert-bor/aho-corasick/tree/master/src/main/java/org/ahocorasick/trie

 

robert-bor/aho-corasick

Java implementation of the Aho-Corasick algorithm for efficient string matching - robert-bor/aho-corasick

github.com

https://www.slideshare.net/ssuser81b91b/ahocorasick-algorithm

 

Aho-Corasick Algorithm(아호 코라식 알고리즘)

Aho-Corasick Algorithm 장홍준 hongjun7@korea.ac.kr

www.slideshare.net

 

posted by 코딩초보 여성게

댓글을 달아 주세요

Tools/Git&GitHub 2020. 6. 6. 15:40

 

오늘 다루어볼 내용은 평소에 조금 헷갈렸던 Git reset과 revert이다. 깃에서 되돌리기 위한 방법은 크게 2가지가 있다. 바로 reset과 revert이다. 그렇다면 둘의 차이점은 무엇일까?

 

  • reset : 시계를 마치 과거로 돌리는 듯한 행위
  • revert : 특정 사건을 없었던 일로 만드는 행위
git reset <--option> "돌아가고 싶은 커밋 hash"

먼저 reset을 알아보자. reset은 특정 커밋으로 돌아가는 행위다. 그말은 특정 커밋 이후의 커밋이력 모두 없어지게 되는 것이다.(물론 옵션마다 상태가 다르긴하다) reset에는 옵션이 3가지가 있다. hard, soft, mixed 각 옵션에 대한 설명은 아래와 같다.

 

  • hard : 돌아가려는 커밋 이후의 모든 내용을 다 지워버린다.
  • soft : 돌아가려는 커밋 이력으로 되돌아 갔고, 이후의 내용은 stage 상태로 남아있는다.(git add 상태) 즉, 커밋을 다시 할 수 있는 상태가 되는 것이다.
  • mixed : 돌아가려는 커밋 이력으로 되돌아 갔고, 이후 내용은 남아있지만, unstage된 상태로 남아있다.(git add 이전 상태, tracked file list)

이제 각 옵션에 대해 실습해보자. 우선 쓰레기 코드가 들어간 커밋이 마지막에 찍혀있는 것을 보자.

 

 

각 reset 옵션 적용 후 상태를 확인하자.

 

<hard>

 

이전 커밋이력으로 돌아갔다. 그리고 이전에 추가했던 trash_code.txt도 감쪽 같이 사라졌다.

 

 

<soft>

 

쓰레기코드가 추가된 커밋이 사라졌다. 하지만 Uncommitted changes 상태가 되었다.(git add)

 

 

<mixed>

 

이전 커밋으로 잘 돌아갔고, 파일은 untracked된 상태이다.

 

 

만약 현재 커밋으로부터 몇개 이전으로 커밋을 되돌리고 싶다면 아래 문법으로도 reset이 가능하다.

 

#현재 커밋 기준 6번째 전 커밋으로 되돌린다.
git reset HEAD~6

 

여기까지 reset에 대해 다루어보았다. 다음은 revert에 대해 다루어보자.

 

git revert "지우고 싶은 커밋 hash"

revert는 특정 커밋을 아예 날려버리는 행위이다. 하지만 reset과는 조금 다른 이력이 남는다. 바로 실습내용을 확인해보자.

 

 

나는 가장 마지막 커밋을 revert 할것이다. 과연 이력은 어떻게 남을 걸까?

 

 

reset과는 다르게 내가 특정 커밋을 revert했다라는 이력이 남아있다.(물론 trash_code.txt가 추가됬다는 것도 남아있다.) 이것이 reset과의 차이점이며, 또 하나는 reset은 특정 커밋 이후의 이력을 모두 지우지만, revert는 중간에 껴있는 특정 커밋 이력을 날려버릴 수 있다.

 

그렇다면 revert와 reset은 어떠한 상황에서 사용해야 할까?

보통 reset은 원격 레포지토리로 푸시하기 이전에만 사용한다. 만약 이미 원격 레포지토리에 푸시한 이후에 reset을 하고, push를 하면 아래와 같은 메시지가 보일 것이다. 그 이유는 로컬의 커밋이 원격 커밋보다 뒤에 있기 때문에.. 물론 git push --force 옵션을 사용하여 push할 수 있지만, 이미 다른 사람들이 작업한 커밋이 푸시되어있다면? 윽 생각도 하기 싫다. 

 

 

reset은 혼자만 사용하는 브랜치일 때와 다른 사람들이 해당 브랜치를 pull한 적이 없을 때 정도만 사용가능할 듯하다. 그 이유는 로컬에서만 작업한 내용에서 실수로 다른 커밋을 찍었고 아직 push하기 이전에 reset을 한다면 커밋이력이 훨씬 깔금해지기 때문이다. 하지만 push 이후에는 왠만하면 revert 옵션을 사용하자.

 

push 이후에 revert를 사용하면 내가 어떠한 커밋에 대해 revert를 했는지가 커밋 로그에 남기때문에 훨씬 이력관리에 좋고, 다른 사람이 제가 이력을 지운 커밋이후에 작업을 했더라고, 그 커밋들을 건드리지 않기때문에 크게 문제 없다. 여기까지 git reset, revert에 대해 다루어보았다.

 

<참고>

 

개발바보들 1화 - git "Back to the Future"

  이 내용에 대한 자세한 기술적인 설명이 듣고 싶나요? 연속되는 다음글을 참조하세요    

www.devpools.kr

posted by 코딩초보 여성게

댓글을 달아 주세요

Web/Spring 2020. 5. 15. 14:12

mongo host를 Replicaset member 만큼 명시하지 않고, dns등 하나의 호스트만 명시한경우에는 반드시 multiple mode를 명시해주어야 한다. 내부적으로 host의 갯수를 모고 single mode인지 multiple mode인지 판단하기 때문...

posted by 코딩초보 여성게

댓글을 달아 주세요

오늘 다루어볼 내용은 java 14에서 도입된 record 타입의 클래스입니다. 

 

record란?

레코드(record)란 "데이터 클래스"이며 순수하게 데이터를 보유하기 위한 특수한 종류의 클래스이다. 코틀린의 데이터 클래스와 비슷한 느낌이라고 보면 된다. 밑에서 코드를 보겠지만, record 클래스를 정의할때, 그 모양은 정말 데이터의 유형만 딱 나타내는 듯한 느낌이다. 훨씬더 간결하고 가볍기 때문에 Entity 혹은 DTO 클래스를 생성할때 사용되면 굉장히 좋을 듯하다.

 

sample code

간단하게 샘플코드를 살펴보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class SampleRecord {
   private final String name;
   private final Integer age;
   private final Address address;
 
   public SampleRecord(String name, Integer age, Address address) {
      this.name = name;
      this.age = age;
      this.address = address;
   }
 
   public String getName() {
      return name;
   }
 
   public Integer getAge() {
      return age;
   }
 
   public Address getAddress() {
      return address;
   }
}
cs

 

위와 같은 코드가 있다고 가정하자. 해당 클래스는 모든 인스턴스 필드를 초기화하는 생성자가 있고, 모든 필드는 final로 정의되어 있다. 그리고 각각 필드의 getter를 가지고 있다. 이러한 클래스 같은 경우는 record 타입의 클래스로 변경이 가능하다.

 

1
2
3
4
5
public record SampleRecord(
   String name,
   Integer age,
   Address address
) {}
cs

 

엄청 클래스가 간결해진 것을 볼 수 있다. 이 record 클래스에 대해 간단히 설명하면 아래와 같다.

 

  • 해당 record 클래스는 final 클래스이라 상속할 수 없다.
  • 각 필드는 private final 필드로 정의된다.
  • 모든 필드를 초기화하는 RequiredAllArgument 생성자가 생성된다.
  • 각 필드의 getter는 getXXX()가 아닌, 필드명을 딴 getter가 생성된다.(name(), age(), address())

 

만약 그런데 json serialize가 되기 위해서는 위와 같이 선언하면 안된다. 아래와 같이 jackson 어노테이션을 붙여줘야한다.

 

1
2
3
4
5
public record SampleRecord(
   @JsonProperty("name") String name,
   @JsonProperty("age") Integer age,
   @JsonProperty("address") Address address
) {}
cs

 

record 클래스는 static 변수를 가질 수 있고, static&public method를 가질 수 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public record SampleRecord(
   @JsonProperty("name"String name,
   @JsonProperty("age") Integer age,
   @JsonProperty("address") Address address
) {
   
   static String STATIC_VARIABLE = "static variable";
   
   @JsonIgnore
   public String getInfo() {
      return this.name + " " + this.age;
   }
 
   public static String get() {
      return STATIC_VARIABLE;
   }
}
cs

 

또한 record 클래스의 생성자를 명시적으로 만들어서 생성자 매개변수의 validation 로직등을 넣을 수도 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public record SampleRecord(
   @JsonProperty("name"String name,
   @JsonProperty("age") Integer age,
   @JsonProperty("address") Address address
) {
 
   public SampleRecord {
      if (name == null || age == null || address == null) {
         throw new IllegalArgumentException();
      }
   }
 
   static String STATIC_VARIABLE = "static variable";
 
   @JsonIgnore
   public String getInfo() {
      return this.name + " " + this.age;
   }
 
   public static String get() {
      return STATIC_VARIABLE;
   }
}
cs

 

이러한 record 클래스를 spring의 controller와 연계해서 사용하면 더 간결한 injection이 가능해지기 때문에 훨씬 깔끔한 컨트롤러 클래스작성이 가능하다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
======================================================================================
 
public record SampleRecord(
   @JsonProperty("name"String name,
   @JsonProperty("age") Integer age,
   @JsonProperty("address") Address address
) {
   
   static String STATIC_VARIABLE = "static variable";
   
   @JsonIgnore
   public String getInfo() {
      return this.name + " " + this.age;
   }
 
   public static String get() {
      return STATIC_VARIABLE;
   }
}
 
======================================================================================
 
public record Address(
    @JsonProperty("si"String si,
    @JsonProperty("gu"String gu,
    @JsonProperty("dong"String dong
) {}
 
======================================================================================
 
@Service
public class SampleRecordService {
    public Mono<SampleRecord> sampleRecordMono(SampleRecord sampleRecord) {
        return Mono.just(sampleRecord);
    }
}
 
======================================================================================
 
@RestController
public record SampleController(SampleRecordService sampleRecordService) {
    @PostMapping("/")
    public Mono<SampleRecord> sampleRecord(@RequestBody SampleRecord sampleRecord) {
        System.out.println(sampleRecord.getInfo());
        return sampleRecordService.sampleRecordMono(sampleRecord);
    }
}
 
======================================================================================
cs

 

여기까지 간단하게 jdk 14의 new feature인 record 클래스에 대해 간단하게 다루어 보았다. 모든 코드는 아래 깃헙을 참고하자.

 

 

yoonyeoseong/jdk_14_record_sample

Contribute to yoonyeoseong/jdk_14_record_sample development by creating an account on GitHub.

github.com

 

참조 : https://dzone.com/articles/jdk-14-records-for-spring-devs

 

JDK 14 Records for Spring - DZone Java

In this article, we'll discuss several use cases for JDK 14 Records to write cleaner and more efficient code.

dzone.com

 

posted by 코딩초보 여성게

댓글을 달아 주세요