/ POSTS

NHN FORWARD 2019✨ 후기

Note : 이 글은 지극히 주관적인 생각을 토대로 작성된 글입니다. 혹시나 잘못된 부분이 있다면 메일 또는 코멘트를 통해 알려주시면 감사하겠습니다. 😄 제 메일은 About 탭에서 확인하실 수 있습니다. 📧

Intro..

얼마 전에 포스팅한 2019년 회고에서 올해에는 외부 세미나나 컨퍼런스에서 많이 참여하지 못해서 아쉽다고 적었었는데, 포스팅하고 며칠 지나서 지인 개발자분께서 연락이 왔었다. “혹시 개발자 컨퍼런스에 갈 생각이 있느냐?”라고 물으시길래 어떤 컨퍼런스인지 물었는데, NHN FORWARD라고 대답해주었다. 알아보니까, NHN에서 주최하는 개발자 컨퍼런스로 11월에 서울에서 이미 한 번 주최했는데, 반응이 좋았어서 지방에서 한 번 더 열린다는 내용이 있었다. 참가 등록을 사전에 받아서 이미 참가 등록은 마감된 상태였는데, 지인 개발자분께서 바빠서 못 갈 것 같다고 자신의 참가권을 양도해주셨다. 처음에는 고민했는데, 세션 목록을 보니까, 참석하고 싶어졌다. 더군다나 이 정도 규모의 큰 컨퍼런스는 아직 참석해본 경험도 없었고, 수도권이 아니라면 참석하기도 쉽지 않았기 때문에 이번 기회를 놓치고 싶지 않았다. 하나 아쉬운 부분은 컨퍼런스 장소가 부산이 아닌 창원이라는 부분이었다.

NHN FORWARD 2019 행사장 도착

오전 9시 30분부터 등록을 받아서 부산에서 일찍 출발해야 하는 게 조금 힘들었지만, 행사장에는 제시간에 무사히 도착했다. 컨퍼런스는 창원의 그랜드 머큐어 앰배서더 호텔에서 열렸는데, 호텔이라 그런지 시설이 되게 좋았다. 내가 호텔에서 주최되는 컨퍼런스에 오게 될 줄은 몰랐지만, 천천히 실감하면서 행사가 열리는 층으로 이동해서 무사히 등록했다. 등록한 뒤에 본 행사 시작까지 시간이 남아서 행사장을 천천히 둘러보았는데, 볼거리가 많았다. 부스가 여러 개 있었는데, 첫 번째로 간 부스는 구름이라는 회사의 부스였다. 구름에서 진행하는 클라우드 서비스에 대한 소개 및 체험을 해볼 수 있었고 좋은 기념품과 스티커도 받을 수 있었다. 두 번째로 간 부스는 핸즈온 랩을 해볼 수 있는 공간이었는데, 컨퍼런스 사이트에 미리 지정된 15개 정도의 주제 중에서 원하는 주제를 골라서 직접 실습해보면서 짧은 시간 안에 새로운 기술을 습득할 수 있는 곳이었다. 비치된 아이맥을 통해서 실습할 수 있었고 실습하다가 막히면 옆에 계시는 개발자분에게 도움을 요청할 수 있었다. 하나의 주제당 15분에서 30분 정도 걸리는 정도의 실습이었던 것으로 보였다. 사람이 많아서 주변만 기웃거렸다. 세 번쨰로 간 부스는 프론트 앤드 상담소였는데, NHN에서 실무를 진행하시는 현업 프론트 앤드 개발자분들이 프론트 앤드 개발자를 꿈꾸는 학생이나 주니어 개발자들을 위해 상담을 해주는 부스였다. 나는 프론트 앤드를 지망하고 있지는 않아서 상담을 받지는 않았지만 취지가 굉장히 좋은 부스였던 것 같다.

부스들을 둘러보고 나니까, 행사 시작 시간이 되었고 행사 장소로 가서 경남 도지사님의 인사말을 듣고 NHN의 높으신 분이 진행하는 키노트를 들었다. 키노트에서 들었던 내용 중에서 인상 깊었던 내용이 있었는데, 다음과 같은 내용이었다. 이번 NHN FORWARD의 부제가 Small Steps make a Big Difference인데, 우리가 주최한 이 컨퍼런스가 작은 한걸음이지만, 이 한 걸음으로 인해서 많은 개발자들이 성장할 기회를 만들 수 있으면 좋겠다는 내용이었다. 그리고 NHN은 계속 새로운 단계의 첫걸음을 내디디면서 성장해나갈 것이라고 얘기해주시면서 키노트가 마무리되었다. 이 키노트가 마무리되고 15분 정도 있다가 각 트랙을 진행하는 장소에서 세션이 진행되었다. 세션은 크게 트랙 1과 트랙 2 그리고 스몰 스텝으로 나누었다. 트랙 1에는 백 앤드 개발 관련 세션이 많았고, 트랙 2에는 프론트 앤드, 클라우드, 머신러닝, 아키택쳐와 같은 다양한 주제가 집결되어 있었다. 스몰 스텝은 주니어 개발자와 학생들을 위한 성장을 다룬 이야기가 주된 세션 내용이었다. 나의 주 관심사는 트랙 1에 몰려있었기 때문에 트랙 1에서 세션을 들었다.

행사장에 갔는데, 꽤 많은 사람들이 있어서 놀라서 찍었던 사진
행사장 내에서 핸즈 온 랩을 진행할 수 있었던 장소
핸즈 온 랩을 진행하고 싶었지만 이미 풀방이었다..
NHN FORWARD 2019 KeyNote 중에 한 장
내가 주로 들었던 트랙 1 세션 목록

세션 내용

내가 들었던 트랙 1 세션이 대부분 백 앤드 관련 세션이었고, 실무에서 많이 쓰이는 내용이라 모든 내용들을 완벽하게 이해하긴 힘들었다. 그래도 세션을 듣다 보니까, 내용이 조금씩 이해되기 시작했다. 세션을 들으면서 여러 생각이 들었고, 느끼는 것도 많았다. 그중에서 가장 많이 드는 생각은 “지금도 공부할게 많이 남아서 열심히 공부해야 하는데, 회사가서는 더 열심히 공부해야 되겠다.” 라는 생각이었다. 시간 관계상 트랙 1의 모든 세션은 듣지 못했지만, 마지막 세션 빼고는 다 들을 수 있었다. 들었던 세션별로 인상 깊고 기억에 남는 내용과 내가 세션을 들으면서 느꼈던 부분을 짧게 정리해서 경험을 공유하고자 한다.

  • 첫번째 세션, HTTP API 설계, 후회, 고민

    • 이 세션은 발표자님께서 회사에서 서비스를 개발하면서 HTTP API를 디자인한 경험을 공유하는 세션이었다. 먼저 처음에 API 설계 시에는 Restful API를 만들고 싶으셨으나, 실상은 REST를 만족하기란 쉽지가 않았다고 한다. 세션에서는 현재 서비스에는 어떻게 API를 적용되어 있는지를 보여주었다. 현재는 표준에 맞지 않은 API를 서비스에서 사용하고 있지만 차후에 개편할 수 있다면 REST 표준에 맞도록 개편하고 싶다고 한다. 그래서 현재 서비스가 실제 오류 없이 동작은 하고 있으나 API 디자인 설계가 완벽하지 않다. 그래서 후회가 남고 어떤 식으로 개선할 수 있을지 고민했다고 하셨다.

    • 현재는 현실에 맞춰서 초기에 디자인했던 대로 유지하고 있으나, 고민 중인 사항으로 HTTP Cache 적용을 생각해두고 있고, 권한 관리에 대해서 어떤 식으로 처리할 수 있을지도 고민 중이라고 하셨다. 세션 마무리에 API 설계 시에 미리 정해두면 좋은 것에 대해 말씀해주셨다.

    • API 설계시에 미리 정헤두면 좋은 것

      • Resource에 어울리는 단어들 -> 자주 사용되는 이름을 미리 잘 정해두면 좋다.

      • flag 이름, 날짜 시간 필드 명 같은 것도 미리 정해두면 좋다.

      • Query Parameter 이름도 가능한 정확한 표현으로 짓는 것이 좋다.

    • 이 세션을 들으면서 API 설계 시에는 초기에 잘 디자인 하는 게 다음에 유지보수 하기에 편리하다는 것을 알 수 있었고 그럼에도 불구하고 API를 잘 설계하는 것은 손이 많이 가고 어려운 작업이라는 것을 느낄 수 있었다.

  • 두번째 세션, 가장 좋은 쿠폰을 픽 하려다 만난 CPU Full Load 개선기

    • 이 세션은 발표자님께서 커머스 개발팀에서 개발 도중에 특정 쇼핑몰 API 서버에서 CPU Full Load가 발생하는 이슈를 발견해서 이를 개선한 경험을 공유하는 내용이었다. 이슈를 발견하고 코드를 분석하면서 어떤 부분이 문제인가 알아보았는데, 특정 시점에 Thread Dump가 일어나는 것을 발견했고 이걸 일으키는 범인은 상품-쿠폰 매핑 API 였다.

    • 상품-쿠폰 매핑 API의 프로세스

      • 물건을 장바구님에 담는다. -> 배송지를 입력한다. -> 할인/포인트를 선택한다. -> 결제한다.
    • 상품-쿠폰 매핑 API는 다른 서비스에서도 많이 사용하는데, 굳이 여기서 CPU 트래픽을 증가시키는 이유가 무엇인가?

      • NHN 커머스 플랫폼에선 다양한 서비스를 거치면서 최고의 할인율을 만들기 위한 최적의 쿠폰을 매핑시켜주기 위해서 다양한 서비스를 거치는데, 여기서 많은 동작을 수행하면서 트래픽이 급박하게 올라간다.
    • 상품-쿠폰 매칭 이슈

      • 상품-쿠폰 매칭 문제는 탐욕법 적용이 어렵다.
    • API에 요구되는 성능

      • 기존에는 DFS를 이용해서 모든 쿠폰을 순회하는 방식으로 동작했다. 그래서 느렸다.

      • NCP 정책에 맞는 다른 알고리즘을 선택해야 한다.

    • 개선 방법

      • 헝가리안 알고리즘을 사용해서 이를 개선했고, 개선 이후 성능 테스트를 거친 결과 성능이 개선 전보다 더 좋아진 것을 확인할 수 있었다.
    • 이번 세션은 내용이 꽤 복잡해서 내용을 전부 이해하지는 못했다. 점심을 먹고 직후에 진행한 세션이라서 살짝 졸기도 했고.. 그래도 핵심이 되는 문제에 관한 내용은 이해할 수 있었다. 현업에서는 이런 문제가 자주 등장할 텐데, 어떤 식으로 해결할 수 있을지 계속 고민하는 발표자님이 멋있어 보였다.

  • 세번째 세션, DDD-Lite@Spring

    • 이번 세션은 도메인 주도 설계(Domain-Driven Design, 줄여서 DDD)에 대한 세션으로, 중급 이상의 세션이었다. 학부생들과 주니어 개발자는 이해하기 힘든 세션일 수 있다고 발표자님께서 말씀해주셨다. 그래도 어깨너머로만 들었던 도메인 주도 설계에 관한 내용을 직접 자세하게 들을 수 있어서 좋았다.

    • 도메인 주도 설계는 크게 전략적 패턴, 전술적 패턴으로 나뉜다고 한다. 우리가 이 세션에서 다룰 것은 전략적 패턴이 아닌 전술적 패턴이다.

    • 복잡성과 위기

      • 기술은 항상 발전하는데, 왜 우리의 프로젝트는 갈수록 힘든가? 왜 유지보수가 힘든가?

      • 애플리케이션이 엄청 복잡하기 때문, 해결해야할 문제 자체가 복잡하기 때문

      • 복잡성과 비용 -> 애플리케이션의 복잡성이 올라가면 비용도 올라가고 그럼 위기를 맞는다.

    • 도메인 주도 설계를 통해서 위기를 극복하자.

      • 전략적 패턴은 큰 그림을 그리는 것이고, 전술적 패턴은 핵심 도메인을 주로 다루는 방식이다.

      • 문제 자체를 직접 해결하려고 하면 힘들다. 그래서 분할 정복을 통해서 문제를 쪼개서 해결한다.

      • 커다란 도메인을 서브 도메인으로 분할하는 방식으로 처리할 수 있다.

    • DDD-Lite

      • DDD의 전술적 패턴의 일부를 DDD-Lite라고 한다.
    • DDD에 대해 레퍼런스를 찾아보면 내용이 잘 나오는데, 실제로 어떻게 적용을 해야할지에 대해서는 알아보기 힘들다. 자료도 잘 없고.. 그래서 아키택쳐와 모듈을 잘 이용해야 한다.

    • 세션에서는 헥사고날 아키택쳐를 언급했는데, 헥사고날 아키택쳐는 전부 도메인을 바라보고 있다. 헥사고날 아키택쳐와 DDD의 핵심은 어플리케이션의 모든 것이 도메인에 의존하고 있다. 이 말은 곧 도메인은 그 어떤 것에도 의존하지 않는 것이라고 한다.

    세션에서 다루었던 헥사고날 아키택쳐
    • 결론

      • 기술보다 도메인이 먼저다.

      • DDD는 학습곡선은 낮으나 깊다고 한다. 학습을 하는 것이 어려울 수 있으나 학습을 통해서 많은 것을 개선할 수 있는 방법론을 얻을 수 있다.

  • 네번째 세션, Reactive로 달리는 Kafka

    • 이번 세션은 KafkaReactive API를 제공하는 Reactor Kafka에 대한 내용을 소개하는 세션이었다. 그리고 실무에서 적용한 사례 또한 소개해주셨다. 내용이 다소 복잡해서 이해하기 어려울 수 있지만 이런 게 있구나! 정도만 이해하고 가도 괜찮은 소득이 될 거라고 말씀해주셨다.

    • Kafka 그리고 Spring

      • Kafka는 간단히 얘기하면 메세지 큐이다. 그런데 사용 방법에 따라 Storage로 사용할 수도 있고 Buffer로도 사용할 수도 있다.

      • Spring KafkaSpring처럼 토픽만 지정해두면 원하는 로직을 처리할 수 있다.

      • 하지만 Spring Kafka는 한 번에 하나의 메세지밖에 처리하지 못하는 제약이 있다.

      • 이런 제약을 해결하기 위해 Reactor Kafka가 등장했다.

      • 그럼 Spring Kafka는 더 이상 사용하지 않는가? 아니다. 최근 업데이트에서 Spring KafkaReactor Kafka가 포함되었다고 한다.

    • Reactor Kafka를 이용해서 실제 실무에 적용한 사례를 말씀해주셨는데, Reactor Kafka를 통해서 최악의 경우(1K 이상의 서버에서 동시다발적으로 이벤트가 감지되거나 해당 이벤트가 짧은 기간 동안 수차례 반복하는 상황)가 발생하더라도 통지에 지연이 발생하지 않고 각 이벤트가 상호 독립성을 보장할 수 있었다고 한다.

    • Mono/Flux, Kafka, Observable에서 사용할 수 있는 연산자에 대한 내용도 얘기해주셨고, 이를 이용해서 데이터를 모아서 처리하는 법에 대한 얘기도 해주셨다.

    • 적용하면서 얻은 몇가지 결론

      • 모든 것을 공짜로 해결할 수는 없다. -> 사용하기에 까다로운 부분이 많다.
    • Reactor Kafka에 기대한 내용

      • Spring KafkaListener와 비슷한 무언가

      • 지금은 안 되겠지만 언젠가 가능하리라 기대.

    • 세션이 끝난 후에 따로 질문을 드린 부분..

      • 실무에서 온전한 비동기 논블러킹을 위해서 DB에 대한 처리는 어떻게 하였는지 NoSQL을 사용하셨냐는 질문을 드렸는데, 그 당시에는 DB 서버를 따로 두고 비동기 논블러킹이 필요한 로직만 따로 처리하셨다고 하셨다고 한다. 그런데 지금은 사정이 달라졌다고 한다. 이제는 R2DBC을 이용하는 것 대한 긍정적인 생각을 하고 계신다고 한다. 하지만 R2DBC를 이용하면 JPA와 같은 것이 온전하게 동작하지 않을 수 있다고 하신다.
  • 마지막 세션, Spring JPA의 사실과 오해

    • 이 세션 제목을 보고 객체지향의 사실과 오해라는 책 제목이 떠올랐는데, 발표자님이 일부러 오마쥬해서 유도했다고 한다. 세션 내용은 JPA에 대한 내용중에서 연관관계 매핑Spring Data JPA Repository에 대한 사실과 오해를 다루었다.

    • 연관관계 매핑

      • 다중성

        • @OneToOne, @OneToMany, @ManyToOne, @ManyToMany
      • 방향성

        • 단방향, 양방향
      • 단방향 vs 양방향

        • 사실상 단방향 매핑만으로 연관관계 매핑은 이미 완료.

        • 단방향 매핑에 비해 양방향 매핑은 복잡하고 객체에서 양쪽 방향을 모두 관리해주어야 한다.

        • 양방향 매핑은 단방향 매핑에 비해 반대 방향으로의 객체 그래프 탐색 기능이 추가된 것 뿐

      • 대개의 경우 단방향 매핑이면 충분하다.

        • 우선은 단방향 매핑을 사용하고 반대 방향으로의 객체 그래프 탐색이 필요할 때 양방향을 사용
      • 영속성 전이

        • 엔티티의 영속성 상태 변화를 연관된 엔티티에도 함께 적용되는 것.
      • 다대일 단방향 연관관계 매핑의 경우는 작성한 대로 쿼리가 잘 작동한다.

      • 오해 1 - 양방향 매핑보다 단방향 매핑이 무조건 좋다.

        • 일대다 단뱡향 연관관계 매핑에서 영속성 전이를 통한 insert

          • 일대다 관계의 외래키 지정을 위해 추가적인 업데이트 쿼리가 발생.

          • 그래서 일대다 단방향 연관관계 매핑에서는 단방향보다 양방향이 더 효율적이다.

      • N + 1 문제

        • 엔티티에 대한 하나의 쿼리로 N개의 레코드를 가져왔을 때, 연관관계 엔티티를 가져오기 위해 쿼리를 N번 추가적으로 수행하는 문제
      • 오해 1 - N + 1 문제는 Eager Fetch 전략 때문에 발생한다.

        • Fetch 전략을 Lazy로 설정했더라도 연관 엔티티를 참조하면 그 순간 추가적인 쿼리가 수행됨.
      • 오해 2 - findAll() 메서드는 N + 1 문제를 발생시키지 않는다.

        • Fetch 전략을 이용해서 연관 엔티티를 가져오는 것은 오직 단일 레코드에 대해서만 적용
    • Spring Data Repository

      • 스프링 데이터 프로젝트에서 제공

      • Data Access Layer 구현을 위해 반복적으로 작성했던 유사한 코드(boilerplate code)를 줄여준다.

      • 오해 1 - JPA Repository 메서드만으로 조인 쿼리를 실행할 수 없다.

        • Jpa Repository 메서드에서는 _(underscore)를 통해서 조인 쿼리를 실행할 수 있다.
      • 잘 알려지지 않은 사실 - page vs slice

        • Page 인터페이스는 Slice 인터페이스를 상속받고 있다.

        • Page를 사용할 경우 Count 쿼리를 실행하지만, Slice를 사용할 경우 Count 쿼리를 실행하지 않는다.

        • 그렇기 떄문에 Slice를 사용하는 것이 성능적으로 효율적인 코드를 작성할 수 있다.

      • 오해 2 - Jpa Repository 메서드로는 DTO Projection을 할 수 없다.

        • 가능하다.

        • 클래스 기반, 인터페이스 기반, 다이나믹 기반으로 가능하다.

    • 요약

      • 연관관계 매핑

        • 사실상 단방향 매핑만으로 연관관계 매핑은 이미 완료

        • 대개의 경우 단방향 매핑이면 충분하다.

        • 일대다 단방향 연관관계 매핑에서 영속성 전이를 사용할 경우 양방향으로 변경

      • Spring Data Jpa Repostiory

        • JpaRepository 상속 -> 왠만한 CRUD, Pageing, Soring 메서드 사용

        • 메서드 이름 규칙을 통한 쿼리 생성 -> 이름 규칙에 따라 인터페이스에 메서드 선언만 하면 쿼리 생성

        • JPA Repository 메서드에서도 다양한 DTO Projection 지원.

    • 결론

      • 여기서 설명한 사실과 오해가 많은 실수를 제거하는데 도움이 될 수 있었으면 좋겠다.

마치며

이번에 처음으로 큰 규모의 컨퍼런스에 참여할 수 있었는데, 왜 사람들이 큰 규모의 컨퍼런스에 가는지 알수 있는 좋은 기회가 되었다. 편의시설이 너무 편해서 좋았다. WIFI는 물론이고, 큰 공간에서 커다란 스크린과 마이크를 통해서 쾌적한 세션을 들을 수 있었고, 뒤쪽 자리에서 세션을 들었어도 질의·응답을 마이크로 진행하기 때문에 소통 또한 편리했다. 그리고 다양한 부스와 핸즈 온 랩과 같은 즐길 거리가 많아서 다양한 방식으로 즐거운 시간을 보낼 수 있었다. 그리고 규모가 크다 보니까, 다양한 주제를 가진 세션이 많아서 관심 있는 세션을 골라 들을 수 있다는 부분이 제일 마음에 들었다. 부가적으로 많은 기념품과 당 떨어질 틈 없이 간식을 제공해주었던 점도 좋았다. 다음에는 서울에서 열리는 여러 컨퍼런스에도 참여해보고 싶다. (다음에도 참여할 기회가 있겠지?) 처음이라 많이 낯설었고 많이 요란했던 후기를 마무리한다. 혹여나 여기까지 읽어주신 분이 계신다면 읽어주셔서 감사드립니다.