상세 컨텐츠

본문 제목

위코드 기업협업 2주 차 회고

나의 기록/그냥 글

by moonionn 2021. 5. 23. 18:55

본문

머리카락이 자랐어요!

목차

1. 이번 주 직면했던 문제

2. 해결 과정

3. 아쉬운 점

 

-저번주 회고 내용 중 일부- 이자 이번주 플래그

 


 

1. 이번주 직면했던 문제

자바스크립트가 문제였다.

저번주, 기획을 갈무리 짓고 서버리스 개념을 익히고 나서

이번 주에는 본격적으로 코드를 만지기 시작했습니다.

결론부터 말하자면 비동기 동기에게 얻어맞느라 정신없던 한 주였습니다.

원하는 대로 코드가 돌아가도록 하는 데에도 땀을 뻘뻘 흘리느라,

일단은 뭐라도 실행되도록 하는 것이 이번 주 목표였습니다. (효율성은 미래의 나에게 맡긴다.)

새벽에 거의 울기 일보직전까지 갔던 그 기분... 잊지 모태...

 

처절한 로그 기록. 코드 실행 순서가 뒤죽박죽

 

옆집애랑 비교하기 시작

 

문제 원인

지금 구현중인 기능은 survey 기능입니다.

하나의 survey는 여러 page를 가지고,

하나의 page는 여러 question을 가지고,

하나의 question은 여러 choice를 가질 수 있습니다.

 

 

그러다 보니 가장 안쪽부터 들어가 DB작업을 해줘야 했는데,

for 문
  for 문
    for 문
      DB 작업(비동기 작업) 시작
        .then()
          .then()
          ...

이러다 보니 코드를 컨트롤하기가 쉽지 않았습니다.

(이 문제는 javascript의 async await와 모델링 보수공사로 해결됩니다.)

 

 


 

2. 해결 과정

2-1. 모델 보수 공사

현재 사용중인 DB는 몽고디비입니다.

정규화를 먼저 한 뒤 비정규화 과정을 거치는 방식으로 모델링을 했습니다.

정규화 방식의 모델링 구도. SQL을 사용했더라면 테이블이 최소 8개는 나왔을 것.

 

survey, page, question, choice를 하나의 document 안에 넣을 수도 있었겠지만

너무 트리구조가 복잡해질 우려가 있었고, 

또 투표를 할 때에는 question과 choice정보만 있어도 되기 때문에

survey - page와 question - choice를 따로 묶었습니다.

 

문제는, 딱 여기까지만 했으면 괜찮았을 텐데

choice별 count(투표수)를 aggregate할 때 굳이 question 정보가 필요할까?

투표를 할 때 굳이 question정보가 필요할까? 그냥 choice id만 있어도 되는 거 아닌가?

choice는 독립적으로도 존재가치가 있을 수 있어! 라는 생각이 들기 시작하며

(자꾸 쪼개려는 습관이 자동으로 나온 듯?)

 

결국 세 개의 document가 탄생했습니다.

초기 모델링. 나중에는 document2와 document3를 하나로 묶었다.

 

choice를 독립적인 document로 받으려다 보니 

불필요한 중첩 for문 속 비동기 작업을 하나 더 거쳐야 했습니다.

이 문제는 시니어분이 다시금 document의 독립성에 대한 의문을 제기하시며 해결되었습니다.

결국 DB 접근 방식의 문제였던 것 같습니다.

쪼개느냐 합치느냐!

 

2-2. async await

then과 catch로만 중첩 for문 속 비동기를 제어하면 코드의 가독성이 떨어지는 듯했습니다.

그리고 계속해서 "이렇게 하는 게 맞나? 아닌 거 같은데"라는 마음의 소리가 귓가에 맴맴 돌았습니다.

// 이번주 초기에 짠 코드 일부

connectToDB()
  .then(() => {
    Survey.findById(surveyId)
      .then((survey) => {
        survey.pages.forEach((page, pageIdx) => {
          page.questions.map((questionId, questionIdx) => {
            return Question.findById(questionId)
              .then((question) => {
                page.questions[questionIdx] = question;
                if (questionIdx === page.questions.length - 1) {
                  return page;
                }
              })
              .then((modifiedPage) => {
                survey.pages[pageIdx] = modifiedPage;
                if (
                  pageIdx === survey.pages.length - 1 &&
                  questionIdx === page.questions.length - 1
                ) {
                  return res.status(200).json({ survey: survey });
                }
              })
              .catch((error) => {
                console.log(error);
                return res.status(400).json({ ERROR: error });
              });
          });
        });
      })
      .catch((error) => {
        console.log(error);
        return res.status(400).json({ ERROR: error });
      });  
  })

 

결국 회사분들께 도움을 요청하게 되었습니다.

 

귀띔해주신 것 중 가장 유용했던 건 for await 문이었습니다.

for await은 반복문 내의 모든 비동기 작업을 순차적으로 처리합니다.

exports.postSurvey = async (req, res, next) => {
  const { responses } = req.body;
  // 중간생략

  for await (let response of responses) {
    const question = await Question.findById(response.questionId)
      .select("choices")
      .exec();

    // 중간 생략
    
    question.save();
}

 

처음에는 Promise.all()도 써보았는데 제 의도대로 작동하지 않았었습니다.

이유는 Promise.all()과 for await의 차이점을 모르고 쓰려했기 때문인데,

제가 원한 건 직렬 처리지, 병렬 처리가 아니었기 때문입니다.

 

그리고 병렬처리가 가능하다는 점을 알게 된 후 제 머리는 더 복잡해지기 시작했습니다.

어라? 병렬 처리? 멀티 스레딩이 되는 건가 그럼?
아니 내가 아는 자바스크립트는 단일 스레드 기반인데?
시분할 시스템.. 뭐 그런 건가? 원래 그런 것도 병렬 처리라고 하는 건가?
아니 잠깐. 애초에 Web API나 Node API는 어디서 돌아가지?
아니. 애초에 왜 자바스크립트는 단일 스레드 기반이지?????

 

이렇게 또 앞으로 공부해야 할 것들이 계속해서 생겨나는 중입니다.

 


 

3. 아쉬운 점

알고 쓰는 것이냐?

어떤 특정 기술을 선택할 때, 많은 개발 입문자들이 고민해볼 필요가 있는 문제인 것 같습니다.

물론 완벽히 이해하고 쓸 수는 없겠지만,

누군가 "알고 쓰는 거니?"라고 물었을 때, 나의 의견을 피력할 수는 있어야 하지 않을까 싶습니다.

지금까지 정해진 기술 스택, 정해진 방식대로 개발을 공부하다 보니 그런 부분을 놓쳤었습니다.

 

단적인 예시로, 현재 몽구스를 쓰고 있는데,

"왜 몽구스를 쓰는지?"라는 질문을 받았을 때 아차 싶었습니다.

머릿속에서는 "편하니까! 인기 있는 odm이니까!"가 떠올랐지만

정확히 다른 odm들과 어떻게 다른지, 날 것의 mongoDB와 어떻게 달라서 편한지 설명하지 못했습니다.

 

내가 안 좋은 습관을 가지고 있었구나, 라는 걸 알게 된 한 주였습니다.

 

 

마무리는 이번 주 읽어본 동기 비동기 공부자료로...

https://www.nextree.co.kr/p7292/

 

Node.js: 비동기 프로그래밍 이해

대부분의 기업형 애플리케이션은 중앙의 서버에서 동작합니다. 이러한 서버는 Web을 위한 HTTP 서버 또는 소켓 통신을 위한 네트워크 서버 등이 있습니다. 서버는 중앙집중형태로 클라이언트의

www.nextree.co.kr

https://stackoverflow.com/questions/25082867/how-are-promises-implemented-in-javascript-without-threads

 

How are Promises implemented in Javascript without threads

Recently, I have been seeing the concept of Promises being implemented in AngularJS and JQuery. I have seen the implementation of a Futures in Java as in code below, however this requires concept of

stackoverflow.com

https://stackoverflow.com/questions/30823653/is-node-js-native-promise-all-processing-in-parallel-or-sequentially

 

Is Node.js native Promise.all processing in parallel or sequentially?

I would like to clarify this point, as the documentation is not too clear about it; Q1: Is Promise.all(iterable) processing all promises sequentially or in parallel? Or, more specifically, is it the

stackoverflow.com

 

관련글 더보기

댓글 영역