본문 바로가기

프로젝트

[TIL] 20240522 68일차

[개인 기록]

Git Stash 사용법

[메모/생각정리]

 

현재 작성한 사항을 commit 하지 않고

dev 변경 사항을 받아온(pull) 다음에 이어서 진행하고 싶은 경우 아래와 같이 진행한다.

 

우선 commit 전단계(add) 까지 한 상황이면

 

git restore --staged .

을 입력하여 add 를 취소한다.

 

현재까지 작성한 사항을 임시로 저장해둔다

git stash

 

dev로부터 pull 하여 받아온다

git pull origin dev

 

stash로 임시저장해둔 사항을 다시 반영한다

git stash pop

 

BootStrap 호환성 고려

[메모/생각정리]

 

Bootstrap을 사용할 때

프로젝트에 적용한 버전과 참고할 문서의 버전을 확인해야 한다.

 

현재 프로젝트 세팅 버전: 4.x

 

처음으로 확인한 부트스트랩 문서 버전: 5.x

https://getbootstrap.kr/docs/5.0/utilities/spacing/

 

간격

Bootstrap에는 요소의 모양을 수정하기 위한 광범위한 반응형 gap, padding 및 margin 유틸리티 클래스가 포함되어 있습니다.

getbootstrap.kr

 

다시 검색하여 확인한 부트스트랩 문서 버전: 4.x

https://getbootstrap.com/docs/4.0/utilities/spacing/

 

Spacing

Bootstrap includes a wide range of shorthand responsive margin and padding utility classes to modify an element’s appearance.

getbootstrap.com

 

내용이 다르니 반드시 확인할 것

 

 

[팀 기록]

Authorization & 페이지 처리

[기술적 의사결정]

 

JWT 함수 사용 여부를 페이지 별로 나눌게 아니라 요청(기능) 별로 나눠야 한다

→ JWT를 사용해야하는 요청(GET)이 있고 아닌 요청(PUT, POST, DELETE)이 있기 때문

우선 페이지(template, html 파일)마다 JWT를 다루는 함수는 있어야 하며

아래의 경우에 따라 JWT 활용 여부를 판단

  1. 로그인 페이지 -> access 토큰을 최초 발급받는 함수가 있어야 함
  2. 회원가입 페이지 -> JWT 함수 불필요
  3. 나머지 페이지들에 대해서는 ① → ② 과정을 포함

① refresh 토큰을 이용해서 if refresh 살아있음: 토큰 refresh를 수행 else: 로그인 페이지로 이동

위 과정을 처리하는 함수가 필요

② localstorage로부터 access 토큰을 꺼내서 auth 정보를 계속 들고 있도록 해야 함

(header에 위치해 무조건 사용하도록 해야 한다.) (이 함수를 base.html 에 포함할지 여부는 더 논의 후 결정)

const token = localStorage.getItem('access_token');
const response = await fetch('{% url '<api 주소>' %}', {
    method: 'GET',
    headers: {
        'Authorization': `Bearer ${token}`,
    },
});

-> 모든 요청에 있어서 headers에 access token 정보를 넣어서 보내야 한다 (api를 수행하는 모든 과정 + 페이지 로드 시 필요)

 

 

async-await / ajax 사용에 대하여

[기술적 의사결정]

 

발단:

ChatGPT의 도움을 받아 작성한 JWT 로그인 함수와 JWT access token을 로드하는 함수에서 async - await 구문을 확인하게 되었다.

작성 코드를 살펴보니 ajax와 유사한 동작을 함을 발견할 수 있었다.

const token = localStorage.getItem('access_token');
const response = await fetch('{% url <api 링크> %}', {
    method: 'GET',
    headers: {
        'Authorization': `Bearer ${token}`,
    },
});
const postData = {
    'insert_comment': cm
}
$.ajax({
    type: 'POST',
    url: '{% url <api 링크> %}',
    data: JSON.stringify(postData),
    dataType: 'JSON',
    contentType: "application/json",
    success: function (data) {
		    // 성공 시 동작
        console.log("성공")
    }
})

그래서 async - await 과 ajax 둘 중 어떤 것을 사용해야 할지 의논하는 시간을 가지게 되었다.

결론:

  • ajax는 비동기 처리 함수이며, jQuery를 import 해야 사용할 수 있다.
  • async - await은 JS에서 지원하는 문법이며 비동기 처리를 await을 통해 동기적으로 처리할 수 있도록 해준다.

jQuery를 가급적 지양하라는 피드백 + 동기적 처리를 필요할 때 사용할 수 있다는 점을 통해 async - await 을 사용하는 방향으로 결정.

 

검색 기능 구현 - 쿼리스트링 처리

[기능 구현]

 

현재 프론트 구현 단계에서 검색 기능을 수행할 때

사용자로부터 2가지를 입력받는다.

 

  • 검색 종류: 검색 종류를 선택한다. 태그, 게임, 작성자 3가지가 있다.
    • 태그: tag-q
    • 게임: game-q
    • 작성자: maker-q
  • 선택한 검색 종류에 따라 전달할 쿼리 스트링 중 Key 가 변경된다.
  • 검색어: 선택한 검색 종류에 맞는 검색어를 입력 받는다. 쿼리 스트링 중 Value에 해당한다.

이를 처음에 form 태그로 감싼 후 GET 요청을 보냈더니 문제가 발생했다.

검색 종류, 검색어 각각에 name 속성을 지정해준 후 각각이 쿼리 스트링으로 처리되는 것이었다. (검색 종류의 name 속성이 ’search_sort’, 검색어의 name 속성이 ‘search_text’ 일 때 ?search_sort=tag-q&search_text=asd 와 같은 형태로 GET 요청을 보내게 됨)

처음에 구상한 대로 쿼리 스트링을 ‘?tag-q=asd’ 와 같은 형태로 보내기 위해서는 JS를 사용할 수밖에 없었다.

 

검색 기능 구현 - 검색 페이지를 어떻게 할 것인지

[기술적 의사결정]

 

[발단]

검색 결과를 가져오기 위해서 api를 호출한다.

api 호출을 검색하는 페이지에서 진행하게 되면 다른 페이지를 로드할 필요 없이 해당 페이지에서 데이터를 보여주면 된다.

이러한 이유로 2가지의 방안이 나왔다.

 

[선택]

① 기획 시 결정했던 방안

‘/search/’ url 패턴을 가진 별도의 페이지(이하 ‘검색 페이지’)에서 검색 결과를 보여준다.

② [발단]을 이유로 나오게 된 방안

별도의 페이지를 마련하지 않고 검색을 진행한 페이지에서 검색 결과를 보여준다.

 

①, ② 모두 api를 호출하는 점이 같지만, 페이지를 따로 마련하느냐 기존의 페이지를 사용하느냐의 차이가 존재할 뿐이었고

따라서 기존에 기획했던대로 ①방안인 검색 페이지에서 검색 결과를 보여주는 것으로 결정했다. 이를 선택한 이유는 래퍼런스로 삼은 페이지에서 검색을 진행하면 별도의 페이지에서 보여주고 있었으며, 기존의 기획을 최대한 수정하지 않고 진행하기 위해서였다.

 

for 구문 언어의 차이 (Python, JS)

[기타사항]

 

List 안의 item에 접근하기 위해서

python 에서는 아래와 같이 사용한다.

itmes = ['a', 'b', 'c']
for item in items:
		print(item)

# 기대 출력
# a
# b
# c

 

이를 JS에서 똑같이 사용하면 python과 같은 결과가 나오지 않는다.

itmes = ['a', 'b', 'c']
for (let item in items) {
		console.log(item);
}

// 기대 출력
// a
// b
// c

// 실제 출력
// 0
// 1
// 2

 

index가 출력된다. 따라서 JS에서 python과 같은 동작을 수행하기 위해선

for ~ in 구문이 아닌 for ~ of 구문을 사용해야 한다.

itmes = ['a', 'b', 'c']
for (let item of items) {
		console.log(item);
}

// 실제 출력
// a
// b
// c

 

이 구문을 사용하여 api 호출로 응답받는 데이터의 특정 요소에 접근할 수 있었다.

const data = await response.json();

for (let row of data) {
    const game_list_div = document.getElementById('game_list');

    const card_div = document.createElement('div');
    card_div.setAttribute("class", "card");
    card_div.setAttribute("style", "width: 18rem;");

    const card_img = document.createElement('img');
    card_img.setAttribute("class", "card-img-top");
    card_img.setAttribute("width", "100%");
    card_img.setAttribute("height", "180");
    if (!row.thumbnail) {
        card_img.setAttribute("src", "{% static 'image/image_cap.svg' %}");
    } else {
        card_img.setAttribute("src", row.thumbnail);
    }

    const card_body_div = document.createElement('div');
    card_body_div.setAttribute("class", "card-body");
    // card_body_div.setAttribute("class", "card-img-overlay");

    const card_title = document.createElement('h5');
    card_title.setAttribute("class", "card-title");
    card_title.textContent = row.title;

    const card_content = document.createElement('p');
    card_content.setAttribute("class", "card-text");
    card_content.innerHTML = `maker: ${row.maker}<br>평점: ${row.star}`;

    card_body_div.appendChild(card_title);
    card_body_div.appendChild(card_content);
    card_div.appendChild(card_img);
    card_div.appendChild(card_body_div);
    game_list_div.appendChild(card_div);
}

'프로젝트' 카테고리의 다른 글

20240520 ~ 20240524 14주차 정리  (0) 2024.05.24
[TIL] 20240523 69일차  (0) 2024.05.23
[TIL] 20240521 67일차  (0) 2024.05.21
[TIL] 20240520 66일차  (0) 2024.05.20
20240513 ~ 20240517 13주차 정리  (0) 2024.05.18