될때까지

((과제1)) 프리온보딩 DAY 2 본문

프로젝트/프리온보딩

((과제1)) 프리온보딩 DAY 2

랖니 2022. 10. 5. 10:44
728x90

지난 포스팅에 이어서 작성합니다 ➡️ 프리온보딩 DAY1

 

((과제1)) 프리온보딩 DAY 1

# 1 : URL 생성 특정 회원에 대한 측정 기록과 측정 데이터를 생성하는 기능을 만들고 있다. 처음 생각했던 URL은 /users/:userId/measurement-data 였다. 하지만 index.js에서 라우팅을 할 때 가운데에 변수값

i-c-a-n-d-o.tistory.com

 

 

# 1 : URL 생성

내가 맡은 기능은 /measurement-data/user/:userId 처럼 작성하는 게 RESTful하다고 의견을 모아서 이처럼 진행한다.

# 2 :  트랜잭션 처리

측정 기록 및 측정 데이터 업로드 및 삭제 시 트랜잭션이 요구되는데 mysql에서 처리할 수도 있고 CASCADE옵션으로 처리할 수도 있다. 오 그러네 CASCADE로 애초에 처음부터 처리할 수도 있구나 왜 그생각을 못했을까!! 심지어 CASCADE는 1차 프로젝트 코드를 살펴볼 때 조사했던 부분인데 유레카! 해당 스텝은 담당 기능 구현해야하는 팀원들과 트랜잭션을 구현할 때 추후 의논하기로 했는데, 우리팀은 그냥 코드로 작성하기로 했다.

 

# 4 : 데이터 종류마다 다른 유효성

내부에서 발생한 500에러는 안된다고 적혀있다. 이에 따라 자세한 예외처리를 해주도록 얘기했다.
최대한 프론트로부터 전달받은 데이터는 모두 검사하는 로직을 작성합시다 👍

유효성 검사하는 로직의 길이가 적지 않았고 여러가지 유효성이 필요하기 때문에 코드를 분리시키기로 했다.
utils 폴더를 만들고 그 내부에서 모든 유효성 검사 로직을 처리하는 파일을 작성했다. 

 

특정 회원에 대한 측정 기록과 측정 데이터 생성하기

측정 기록은 반드시 하나 이상의 측정 데이터와 맵핑된다 => 측정 데이터가 안들어오면 키에러 처리

하나의 측정 기록에 대해 측정 ㄷ이터의 종류 중복되는 경우 없다 => 이미 존재한다고 에러 처리

몸무게 => 유효성 검사

데이터 숫자 5가지 => 유효성 검사

 

 

# 자바스크립트에서의 반복문

1개의 요청에 여러개의 데이터 타입과 벨류값이 담겨있다.
1개의 측정 기록에 데이터 타입값은 중복되면 안된다.
이를 해결하기 위해 배열 반복문을 돌려 해당 데이터 타입이 이미 DB에 저장되어 있는지 하나씩 유무를 확인하도록 로직을 짜고 싶었다.

그래서 자바스크립트 배열 반복문을 검색했고 종류가 왜케 많아? 일단 공부는 나중에 파보고(??) 지금은 프로젝트 부터 진행하는게 급해!!

for가 있고 forEach가 있고 엄청많은데 익숙한 for을 사용해 반복문을 돌렸다.
반복문을 돌면서 해당 바퀴에 해당하는 타입id를 DAO로 보내서 실존하는 데이터 타입인가 확인하고, 실존하는 데이터 타입이라면 유효성 검사를 돌린다. 다 돌고나면 유효성 검사까지 끝난 안전한 데이터라는 이야기지? 해당 데이터를 DAO로 보내 DB에 저장하기 위해 또 배열에 객체로 담아 보내주게끔 로직을 작성했다.

뭔 소린지 모르겠쥬 누구 보라고 작성하는 게 아니라
내가 나중에 면접가거나 해당 코드를 봤을 때 기억을 못할까봐 작성하는 게 9할이기 때문이니까..^_^ 
해당 코드는 깃허브에 있으므로 따로 첨부하진 않겠드아

반복문을 돌면서 해당 데이터 타입을 확인하고, 확인이 끝나면 다시 새 배열에 담아 DAO로 보낸다까지 혼자 생각해낸게 기특했다.
코드가 지저분하고.. 다른 분들이 보기엔 가독성이 떨어질테지만 ㅠㅠ 난 기억에 남아버린 코드가 됐다. 뿌듯해! 💪

 

# 트.랜.잭.션 어쩌면 좋니 1😵‍💫

코드를 작성하기 전에 마인드맵이나 그림을 먼저 그려놓고 시작해야 했/었/다/알/면/서/왜/안/했/니/이/번/에/는!!!

트랜잭션이란? 하나의 논리적 작업을 완료하기 위해 DB에 가해지는 여러개의 쿼리문을 하나의 단위로 바라보는 것을 뜻한다.
지금 진행하고 있는 과제에 적용시켜보자
1개의 측정 기록을 생성하면서 다수의 측정 데이터도 생성해야 한다. 
예를 들어 3개의 측정 데이터를 생성하던 도중에 2번째 데이터 입력 과정에서 오류가 발생하면
이제까지 생성했던 데이터를 모두 날리고 처음으로 돌아가야한다. 

즉, 트랜잭션의 결과는 단 2개 뿐 모두 생성완료 or NOTHING

이제까지 작성한 내 코드에서는 서비스단에서 트랜잭션을 작성할 수 밖에 없지만,
이미 트랜잭션을 구현한 팀원분은 모델에서 구현하셨다.
그리고 나도 왠지 정확히는 모르겠지만 트랜잭션이라는 작업 자체가 DB에서 쿼리문을 보낼 때 해야 맞지 않나 싶었다.
팀 프로젝트인 만큼 그래 다 같이 DB에서 구현하는 게 맞다 싶었고 그렇게 하루 반 작성한 코드를 날리고 급하게 코드를 다 수정했다 ^_^

코드를 다 지우고 다시 작성했는데.. 토나올만큼 스트레스를 많이 받았지만, 뚱땅뚱땅 어떻게든 굴러가는 내 코드가 뿌듯했다.
나중에 보면 코드를 왜이렇게 작성했어 이불킥하겠지?.? 
더 나은 성장을 위한 발악이라고 해두자

본론으로 들어와, 이번에는 TYPEORM의 "QueryRunner"라는 기능을 사용해 트랜잭션 처리를 해줬다.

const createMeasurementData = async (user_id, weight, measurementData) => {
  const queryRunner = myDataSource.createQueryRunner();

  await queryRunner.connect();   
  await queryRunner.startTransaction();  // 트랜잭션 시작

  try {
    // 1. 측정 기록 생성 쿼리문 작성
    await queryRunner.query();

    // 2. 측정 데이터 생성
    await queryRunner.query();

    await queryRunner.commitTransaction();   // 트랜잭션 커밋
  } catch (err) {
    console.log(err);
    
    await queryRunner.rollbackTransaction();  // 트랜잭션 롤백
  } finally {
  
    await queryRunner.release();   // queryRunner 해제
  }
};

비록 내가 작성했던 서비스단의 코드들은 날라갔고 모델단의 코드들도 수정이 요구됐지만, 다행인건 컨트롤러는 안고쳐도 된다는 부분? 이래서 관심사의 분리처럼 기능별로 최대한 나누면 나눌수록 유지보수가 쉽다고 하는 거구나 새삼 다시 느끼게 됐다.

 

# 트.랜.잭.션 어쩌면 좋니 2😵‍💫

증말.... 머리를 엄청 굴렸다. 트랜잭션을 돌리기 위해서 코드를 다 뒤집고, 1개의 함수에 여러개의 쿼리문을 짜는 걸로 바꾼 건 좋다 이거야.
근데 서비스단에서 DAO로 데이터객체를 보낼 때, 여러개의 데이터 타입과 벨류를 전달해주는데 어떻게 데이터를 생성하지?

검색해봤더니 SQL문에서 1번에 여러개의 데이터를 생성할 수 있다고 한다.
이를 구현하기 위해 "SQL INSERT 여러개"라고 검색했고 아래처럼 넣을 수 있다네?

INSERT INTO 테이블이름 (컬럼1,컬럼2...) VALUES (데이터1, 데이터2...)

 

여기서 또 문제. 서비스에서 전달받은 데이터는 1개가 아닌데요 객체형태로 배열에 담겨서 오는데요 이걸 또 어떻게 추출해서 담는담.. 
하나의 빈 배열을 만들고, 반복문을 돌면서 서비스에서 전달받은 데이터의 벨류값을 추출해서 배열에 추가하고 SQL문뒤에 붙여버렸다.

붙이고 나니까 맨 뒤에 , 컴마가 들어갔는데 컴마를 없애기 위해서는 정규식을 사용했다.

이러한 로직을 DAO 모델단에서 작성하는 게 맞나.. 궁금했다.
뭐 어쩄든 SQL문을 날리기 위해 필요한 작업이였으니.. 찝찝하지만 그대로 pr을 올렸다.

 

그럼 이제 마지막 2번째 기능 구현하러 가자 시간이 없드아 ㅠ_ㅠ

728x90