TIL (ToDay I LearNEd)/K P T (keeP, pRoBlem, Try) & 트러블슈팅

은행 환전 개인과제 트러블 슈팅_TIL

sooyeoneo 2024. 11. 29. 16:01

 

다양한 연관관계, 예외처리, 트랜잭션, JPQL를 활용하여 은행 환전 시스템을 만든다.

 

이를 통해 코드의 안정성과 가독성을 향상시키며, 유지보수가 용이한 구조를 설계하는 방법을 익히고,

고도화된 요구사항을 효과적으로 관리하고 구현하는 능력을 길러보자!

 

개발 전, 공통 조건

  • 모든 테이블은 고유 식별자(ID)를 가진다.
  • 3 Layer Architecture 에 따라 각 Layer의 목적에 맞게 개발
  • CRUD 필수 기능은 모두 데이터베이스 연결 및 JPA를 사용해서 개발
  • 생성, 수정일자는 JPA Auditing 을 통해 관리
  • 주어진 코드에 필요한 기능이 있다면 필수 기능에 없더라도 개발해서 사용
  • Currency 테이블은 달러에 대한 데이터를 가지고 진행
    • 환율 데이터 설정은 현재 기준을 참고

 

기능 구현 🖥

Lv 1. 고객(User)과 통화(Currency) 복잡한 연관 관계 필수

  •  환전 요청 중간 테이블 생성
    •  필드: 고객 고유 식별자, 환전 대상 통화 식별자, 환전 전 금액, 환전 후 금액, 상태
  •  고객과 통화 테이블 간 연관관계
    •  한 고객이 여러 통화로 환전할 수 있고 한 통화는 여러 고객들에 의해 환전될 수 있다.
    •  환전 요청 테이블은 중간 테이블이고 User와 Currency 간 관계를 관리한다.

Lv 2. 환전 요청 CRUD 필수

 C: 환전 요청 수행

  •  환전 대상 통화 식별자가 Currency 테이블에 가지고 있는 환율을 기준으로 환전을 수행
  •  환전 후 금액은 환전 전 금액을 환율로 나눈 결과
  •  환전 후 금액 계산식 : 환전 후 금액 = 환전 전 금액 / 환율`
 
예시 : 
환전 전 금액이 10,000원이고, 환율이 900원/1달러인 경우
환전 후 금액: 10,000원 / 900원 = 11.11
  •  
  • 환전 후 금액에 대해 소수점 두번째 반올림 수행
  •  R: 고객 고유 식별자를 기반으로 특정 고객이 수행한 환전 요청 조회
    •  조건
      •  고객 고유 식별자: 환전 요청 테이블에 있는 User ID
  •  U: 특정 환전 요청 상태를 취소로 변경
    •  상태 값은 normal, cancelled
  •  D: 고객이 삭제될 때 해당 고객이 수행한 모든 환전 요청도 삭제
    •  키워드
      •  영속성 전이, cascade

Lv 3. 예외 처리 필수

  • 모든 상황에 대해 유효성 검사와 예외 처리를 구현하지 않아도 됩니다. 핵심적으로 중요하다고 생각하는 1~2가지 항목에 대해 수행하면 충분합니다.
  •  유효성 검사 추가: 입력 값에 대한 유효성 검사를 추가하여 정책에 맞는 데이터만 취합
    •  3-Layered Architecture 에서 유효성 검사가 어떤 계층의 책임인지 고민해보세요!
    •  이메일, 일자 데이터, 길이 등
    •  키워드
      •  Validation
  •  예외 처리 강화: 적절한 예외 처리 로직을 추가하여 오류 발생 시 사용자에게 명확한 피드백 제공
    •  API 예외처리
      •  키워드
        •  GlobalExceptionHandler
    •  단순히 400, 500 에러코드만 보내지 않고 더 많은 정보를 포함하여 에러 메세지를 전달
      •  요청값의 형식이 맞지 않습니다.
      •  네트워크 요청에 실패했습니다. 다시 시도해주시기 바랍니다.
      •  코드 형태를 고민해봐도 좋겠습니다.
// 예시 형식

{
    "errorCode": "ERR001",
    "errorMessage": "요청값의 형식이 맞지 않습니다."
}

 

Lv 4. PostConstruct 적용 도전

  •  조건
    •  스프링이 구동될 때 통화 테이블에 있는 환율이 0이거나 음수이거나 지정된 범위를 벗어나는 경우
  •  유효하지 않은 값으로 간주하고 로그를 기록하세요.
  •  키워드
    •  @Component, @Slf4j

Lv 5. JPQL 도전

  •  고객의 모든 환전 요청을 그룹화하여 조회
  •  반환해야하는 컬럼
    •  해당 고객이 수행한 환전 요청 데이터들의 총 row 수
    •  해당 고객이 환전을 요청한 총 금액
  •  키워드
    •  @Query, Group By, SUM, COUNT
// 예시 

[
    {
        "count": 3,
        "totalAmountInKrw": 50000.00
    }
]

 

 

 

트러블 슈팅 🎯

본격적인 트러블 슈팅에 앞서, 작은 오류도 회고한다.

 

처음에 fork 받아 온 프로젝트를 clone 받아온 상태였다.
그런데 아무리 깃 레퍼지토리 연동을 하고 코드를 새로 짜도 pull 할 수 있는 내역이 없다고 뜨는 상태였다.


특히나 인텔리제이에서는 git에 연동된 파일에 대해서는 색깔이 표시되는데, 

빨간색은 아직 github에 연동된 시점에서 github에 repository에 올라가지 않은 상태이고 커밋 전이다.(local에 있음)

초록색은 github에 연동된 시점 이후에 새로 생성된 파일들이다.

파란색은 github에 이미 커밋 푸쉬가 된 상태의 파일이며 이후에 수정된 사항이 있는 경우이다.

 

색깔이 없이 하얀색이었다. github repository 연동을 아무리 살펴보아도 똑같이 pull rejected 가 되면서 거부되었다.

 

 

무엇인가 fork 하고 clone 하는 과정에서 경로가 꼬였을 수도 있어서 여러가지 시도해보던 중에

git init을 해보기로 하였다.

빈 깃 저장소인 경우에 조금이라도 무엇인가 남아있을 지도 모른다는 생각과 함께 새롭게 초기화를 하였다.

 

 

빨간 색으로 변경되면서

감격스럽게도 이제 커밋이 가능한 상태가 되었다!!!

 

 

 

 

 

오류 1

 

이제는 ERROR 글씨를 봐도 놀랍지 않고,
바로 entityManagerFactory 파란 밑줄의 글을 오른쪽으로 쭉 드레그해서 Reason : 부분을 찾아보면,
어떤 오류가 있었는지 알 수가 있다.

 

오류 메시지 

Failed to initialize JPA EntityManagerFactory: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is java.lang.RuntimeException: Driver com.mysql.cj.jdbc.Driver claims to not accept jdbcUrl, {DB_URL}

 

application.properties 에서 url 을 입력 하지 않고 {DB_URL} 로 남겨둔 것이 문제였다. 

 

원래 fork로 가져온 코드에는 아래와 같이 되어있는데, 아마도 암호화가 된 것 같다.

spring.datasource.url={DB_URL}
spring.datasource.username=root
spring.datasource.password={DB_PASSWORD}

이 부분은 다음에 다시 적용해보려고 한다.
(현재는 그냥 임의의 값을 입력하여 push하고, application.properties는 commit을 피하고 있다.) 

참조 블로그 : https://youngseo-computerblog.tistory.com/80

 

 

3번 줄의 spring.datasource.url=의 값을 입력해주었다.

 

spring.datasource.url=jdbc:mysql://localhost:3306/currrency_exchange

 

 

설레는 마음으로 다시 실행해보았다.

 

또 ERROR가 떴다. 당황하지 않고 에러 메시지를 끝까지 확인한다.

2024-11-29T09:57:25.417+09:00 ERROR 67483 --- [user-currency] [  restartedMain] o.h.engine.jdbc.spi.SqlExceptionHelper   : Unknown database 'currrency_exchange'
2024-11-29T09:57:25.426+09:00 ERROR 67483 --- [user-currency] [  restartedMain] j.LocalContainerEntityManagerFactoryBean : Failed to initialize JPA EntityManagerFactory: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.SQLGrammarException: Unable to open JDBC Connection for DDL execution [Unknown database 'currrency_exchange'] [n/a]

 

이번에는 데이터 베이스 생성이 안되었다.. 스키마만 create한 상태로 아무것도 하지 않았는데.

JPA는 DB를 자동 생성해주는 게 아니었나? 설정이 잘못 된 건가...

 

혹시몰라서 application.properties을 다시 한 번 확인해보니

currency_exchage에 r이 2개가 아닌 3개가 들어가서 오타가 난 것을 확인하였다.

 

(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄부끄러움은 나의 몫이니 얼른 수정해주었다.

spring.datasource.url=jdbc:mysql://localhost:3306/currency_exchange

 

 

다시 실행해보니 정상 작동이 되는 것을 확인하였다! 

 

 

 

...