[2024.05.10 TIL] 내일배움캠프 19일차 (개인 과제 발전, JS 복습)

My_Code·2024년 5월 10일
0

TIL

목록 보기
23/113
post-thumbnail

본 내용은 내일배움캠프에서 활동한 내용을 기록한 글입니다.


💻 TIL(Today I Learned)

📌 Today I Done

✏️ 개인 과제 발전시키기

  • 리뷰 기능에 대한 CRUD를 구현함

  • 리뷰를 작성하면 작성 데이터를 localStorage에 저장

  • 리뷰마다 고유한 ID를 만들어서 수정, 삭제 시 리뷰들을 구분함

// 리뷰 저장하는 함수
export const saveReview = (id) => {
    let date = new Date();

    let year = date.getFullYear();
    let month = ('0' + (date.getMonth() + 1)).slice(-2)
    let days = ('0' + date.getDate()).slice(-2)
    let hours = ('0' + date.getHours()).slice(-2)
    let minutes = ('0' + date.getMinutes()).slice(-2)
    let seconds = ('0' + date.getSeconds()).slice(-2)

    let day = year + '-' + month + '-' + days + " " + hours + ":" + minutes + ":" + seconds

    const review = {
        movieId: id,
        reviewer: document.getElementById("reviewer").value,
        reviewPass: document.getElementById("review_pass").value,
        reviewContent: document.getElementById("review_content").value,
        dateTime: day
    }
    localStorage.setItem(crypto.randomUUID(), JSON.stringify(review));
    console.log(localStorage);
}


// 리뷰 리스트 로드하는 함수
export const loadReview = (id) => {
    let searchReviews = [];
    for (let i = 0; i < localStorage.length; i++) {
        let key = localStorage.key(i);
        let value = localStorage.getItem(key);

        if (JSON.parse(value).movieId === id) {
            searchReviews.push([key, JSON.parse(value)]);
        }
    }
    console.log(searchReviews);
    searchReviews.sort((a, b) => a[1].dateTime < b[1].dateTime ? -1 : 1);
    console.log(searchReviews);

    document.getElementById("movie_review_list_box").innerHTML = " ";
    searchReviews.forEach((item) => {
        let review_list_tmp = `
        <hr>
        <div class="movie_review_list">
            <div class="review_list_left">
                <div class="review_img_name_date">
                    <div class="review_img_box">
                        <img class="commenter_img" src="./img/commenter_img.png">
                    </div>
                    <div class="review_name_date">
                        <p><b>${item[1].reviewer}</b></p>
                        <p>${item[1].dateTime}</p>
                    </div>
                </div>
                <div class="review_content">
                    <p>${item[1].reviewContent}</p>
                </div>
            </div>
            <div class="review_list_right">
                <div class="update_btn">
                    <button id="update_btn_${item[0]}" type="button" class="btn btn-outline-warning">수정</button>
                </div>
                <div class="delete_btn">
                    <button id="delete_btn_${item[0]}" type="button" class="btn btn-outline-danger">삭제</button>
                </div>
            </div>
        </div>
        `
        document.getElementById("movie_review_list_box").insertAdjacentHTML("beforeend", review_list_tmp);

        document.getElementById(`update_btn_${item[0]}`).addEventListener("click", () => {
            updateReview(item[0]);
        });

        document.getElementById(`delete_btn_${item[0]}`).addEventListener("click", () => {
            deleteReview(item[0]);
        });
    })

}


// 리뷰 수정하는 함수
export const updateReview = (reviewId) => {
    const reviewData = JSON.parse(localStorage.getItem(reviewId));

    if (prompt("비밀번호를 입력해주세요.", "") === reviewData.reviewPass) {
        reviewData.reviewer = prompt("작성자를 입력해주세요.", reviewData.reviewer);
        reviewData.reviewContent = prompt("내용을 입력해주세요.", reviewData.reviewContent);
        reviewData.reviewPass = prompt("내용을 입력해주세요.", "");
        localStorage.removeItem(reviewId);
        localStorage.setItem(reviewId, JSON.stringify(reviewData));
        alert("변경되었습니다!");
        loadReview(reviewData.movieId);
    } else {
        alert("비밀번호가 틀렸습니다!!");
    }
}


// 리뷰 삭제하는 함수
export const deleteReview = (reviewId) => {
    const reviewData = JSON.parse(localStorage.getItem(reviewId));

    if (prompt("비밀번호를 입력해주세요.", "") === reviewData.reviewPass) {
        localStorage.removeItem(reviewId);
        alert("삭제 되었습니다");
        loadReview(reviewData.movieId);
    } else {
        alert("비밀번호가 틀렸습니다!!");
    }
}
  • 기존의 페이지 단위의 검색을 TMDB의 Search API를 사용하는 방식으로 변경

  • 문자열을 Search API의 쿼리값으로 넘겨주면 그 문자열에 해당하는 영화의 데이터를 넘겨줌

// 제목으로 영화 검색해서 해당 영화 데이터 fetch
export const searchMovieData = async (searchText) => {
    try {
        const response = await fetch(`https://api.themoviedb.org/3/search/movie?query=${searchText}&include_adult=false&language=ko-KR&page=1`, options);
        const data = await response.json();
        console.log(data);
        return data.results;
    } catch (err) {
        console.error(err);
    }
}
// 제목으로 영화 검색
const searchMovie = async () => {
    if ($searchContent.value === "") {
        window.alert("검색할 제목을 입력해주세요!!");
    } else {
        // 슬라이드 삭제
        $movieSlide.remove();
        // 현재 카드 리스트를 삭제
        $movieCards.replaceChildren();
        const movieData = await searchMovieData($searchContent.value);

        movieData.forEach(item => {
            appendCard(item.id, item.title, item.genre_ids, item.poster_path, item.vote_average, $movieCards);
        });
    }
}

✏️ 자바스크립트 학습목표 복습하기

  • 자바스크립트 문법에 익숙해질 수 있다.

  • apply 함수, bind 함수 및 call 함수가 언제 어떻게 사용되어야 하는지를 설명할 수 있다.

    • call 메서드 : this를 명시적으로 바인딩하기 위한 메서드
    var obj = {
        a: 1,
        method: function (x, y) {
            console.log(this.a, x, y);
        }
    };
    
    obj.method(2, 3); // 1 2 3
    obj.method.call({ a: 4 }, 5, 6); // 4 5 6
    • apply 메서드 : this를 명시적으로 바인딩하기 위한 메서드, call과 유사
    var func = function (a, b, c) {
        console.log(this, a, b, c);
    };
    func.apply({ x: 1 }, [4, 5, 6]); // { x: 1 } 4 5 6
    
    var obj = {
        a: 1,
        method: function (x, y) {
            console.log(this.a, x, y);
        }
    };
    
    obj.method.apply({ a: 4 }, [5, 6]); // 4 5 6
    • bind 메서드 : call과는 다르게 즉시 호출하지는 않고 넘겨받은 this 및 인수들을 바탕으로 새로운 함수를 반환 (this를 미리 적용하기 위해 사용)
    var func = function (a, b, c) {
        console.log(this, a, b, c);
    };
    func.apply({ x: 1 }, [4, 5, 6]); // { x: 1 } 4 5 6
    
    var obj = {
        a: 1,
        method: function (x, y) {
            console.log(this.a, x, y);
        }
    };
    
    obj.method.apply({ a: 4 }, [5, 6]); // 4 5 6
  • 자바스크립트의 데이터 종류에 대해 이야기할 수 있고, 각각 메모리에 어떻게 저장되고 사용 되고, 수거 되는지를 이해 할 수 있다.

    • 데이터 타입은 기본형과 참조형으로 나눠짐
    • 값의 저장 방식과 불변성의 여부로 구분됨
    • 기본형은 한 주소에 값이 들어있는 형태 (Number, String, ...)
    • 참조형은 한 주소에 다른 값들의 주소가 들어있는 형태 (Array, Object, ...)
  • 실행컨텍스트의 정의와, 실행컨텍스트를 이루는 요소 및 그 하위요소를 이해할 수 있다. 이를 통해 함수가 실행될 때 어떠한 과정이 일어나는지를 말할 수 있다.

    • 실행 컨텍스트 : 실행할 코드에 제공할 환경 정보들을 모아놓은 객체
    • 콜 스택에 개념을 통해서 코드의 순서를 보장함
    • 실행 컨텍스트는 VariableEnvironment(VE), LexicalEnvironment(LE), ThisBindings으로 구성됨
    • LE : record(=environmentRecord) + outer(=outerEnvironmentReference)
    • record의 수집과정을 호이스팅이라고 함
    • 호이스팅 : 선언된 변수, 함수를 위로 끌어올림
  • this가 어떤 환경에서는 무엇으로 채택되는지에 대한 일련의 과정을 설명할 수 있다.

    • 전역에서의 this는 window 혹은 global를 가리킴
    • 함수 안에서의 this도 마찬가지로 window 혹은 global를 가리킴
    • 객체 안에 있는 함수를 호출하면 그 함수 안에 있는 this는 객체를 가리킴
    • 즉, 일반 함수에서의 this는 전역을, 메서드 안에서의 this는 객체를 가리킴


📌 Tomorrow's Goal

✏️ 개인 사정으로 인한 휴식



📌 Today's Goal I Done

✔️ 개인 과제 발전시키기

  • 원래는 오후까지 구현할 줄 알았는데, 오전 중으로 모두 구현됨

  • 생각보다 TMDB에서 제공하는 API가 다양했음

  • 팀프로젝트에서 만든 장르별 검색도 TMDB API로 제공됨

  • 하지만 장르로 검색된 데이터는 페이지 단위로 제공됨

  • 이렇게되면 장르 검색을 위한 페이지네이션이 따로 필요해 보임

  • 지금은 Popular 영화 API에만 페이지네이션이 걸려있음

  • 여러 조건을 통한 검색 API : https://developer.themoviedb.org/reference/discover-movie


profile
조금씩 정리하자!!!

0개의 댓글