카테고리 없음

내일배움캠프 12주차 화요일 TIL

news0516 2025. 1. 14. 21:00

문자열 s의 길이가 4 혹은 6이고, 숫자로만 구성돼 있는지 확인해 주는 함수, solution을 완성하세요. 예를 들어 s가 "a234"이면 False를 리턴하고 "1234"라면 True를 리턴하면 됩니다.

function solution(s) {
    let arr = s.split('');
    if (arr.length === 4 || arr.length === 6) {
        for (let i = 0; i < arr.length; i++) {
            if (isNaN(arr[i])) {
                return false;
            }
        }
        return true;
    } else {
        return false;
    }
}



행렬의 덧셈은 행과 열의 크기가 같은 두 행렬의 같은 행, 같은 열의 값을 서로 더한 결과가 됩니다. 2개의 행렬 arr1과 arr2를 입력받아, 행렬 덧셈의 결과를 반환하는 함수, solution을 완성해 주세요.

function solution(arr1, arr2) {
    let answer = [];
    for (let i=0 ; i<arr1.length; i++){
        answer[i] = []
        for (let j=0 ; j<arr1[0].length; j++){
            answer[i][j] = arr1[i][j] + arr2[i][j]
        }
    }
    return answer;
}



음식점별 리뷰 조회



파라미터로 받은 restautantId를 통해 기존에 작성한 서버 측 조회 API를 호출하여 db의 음식점별 리뷰를 조회하였다.

async function fetchReviews(restaurantId) {
  try {
    const response = await fetch(
      `/api/users/me/restaurants/${restaurantId}/reviews`,
    );
    if (!response.ok) {
      throw new Error('네트워크 응답이 좋지 않습니다.');
    }
    const data = await response.json();
    const reviews = data.data; // 'data' 속성에서 리뷰 배열 추출

    // 리뷰가 배열인지 확인
    if (!Array.isArray(reviews)) {
      throw new Error('리뷰 데이터가 배열이 아닙니다.');
    }

    displayReviews(reviews);
  } catch (error) {
    console.error('리뷰를 가져오는 중 오류 발생:', error);
  }
}

function displayReviews(reviews) {
  const reviewsContainer = document.getElementById('reviewsContainer');
  reviewsContainer.innerHTML = ''; // 기존 내용 초기화

  reviews.forEach((review) => {
    const reviewElement = document.createElement('main');
    reviewElement.className = 'container';
    reviewElement.innerHTML = `
      <div class="reviewContainer">
          <article id="image">
              <img src="${review.media}" alt="Review Image" style="width: 100%; height: 100%;">
          </article>
      </div>
      <div class="content">
          <article id="star">${'★'.repeat(review.star)}</article>
          <article id="content">${review.content}</article>
      </div>
    `;
    reviewsContainer.appendChild(reviewElement);
  });
}

// 페이지 로드 시 리뷰 가져오기
window.onload = () => {
  const restaurantId = '1'; // 테스트용
  fetchReviews(restaurantId);
};


호출과정에서 오류가 있었지만, validation으로 설정한  서버로그의 오류메시지를 통해 해결 후 진행하였다.

  // 내 모든 리뷰
  // data : userId
  findAllMyReviews = async (data) => {
    const { userId } = data;
    console.log('서비스 계층 : 전달된 사용자 ID:', userId);
    if (!Number.isInteger(userId)) {
      console.error(MESSAGES.REVIEW.SERVICE.ERROR_USER, {
        userId: userId,
      });
      throw new Error(MESSAGES.REVIEW.SERVICE.NOT_FOUND_ERROR);
    }
    // 저장소(Repository)에게 데이터를 요청합니다.
    const reviews = await this.#repository.findAllMyReviews(userId);
    console.log('서비스계층 : 사용자 ID로 조회된 리뷰 데이터:', reviews);

    // 본인의 리뷰만 조회 가능
    // if (reviews.userId !== userId)
    //   throw new Error(MESSAGES.REVIEW.SERVICE.NOT_FOUND_ERROR);

    reviews.sort((a, b) => {
      return b.createdAt - a.createdAt;
    });

    if (!reviews) {
      throw new Error(MESSAGES.REVIEW.SERVICE.NOT_FOUND_REVIEW);
    }

    return reviews.map((review) => {
      return {
        restaurantId: review.restaurantId,
        paymentId: review.paymentId,
        userId: review.userId,
        reviewId: review.reviewId,
        content: review.content,
        star: review.star,
        createdAt: review.createdAt,
      };
    });
  };

어차피 액세스 토큰을 통한 인증 후 전달받는 객체에서 user 데이터를 전달받기 때문에, 오류가 발생하는 유효성 검사는 제외 후 진행하였다.

이후 추가로 작성되어 있던 userId를 통해 내 리뷰를 조회하는 API를 호출하여 띄우는 내 리뷰 페이지를 구성하였다.

 

async function userReviews() {
  try {
    const response = await fetch('/api/users/me/reviews', {
      method: 'GET',
      credentials: 'include', // 쿠키 전송 허용
    });

    if (!response.ok) {
      throw new Error('네트워크 응답이 좋지 않습니다.');
    }
    const data = await response.json();
    const reviews = data.data; // 'data' 속성에서 리뷰 배열 추출

    if (!Array.isArray(reviews)) {
      throw new Error('리뷰 데이터가 배열이 아닙니다.');
    }
    displayReviews(reviews);
  } catch (error) {
    console.error('리뷰를 가져오는 중 오류 발생:', error);
  }
}


// 리뷰 목록을 HTML로 표시
function displayReviews(reviews) {
  const reviewsContainer = document.getElementById('reviewsContainer');
  reviewsContainer.innerHTML = ''; // 기존 내용 초기화

  reviews.forEach((review) => {
    const reviewElement = document.createElement('div');
    reviewElement.className = 'reviewsContainer';

    // Restaurant Name과 createdAt 정보 표시
    const restaurantName = review.restaurantName || 'Restaurant Name';
    const createdAt = new Date(review.createdAt).toLocaleDateString(); // 날짜 포맷 (필요에 따라 수정)

    reviewElement.innerHTML = `
       <main class="container">
        <article id="title">${restaurantName}, ${createdAt}</article> <!-- Restaurant Name과 createdAt 동적 표시 -->
        <div class="review">
          <div class="reviewContainer">
            <article id="image">
              <img src="${review.media || 'default-image.jpg'}" alt="Review Image" style="width: 100%; height: 100%;">
            </article>
            </div>
            <div class="content">
             <article id="star">${'★'.repeat(Number(review.star))}</article>
             <article id="content">${review.content}</article>
             </div>
            <div class="button">
              <button id="button" onclick="reorder(${review.reviewId})">재주문</button>
              <button id="button" onclick="editReview(${review.reviewId})">수정</button>
              <button id="button" onclick="deleteReview(${review.reviewId})">삭제</button>
             </div>
        </div>
      </main>
    `;

    reviewsContainer.appendChild(reviewElement);
  });

window.onload = () => {
  userReviews();
};

}



이후 임시 구성한 수정 버튼을 통한 수정 기능을 개발하였다.
이때 내 리뷰 조회 시 얻은 리뷰 정보 중 reviewId 활용을 위해 얻은 데이터를 전역변수로 선언하고,
수정 버튼 클릭 시 전역변수로 선언된 리뷰 데이터를 사용하도록 구성하였다.

// API 호출 및 리뷰 목록 가져오기
let currentReviewId = null; // 현재 수정할 리뷰 ID
let allReviews = []; // 전체 리뷰 데이터를 저장하는 전역 변수

function closeModal() {
  document.getElementById('editModal').style.display = 'none';
}  // 모달 닫는 함수 추가

async function userReviews() {
...
    const reviews = data.data; // 'data' 속성에서 리뷰 배열 추출
...
    // 전체 리뷰 데이터를 전역 변수에 저장
    allReviews = reviews;
...
}
...


// 수정 버튼 클릭 시 모달 열기
function editReview(reviewId) {
  currentReviewId = reviewId; // 수정할 리뷰 ID 저장

  // 전역 변수에서 해당 리뷰 데이터를 검색
  const review = allReviews.find((r) => r.reviewId === reviewId);
  if (!review) {
    console.error('리뷰를 찾을 수 없습니다.');
    return;
  }

  // 기존 리뷰 데이터 채우기
  document.getElementById('editContent').value = review.content;
  document.getElementById('editStar').value = review.star; // 별점 설정

  // 모달 창 열기
  document.getElementById('editModal').style.display = 'block';
}



버튼 클릭 시 모달창을 열어 수정사항을 입력하고, saveReview 함수를 통해 리뷰 업데이트 API를 호출하여 db에 업데이트를 반영하고 있다.

function saveReview() {
  const content = document.getElementById('editContent').value;
  const star = document.getElementById('editStar').value;

  // 전역 변수에서 수정 대상 리뷰 데이터 업데이트
  const reviewIndex = allReviews.findIndex(
    (r) => r.reviewId === currentReviewId,
  );

  if (reviewIndex === -1) {
    console.error('수정할 리뷰를 찾을 수 없습니다.');
    return;
  }

  // 업데이트된 데이터
  allReviews[reviewIndex] = {
    ...allReviews[reviewIndex],
    content: content,
    star: star,
  };

  // 서버에 수정된 데이터 전송
  fetch(`/api/users/me/reviews/${currentReviewId}`, {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      content: content,
      star: star,
    }),
  })
    .then((response) => {
      if (!response.ok) {
        throw new Error('리뷰 수정에 실패했습니다.');
      }
      return response.json();
    })
    .then(() => {
      console.log('수정 성공');

      displayReviews(allReviews);  // 수정된 데이터로 화면 갱신
      console.log('전송 데이터:', {
        content: content,
        star: parseInt(star, 10),
      });

      closeModal();  // 모달 창 닫기
    })
    .catch((error) => {
      console.error('리뷰 수정 중 오류 발생:', error);
    });
}

// 페이지 로드 시 리뷰 가져오기
window.onload = () => {
  userReviews();
};

 

수정 모달 창

 

test1111111111 >>> test10101010101


이후 팀원에게 부탁하여 restautantId로 음식점 이름을 요청하는 API를 추가 구성하였고, 해당 API를 통해 리뷰별 음식점 이름을 표시하는 등의 추가처리가 필요한 상태이다.

메뉴 선택 페이지

해당 메뉴선택 페이지도 임시로 API 통해 restautantId에 따른 메뉴 조회까지만 완료하였고, 추가 작업이 필요한 상태로 오늘 작업을 마무리하였다.

오늘 작업 중 느낀 것은 규모가 매우 크지 않은 프로젝트이기 때문에 오히려 3 계층 아키텍처로 구성된 구조가 복잡성 측면의 단점이 있다고 생각했다. 어제부터 오늘 오전까지 한 가지 오류(내 리뷰 조회 API 호출 x)에 매몰되어 있었는데, 온갖 서버로그를 직접 콘솔로그를 띄어 오류를 찾는 과정에 시간이 많이 소모되었다.
반대로 원하는 API를 추가하거나, 다른 팀원들이 작성한 코드를 직관적으로 이해할 수 있다 느껴서, 여러 가지 개발 방법론의 장단점이 있겠다는 생각이 들었다.