Finance와 함께 - Java로 구현하는 현재가치

이미지
Present Value with Java  이번 Post는 현재가치를 Java로 구현한다. 재무업무 상 필요한 개념이며 우리가 살아가는데 요긴하게 쓰일 수 있으니 꼭 알아가길 바란다. PV(Present Value)  미래에 얻게 될 확실한 부의 가치를 현재의 가치로 환산한 값이다. 줄여서 현가( 現價 )라고 한다.  2000년의 1,000원이 2021년의 1,000원과 동일한 가치를 가지지 않는다. 예를 들어보자.  연 금리가 2%라고 생각하면자. 국민연금 납입기간이 끝나 1억원의 연금을 받으려고 한다. 이 때, 2가지 선택지가 있다.  지금 당장 1억원을 받는다. 2년 후에 이자 붙여서 1억 4백만원을 받는다.  어떤 선택이 더 이득일까? 1번을 선택 후 은행에 저금해보자. 2년 후 2번과 비교했을 때, 1번이 4만원이 더 이득이다. 이처럼 현재의 기준으로 미래를 예측한 가치를 현재가치라고 한다. 기준은 금리, 이자율,...이 있다. 2년 후의 금리로 계산한 최종금액 구현  현재가치를 구하는 공식은 이  Link 를 참조하자. @Test public void calculatePV_just_function () { double interestRate = 0.02d ; double amount = 100000000 ; double year = 2 ; double pv = amount * Math . pow (( 1 + interestRate ), year ); String formattedPV = NumberFormat . getNumberInstance (). format ( pv ); Sy...

Scott 과 함께 - Outer Join 을 Java 로 구현하기.

이미지
Outer Join  이번 Post는 Outer Join을 Java로 구현한다. 이전 Inner Join Post와 동일하게 부서의 Job 별 평균급여를 구하지만, 이번에는 직원이 없는 부서도 같이 출력해야 한다. SQL 부서/Job 평균 급여에 Operations 부서도 추가.  Operations 부서는 직원이 없는 부서라서, Job과 평균급여는 Null이다. Operations의 Job은 Null이고 평균급여는 0으로 Java에서 표현한다. select d . dname , e . job , avg ( e . sal ) from dept d left outer join emp e on d . deptno = e . deptno where 1 = 1 group by d . dname , e . job ; Java 부서 Stream + 직원 Stream  처음 생각했던 방법은 부서 Stream의 map()에서 직원 Stream으로 Job별 평균급여를 가져오려고 했지만 실패 했다. Operations의 직원이 없어 직원 Stream의 결과가 Null이면, Operation이 부서 Stream에서 사라졌다. depts . stream () . map ( department -> employees . stream () . filter ( employee -> employee . getDepartment () == department ) . collect ( Collectors . groupingBy (...)) ); 부서 List + 부...

Scott 과 함께 - Inner Join 을 Java 로 구현하기

이미지
Inner join with Java  이번에는 SQL Join과 집계를 Java로 구현한다. 예제는 부서와 Job별 월급의 평균을 가져오는 것이 목적이다. SQL  Java의 결과는 순서에 상관없이 위 그림과 같이 나타나야 한다. 다만 평균급여는 '*'을 사용해 100단위로 표기한다. select dept . dname , emp . job , avg ( emp . sal ) from emp inner join dept on emp . deptno = dept . deptno group by dept . dname , emp . job order by 1 , 2 ; Java JPQL로 필요한 컬럼 조회 후, Java로 집계.  JPQL로 데이터로 직원들의 부서이름, Job, 급여 데이터를 가져온다. 가져온 데이터를 Collectors.groupingBy로 평균급여를 계산한다.   부서이름, Job, 급여는 객체가 이닌 스칼라 타입이기 때문에 결과는 List<Object[]>이다. 배열보다는 편하게 데이터를 꺼내기 위해서 DTO 객체를 만들었다. public class DeptJobCountDto { private String departmentName ; private EmployeeJob job ; private Double amount ; ... } ... Strin sql = "select new dto.DeptJobCountDto (d.name, e.job, e.salary) from Department d join d.employees e" ; 결과 ...

Scott 과 함께 - Recursive Query 구현하기

이미지
Recursive Query   Recursive Query는 계층형(hierarchical) 데이터를 조회할 때 사용하는 쿼리다. 기업에서 흔히 조직도와 BOM(Bill of Materials)에서 사용한다. Oracle은 'Connect By' 그리고 타 DB는 CTE(Common Table Expressions)로 계층형 데이터를 조회할 수 있다. Java의 경우, Entity를 연결해 Graph탐색할 수 있다. 이번 Post는 JPA로 Employee객체의 조직도를 구현하는 기록을 남긴다. Oracle Native Query 결과.  EMP 테이블은 직원 1명에 관리자 1명으로 구성되어 있다. 관리자는 다른 상위 관리자 1명과 연결한다. 'KING'은 사장님이시기 때문에 관리자 값이 Null이다.   'Connect By' 문장은 연결할 데이터 컬럼을 정의한다. 'Start with'는 계층형 데이터의 시작이 어디인지 알려준다. 'Prior' 은 상향식과 하향식으로 데이터 조회 방향을 결정한다. SELECT LEVEL , lpad ( ' ' , LEVEL * 3 , '.' ) || decode ( LEVEL , 1 , NULL , '└▶ ' ) || e . ename AS hierarchy , e . * FROM emp e WHERE 1 = 1 START WITH e . mgr IS NULL CONNECT BY e . mgr = PRIOR e . empno 상향식 결과 SELECT LEVEL , lpad ( ' ' , LEVEL *...

Scott 과 함께 - Domain을 JPA 로 연결

이미지
Scott Schema To JPA.   이전 Post 는 Oracle DB 의 Scott을 객체로 구현했다. 이번 Post는 JPA와 Scott을 연결한다. 또한 초기 데이터는 Insert 문장이 아닌 JPA로 초기화한다. Entity 연결 이전 Post 에서 Oracle 의 Scott 예제 객체들로 만들어봤다. 이번에는 JPA로 연결해서 DB에 저장되는 것을 확인한다. Employee manager 연결.  DB에서 상위 결재권자는 사번이 들어가지만, 객체는 다른 Employee 객체다. 관리자-직원이 서로 연결할 수 있도록 연관관계를 지정했다. 다음 Post에서 재귀형 데이터 조회 예제를 만들 계획이다. @Entity @Table ( name = "emp" ) public class Employee { ... @ManyToOne ( fetch = FetchType . LAZY ) @JoinColumn ( name = "mgr" ) private Employee manager ; @OneToMany ( mappedBy = "manager" ) private List < Employee > members = new ArrayList <>(); ... } SalaryGrade/SalaryGrades 연결.  SalaryGrades를 EMP 테이블에 급여등급 Column이 만들지 않기 위해 @Transient 로 설정한다. Scott 예제의 기존 Table을 최대한 유지하기 위해서다.   Employee 의 SalaryGrade는 Salary에 따라 변하기 때문에 호출할 때마다 달라진다. Salary 가 바뀌면 바뀐 급여로 나오도록 설정한다. @Entity @Table ( name = "emp...

Spring Integration 과 함께 - 마무리

이미지
마무리...  Spring Integration 예제를 만들며 느낌과 생각을 공유한다. 단순하게 만들자.  Spring Integration 의 IntegrationFlow는 단순하게 만들자. Spring Integration 단일 시스템으로 실행할 수 있고 여러 시스템을 연동해서 사용한다. 연동으로 데이터를 전달할 때, 구성 요소(Transformer, Splitter, Service Activator...)에 지나친 처리로직으로 Blocking이 생기면 지연 문제가 생길 수 있다. (만약 IntegrationFlow가 비동기라면 더 심각할 수 있다.) 길을 만드는 Programming  자바에서 try-catch나 throws로 예외를 처리한다. 이 때, 비즈니스 로직을 멈출 수 있고 우회 방법으로 실행한다. 하지만, Spring Integration 도 errorChannel 혹은 Route 기능을 사용해서 오류를 처리해줄 IntegrationFlow 를 만들자. (드라마 명대사 중 '암세포도 생명(?)' 처럼, 오류도 처리하기 위한 길(路)이 필요하다) DSL로 만들자.  Spring Integration은 3가지로 설정할 수 있다. XML File, @Configuration, 그리고 DSL 이다. 3가지 모두 해본 결과, DSL 이 더 가시적이었다. 물론 STS에서 Spring Integration Component Editor 를 이용하면 그림을 그려준다. 하지만 막힐 때, 인터넷에서 구할 수 있는 답과 예제는 DSL이 더 많고 깔끔했다. 마치며...  약 3주를 하나의 Framework에 꽂혀 본업을 잊을 정도로 재밌게 경험한 것 같다. 삽질도 많아서 지병이 도질 정도로 스트레스를 받았지만, 그래도 나름 의미있는 Back-end 프로그램이었다. 나처럼 고생하는 사람들이 이 글을 통해 포기하지 않고 도움 받길 바란다...

Spring Integration 과 함께 - 실전편(2)

이미지
Spring Integration - Polling Example  이번 post 는 Spring Integration 이 외부 데이터를 가져오는 예제를 만든다. Schedule 을 정해서 주기적으로 데이터를 가져올 수 있어, 개인적인 데이터를 모을 때도 유용하게 쓸 수 있다. 개발환경 JDK : OpenJDK 11 Spring : 2.4.2 DB : h2 구조 환율 가져오는 Flow  환율을 일정한 주기로 Web 에서 가져온다. 가져온 환율을 DB 에 저장한다. 환율.  환율은 이 사이트 를 참조했다. 아래 URL 에서 데이터를 호출하면, 최신 환율 데이터를 EUR 기준으로 가져온다. 데이터 형식은 JSON이다. GET https://api.exchangeratesapi.io/latest DB Tables. Exchange Rate Table 구조 Exchange_rate_meta  Header 정보 역할을 한다. 환율일자, 환율수, 기준통화를 저장한다. 기준 통화는 EUR 이다.   exchange_rate 와 FK 관계를 가진다. 이번 FK 관계는 복잡한 연관관계가 필요없기 때문에, JPA 의 @CollectionTable 를 사용했다.  @Entity @Table ( name = "exchange_rate_meta" ) public class ExchangeRateMetaData { @Id @Column ( name = "exchange_date" ) private LocalDate date ; ...