소개
- 주력 언어 또는 기술 : Java, Spring Framework, RxJava, Reactor, Spring WebFlux
- (주)코드스테이츠(https://www.codestates.com)에서 Senior Educational Software Engineer(Backend)로 활동
(From 2022.03 To 2024.01.31)
- 프리랜서 개발자 및 강사로 활동(From 2024.02)
- 저서
안녕하세요? Kevin이라고 합니다. ^^
인프런에서 이렇게 강사로서 여러분들을 만나게 되어서 너무 반갑습니다.
어떤 분야든 마찬가지겠지만 특히나 소프트웨어 개발자는 끊임없이 변화하는 트렌드에 뒤처지지 않도록 항상 자기 자신을 갈고 닦는것이 개발자로써 살아남는 유일한 방법이라고 생각하며 항상 배우는 자세로 즐겁게 소프트웨어 개발을 하고 있는 개발자 중 한 명입니다.
제가 가지고 있는 지식과 경험이 다른 분들에게 조금이나마 도움이 되기를 바라면서 인프런에서 강좌를 시작하였습니다.
앞으로 수강생분들에게 현실적으로 도움이 되는 다양한 강좌로 꾸준히 찾아뵙도록 하겠습니다. 감사합니다.
질문이나 의견은 언제든지 환영하니, 이메일(it.village.host@gmail.com)로 편하게 얘기해주세요.
강의
전체5로드맵
전체1수강평
- 좋은 강의였습니다.
rlackdgml97
2024.05.14
1
게시글
질문&답변
2024.06.02
context의 read, write의 실행 순서
안녕하세요? Context가 왜 아래에서 위로 전파되는지에 대한 부분은 아래 AI 인턴의 답변을 참고하시면 될 것 같구요. 질문자님이 궁금해 하시는 건 코드가 위에서 아래로 순차적으로 읽어나가는데 read가 write 밑에 있으면 write된 값을 왜 read 할 수 없는지를 궁금해 하신다고 이해했습니다. Reactor의 코드 내부에서는 복잡한 과정을 거치긴 하겠지만 핵심은 람다 표현식(함수형 인터페이스)에 있다고 생각합니다. 우리가 명령형 프로그래밍 방식에서 작성하는 코드는 작성한 순서대로 위에서 아래로 실행됩니다. 즉 코드가 순차적으로 즉시 실행된다고 생각하시면 될 것 같은데요. Java의 Stream API나 리액티브 프로그래밍의 경우에는 명령형 프로그래밍 방식처럼 메서드 체인 형태로 순차적으로 실행되는 것 같지만 Operator 함수로 넘겨준 람다 표현식이 즉시 호출되지는 않고 지연 호출이 가능합니다. 단순히 하나의 람다 표현식에 대해서만 지연 호출이 가능하다면 순차적으로 실행되면 약간 딜레이를 주고 실행된다고 볼 수 있지만 Stream API나 리액티브 프로그래밍 같은 경우에는 람다 표현식을 딱 하나만 함수의 파라미터로 전달하는게 아니라 메서드 체인 형태로 각 Operator 함수에서 거의 매번 전달 하는 형태인데 이 때, Operator 함수에서 전달 받은 람다 표현식은 일반적으로 위에서 아래로 순차적으로 실행되지는 않거든요. 문장으로 설명드리니 이해하기가 어려우실텐데 간단히 코드로 표현을 하면 아래와 같습니다. Flux.just(데이터 소스) .operator1(op1-lambda) .operator2(op2-lambda) .operator3(op3-lambda) .subscribe() 위 코드에서 operator1이 operator2를 호출하고 operator2가 operator3을 차례대로 호출하는건 맞는데 operator1, 2, 3에서 각각 파라미터로 전달한 op1-lambda, op2-lambda, op3-lambda 표현식은 구독이 발생하기 전까지는 호출이 지연 된다고 볼 수 있습니다. 람다 표현식의 가장 중요한 특징 중 하나가 지연 호출입니다. 그런데 지연 호출된다고 해서 op1-lambda -> op2-lambda -> op3-lambda 의 순서대로 실행이 되는게 아니라 일반적으로 op3-lambda -> op2-lambda -> op1-lambda 형태로 역으로 호출됩니다. 이렇게 호출 할 수 있는 이유는 내부적으로 op2-lambda가 op1-lambda의 참조를 가지고 있고, op3-lambda가 op2-lambda의 참조를 가지고 있어서 역으로 호출이 가능하다라고 생각하시면 될 것 같습니다. 리액티브 프로그래밍이 이렇게 역으로 호출되어 아래쪽에서 위쪽으로 동작이 전파되는 특성을 가지고 있는데 검색해 보시면 구독이 아래에서 위로 전파된다 라는 내용을 심심치 않게 보실 수 있을텐데 Context의 동작도 구독의 동작에 맞춰서 일어난다고 보시면 될 것 같습니다. 질문하신 부분에 대한 충분한 답변이 되셨길 바랍니다. 감사합니다.
- 0
- 2
- 25
질문&답변
2024.05.19
DROP 전략과 LATEST 전략의 차이점이 무엇인가요?
안녕하세요. 휴일이라서 답변이 조금 늦어졌습니다. 음.. 버퍼가 비워지는 시점이 찰나의 짧은 시점이라서 100퍼센트 정확하게 설명드리기 곤란한 부분이 있긴한데 개념적으로 차이점만 설명드리자면, 우선 현재 버퍼가 가득차 있는 상태이고, subscriber의 처리가 끝나지 않은 시점이라고 가정하겠습니다. 이 시점에 Drop 전략인 경우 버퍼가 가득차 있기때문에 즉시 drop 되어 폐기가 됩니다. 반면에 Latest 전략의 경우 버퍼가 가득차 있고 Upstream 쪽에서 데이터가 emit되어 들어오면 drop 전략처럼 즉시 데이터가 drop되어 폐기 되는게 아니라 최신데이터 하나(A)는 유지합니다. 이 상태에서 뒤따라 오는 데이터(B)가 있다면 A는 이제 최신 데이터가 아니기때문에 B가 최신 데이터가 되고 A는 삭제 됩니다. 저는 여러 분석을 거쳐서 이렇게 이해하고 수강생들에게 설명을 드리고 있습니다. 질문에 답변이 충분히 되셨길 바랄게요.
- 1
- 2
- 69
질문&답변
2024.05.18
백프레셔 전략 관련해서
안녕하세요? 답변이 조금 늦었습니다. 폐기와 드랍의 차이점에 대해서 질문 주셨는데요. 결론부터 말씀드리자면 폐기와 드랍은 결국 같은 의미인데 데이터가 삭제 된다고 보시면 될 것 같아요. 아래는공식 문서에 나와 있는 Backpressure 전략 설명 중에서 Drop 전략와 Latest 전략에 대한 부분만 발췌한건데요. (사진) 둘 다 discard 라는 용어를 보실 수 있는데 이 discard 가 폐기, 삭제, 무시 라는 뜻을 포함하고 있습니다. 다만, 데이터가 언제 폐기(삭제)되느냐의 차이점이 존재합니다. 한마디로 drop이라는 표현에 폐기(삭제)라는 의미가 포함된다고 보시면 될 것 같아요. 즉, drop 된 후 폐기(삭제)된다. 라고 생각해 주시면 될 것 같습니다. 질문에 대한 답이 충분히 되셨는지 모르겠습니다. 더 궁금한게 있으시면 언제든지 편하게 질문 주세요. 감사합니다.
- 1
- 1
- 58
질문&답변
2024.04.12
Backpressure Example 코드 질문드립니다
안녕하세요? 답변이 조금 늦었습니다. 육아를 병행하고 있어서 답변이 늦어진 점 양해 부탁드릴게요. Backpressure Error 전략은 Downstream 쪽에서 Upstream 쪽의 속도에 대응하지 못할 경우 에러를 발생시키는 전략인데요. 에러가 발생할 때 아래와 같은 에러 로그가 출력됩니다. reactor.core.Exceptions$OverflowException: The receiver is overrun by more signals than expected (bounded queue...) 이 문장에서 bounded queue 가 일종의 버퍼를 의미하는데요. Downstream 쪽에서 내부적으로 데이터를 처리할 때 사용하는 버퍼라고 생각하시면 될 것 같습니다. 그런데 여기서의 버퍼는 Backpressure Buffer 전략에서의 Buffer와 조금 다른 동작을 합니다. Downstream 쪽에서 지연 시간을 짧게 주면 버퍼에 그만큼 더 빠르게 데이터가 쌓이게 되고, 지연 시간을 길게 주었을 때 데이터가 그만큼 천천히 쌓인다고 생각하시면 될 것 같습니다.(내부적으로 버퍼에 쌓이는 동작을 조절한다고 보시면 될 것 같습니다.) Backpressure의 내부 메커니즘을 100 퍼센트 다 이해하고 있다고 한다면 솔직히 거짓말일텐데 아무튼 쉽게 생각해서 다음 데이터를 처리하기 위해 넉넉한 시간을 가질 수 있다면 여유를 가지고 처리를 할 수 있는거라고 생각해주시면 좋을 것 같아요. 데이터를 처리할 준비가 안되어 있는데 무작정 데이터가 들어오면 과부하가 걸릴테니까요. 다만, 이 경우에는 여유는 생기겠지만 처리할 수 있는 데이터의 건 수는 그만큼 줄어들테니 적절한 조건을 찾아야 될테구요. 적절한 답변이 되셨으면 좋겠습니다. 감사합니다.
- 0
- 1
- 62
질문&답변
2024.04.05
Single과 관련해 여쭤보고 싶은 부분이 있습니다!
안녕하세요. 아침에 질문을 확인했는데 일정이 바빠서 답변이 조금 늦어졌네요. ^^ 1. Single은 전통적인 client - server 방식의 요청을 처리하는 데 사용한다고 말씀해주셨습니다. 실제로 회사에서 single.blocking() 이런 방식으로 처리하는 코드를 본 적이 있는데, single을 해당 의도처럼 사용할 경우, 동기처리 방식에 비해 얻는 이점이 있을까요?? 제가 아직 생각하기로는 코드는 리액티브이지만 비동기 방식으로 처리하는 것이 아닌 거 같아서요! --> Single을 전통적인 client - server 방식의 요청을 처리하는데 사용한다 라는 의미는 우리가 일반적으로 사용하는 HTTP request와 response가 하나의 HTTP message로 이루어져 있기 때문에 이걸 처리하기 적합하다는 의미이구요. single.blocking() 방식으로 코드를 본 적이 있다고 말씀해 주셨는데, 여러 개의 비동기 작업이 있어서 이 작업이 다 끝날 때 까지 동기적으로 기다려야 되는 상황이 아닌데 습관적으로 blocking()을 호출하는 방식이라면 바람직하지는 않다고 생각합니다. 즉, 비동기 방식을 습관적으로 동기 방식으로 전환한다면 RxJava 같은 리액티브 라이브러리를 사용하는 의미가 퇴색될 수 있는거라고 생각하시면 될 것 같아요. 또한 강의 영상 3분 정도에서 보여주신 SingleCreateExample 코드에서, 발행자인 Single의 create 메소드의 파라미터인 SingleOnSubscribe 가 구현하고 있는 subscribe가 아래 구독자가 구독하는 subscribe() 와 같은 함수가 맞을까요? 코드적으로는 둘이 연관이 있어 보여서, SingleObserver 와 SingleEmitter 사이의 같은 부모가 있는지 확인 해보았는데 그것두 아니더라구요 ㅠ... 둘이 아예 다른 메소드 인가요?? --> 일단 결론은 다른 메서드인데 서로 연관이 있습니다. (사진): 캡쳐한 이미지의 코드를 보시면 SingleCreate은 Single의 하위 클래스인데요. Single.create()을 호출하면 리턴됩니다. (1)의 SingleOnSubscribe는 (4)에서 subscribe()를 호출하는데 이 때의 subscribe()는 구독자가 구독 즉, subscribe()를 호출하면 데이터를 구독자에게 통지하기 위한 emitter를 전달 받는 역할을 한다고 보시면 될 것 같구요. (2)의 SingleObserver를 포함하고 있는 parent 객체가 (3)과 (4)에 서로 연결이 되는걸 볼 수 있는데요. 이 말은 구독자가 구독하면 발행자가 이 구독을 인지하고 데이터를 구독자에게 전달한다라는 의미와 같다고 보시면 될 것 같습니다. 좀 어렵죠? 코드 내부를 다 이해하실 필요는 없고 리액티브 프로그래밍의 Pub/Sub 모델은 서로 독립적인 관계가 아니라 서로 밀접하게 관계를 맺고 있다라는 사실만 일단 기억하시면 좋을 것 같아요. 4. 코드를 살펴보다가 RxJavaHooks 라는 유틸성 클래스를 발견하게 되었는데, 함수형 인터페이스들이 막 정의되어 있는 것은 알겠는데 어떻게 해석해야 할 지가 감이 안 잡히더라구요 ㅠㅠ... 혹시 코드를 해석하는데 조언을 주실 수 잇으실까요?.. --> Hook이라는 의미는 프로그래밍에서 종종 사용하는 용어인데요. 코드 상의 흐름 중간에 끼어 들어서 추가적인 작업을 한다는 의미입니다. RxJavaHooks를 이용해서 Observable이 생성될 때 로깅, 예외 처리, 디버깅 등의 추가적인 작업을 할 수 있도록 해줍니다. 학습하시는데 도움이 되셨길 바랍니다~
- 0
- 2
- 82