레저큐 인턴기 6편 – 백엔드 개발 도전! (2)

웹API 컨트롤러의 레이어드 아키텍쳐

전편에서 이어집니다…

가자고 웹API의 컨트롤러는

  • Controller 레이어: 가장 상위에서 유저의 리퀘스트(request)를 받고 리스폰스(response)를 돌려줌.
  • Service 레이어: Controller 밑에서 실질적인 비지니스 로직의 구현을 담고 있음.
  • Repository 레이어: DB와의 인터페이스를 담당.

이상의 세개 레이어(layer)로 구성되어 있다. 이렇게 하나의 시스템을 여러개의 레이어(층)로 분리하고 차곡 차곡 쌓아 올라가는 식으로 개발하는 방식을 ‘레이어드 디자인 패턴(Layered Design Pattern)’이라고 부르는데, 소프트웨어 엔지니어링에서 가장 보편적인 디자인 패턴 중 하나이다.

여러가지 이유가 있겠지만 이렇게 레이어를 나누는 가장 중요한 이유는

  1. 규모가 큰 시스템을 여러개로 모듈화하여 한 모듈의 문제가 시스템 전체로 번져나가는 것을 막음과 동시에 각 모듈을 쉽게 교체하기 위함이자, (종속성의 최소화, 재사용성)
  2. 오로지 하나의 이슈를 해결하도록 분리된 각 층을 추상화함으로써 컴포넌트 간에 인터페이스를 쉽게 하고 개발을 용이하게 하기 위함이다. (표준의 지원)

Screenshot 2016-09-06 14.59.49.png
가자고 웹API의 컨트롤러는 Controller, Service, Repository 등의 레이어로 구성된 레이어드 아키텍쳐(Layered Architecture)를 따른다.

레이어드 아키텍쳐 관점에서 개발 미션 바라보기

이쯤에서 나의 개발 미션이 무엇이었는지 다시 떠올려보자.

입력한 조건에 따라 DB에서 서비스 운영에 필요한 통계자료를 추출하는 웹 API를 새로 만들기

개발 미션을 가자고 웹API 컨트롤러의 레이어드 스트럭쳐 관점에서 바라보면 구현 단계를 가장 밑에서부터 네단계로 쌓아 올라가는 것으로 압축할 수 있다.

  1. Model 클래스 구현: 쿼리로 조회한 데이터를 담을 모델 클래스 만들기.
  2. Repository 구현: 데이터 추출 SQL 쿼리를 자바로 구현하기.
  3. Service 구현: 비지니스 로직을 코드로 구현하기. 즉, Repository에서 쿼리로 가져온 데이터들을 어떻게 가공하고 Controller에 다시 돌려줄 것인지 고민하기.
  4. Controller 구현: API에 URL 자원을 RESTFul하게 할당하고 유저의 리퀘스트 처리. 리스폰스 리턴.

사실 Repository 레이어에서 DB로부터 데이터를 가져오는 것을 빼고는 복잡할 것이 없는 작업이다.

  • Model 클래스에서는 내가 필요한 정보(DB의 필드에 해당한다)가 무엇인지 고민하고 이 값들을 담을 수 있는 변수들을 멤버로 가지고 있는 클래스들을 새로 만들어주면 된다. (클래스 만들기는 자바의 기본!)
  • Service에서는 Repository에서 돌려준 데이터들의 묶음(Collector: List, Map 등…)을 엑셀 템플릿과 엑셀 라이브러리를 이용해서 엑셀 파일로 출력해주면 된다. (엑셀 라이브러리만 가져다 쓰면 된다!)
  • Controller는 사실상 스프링 프레임워크에서 제공되는 라이브러리들을 이용하면 자바 어노테이션과 몇 줄 안되는 코드로 구현이 가능하다. (스프링이 알아서 다 해준다…)

자 그렇다면 이번 개발 미션의 핵심이 무엇인지 드러난다. Repository에 SQL SELECT 쿼리를 자바로 구현하는 것이 이번 개발 미션에서 가장 중요한 부분이다.

JOOQ로 SQL SELECT 쿼리를 자바로 구현하기

가자고 어플리케이션은 DB 인터페이스에 JPA(Java Persistence API: 자바 영속성 API)와 JOOQ(Java Object Oriented Querying)를 이용한다.

JPA는 자바 진영의 표준 ORM(Object-relational mapping) 기술로, 관계형 DB를 객체지향패러다임 언어인 자바에서 쓰기 위한 맵핑을 담당하는 기술이다. 표준 영속성(여기서 영속성이란 프로그램이 종료되어도 사라지지 않는 속성, 즉 DB 데이터의 속성을 의미한다) API인 만큼 자바를 이용해서 백엔드 개발을 하는 개발자들이 익히 잘 알고 있는 기술이다.

반면에 JOOQ는 다소 생소한 이름일 수 있다. 스위스 취리히 소재의 스타트업 Data Geekery이 운영하고, 개발하고 있는 JOOQ는, SQL 쿼리를 자바로 구현해야 하는 상황에 이용하는 라이브러리이다. 즉, 미리 작성해 놓은 SQL 쿼리를 그대로 자바로 옮기고 싶다거나, 아니면 JPA로는 구현이 힘든 매우 복잡한 SQL 쿼리를 짜야하는 경우에 멋진 대안이 된다. (참고로 이런 목적으로 사용하는 또 다른 라이브러리 중에 유명한 것이 iBatis 란 기술이다. 가자고 시스템에도 iBatis를 사용한 적이 있었지만 지금은 대부분 JOOQ로 대체하고 있다.)

좀 더 와닿는 코드 예제로 살펴보자. 백엔드 어플리케이션에서 아래와 같은 SQL 쿼리를 사용할 일이 있다고 가정하자. (코드 출처는 wikipedia.org – Java Object Oriented Querying)

위의 SQL 쿼리는 STATUS가 ‘SOLD OUT’인 BOOK 들의 AUTHOR 정보를 가져오는 테이블이다. JOOQ를 이용해서 자바로 변환하면, 이렇게 짤 수 있다.

JOOQ를 이용하면, SQL 문법과 상당히 유사한 자바 코드로 SQL 쿼리를 작성 할 수 있다. 자 그렇다면 이제 JOOQ를 이용해서 내가 작성해두었던 SQL SELECT 쿼리들을 자바로 옮길 차례다.

keep-calm-and-code-on
나우 잇츠 타임 포 코딩!

하나만 간단히 살펴보자. 가자고 서비스 운영에 필요한 정보 중에 특정 아이템을 구매한 고객들의 이름, 이메일, 전화번호를 알아야 하는 경우가 있었다. 이 리스트를 추출하기 위해서 아래와 같은 SQL SELECT 쿼리를 작성했었다.

이 것을 새로 생성한 Repository 클래스의 public List<FrontUser> getItemUserStat(List<String> itemCode) 메서드에 구현했다.

잠시 코드를 살펴보자. 먼저 해당하는 SQL SELECT 쿼리를 JOOQ를 이용해서 만들고 나서, fecthInto(FrontUser.class) 메서드를 호출했다. 이 메서드는 FrontUser 라는 모델 클래스의 리스트(List<FrontUser>)를 리턴하는 것을 확인 할 수 있다. 따라서 이 메서드에, 조회하고 싶은 아이템들의 itemCode를 List<String> 로 전달하면 해당하는 사용자의 정보를 FrontUser 모델 클래스의 리스트로 얻을 수 있다.

이렇게 JOOQ로 쿼리를 짜면 쉽고 간단하게 쿼리를 만들 수 있다. IDE의 자동완성 기능의 도움을 받는다면 일일이 JOOQ의 문서나 매뉴얼을 뒤져보지 않아도 그 자리에서 바로 SQL 쿼리를 자바로 옮길 수 있다.

이렇게 완성된 Repository 메서드를 이제는 거꾸로 Service에서 이용하고, 마지막으로 Controller에서 Service 메서드를 호출하면 SQL로 DB에 쿼리를 날렸을 때와 동일한 데이터를 자바 객체 묶음(Collector: List, Map 등등)으로 얻을 수 있었다. Controller의 각 메서드에 이제 RESTFul 한 URL을 할당해주기만 하면 웹 API가 완성된다!

새로운 세계

그렇게 작성한 나의 첫 백엔드 코드를 커밋(Git Commit)하고, 마침내 나의 풀리퀘스트(Pull Request)가 master 브랜치에 머지(merge) 되는 순간, 새로운 세계가 열렸다! 얕게는 매일 SQL 쿼리를 짜고 DB에서 데이터를 긁어오는 반복 노동으로부터의 해방된 것이고, 깊게는 백엔드 개발의 프로세스에 대한 경험을 해보게 된 것이다. 무엇보다 기뻤던 것은 드디어 가자고 프로젝트에 유의미한 기여를 할 수 있게 되었다는 사실이었다.

물론 이 것은 시작일 뿐이었다. 작동하는 웹 API를 만들어보기는 했지만, 웹 어플리케이션이라는 것이 무엇인지, 어떻게 동작하는지 제대로 이해하게 된 것도 아니고, Spring, JOOQ, JPA와 같은 기술들의 문서를 숙지하고 개발한 것도 아니고, 더군다나 효율적인 개발 프로세스대로 개발을 해본 것도 아니다. 그렇지만 내가 만든 API가 제대로 가자고 웹 어플리케이션 위에서 동작한 것을 확인했을 때의 즐거움이란 어마어마한 것이었다. 하하! 드디어 나도 이제 웹개발자구나! 🙂

여튼 이렇게 웹 개발의 ‘ㅇ’도 모르고 있었던 내가 DB를 다루고 관리하는 일부터 시작해서 백엔드 어플리케이션을 개발하는 백엔드 개발자의 업무를 경험해보기 까지 1달이 좀 못되는 시간이 걸렸다. 물론 그때는 몰랐다. 백엔드 개발에 더 익숙해지는데까지는 훨씬 더 많은 시간이 걸릴 것이라는 것을…

백엔드 개발 도전! 편 끝. 레저큐 인턴기는 계속 이어집니다…
By EastskyKang