안전한 협업을 위한 규칙
우리 팀은 현재 [main branch로부터 따온 각각의 기능 branch]에서 작업을 하고 있다.
약식으로나마 PR을 날려 코드가 덮어씌워지는 불상사를 막기 위함이다.
오전 내로 메인이 되는 기능 구현을 마무리하고 팀원분들과 첫 merge를 진행하였다.
아무래도 작업 분리가 완벽하게 되지 않은 상태에서 동시에 작업하는 파일들이 많다 보니 conflict가 어마 무시했다..😂
팀원들이 각자의 공간에서 마음껏 작업할 수 있도록 확실한 분리가 필요했다.
- JS와 CSS는 HTML내에 넣지 않고 따로 파일 생성하여 /static/css or js 디렉토리에 저장
- 변수명, 파일명 컨벤션 정하기(camelCase, snake_case 등)
- 남이 알아보기 쉽도록 주석을 꼼꼼하게 적기
- 단순 출력 확인을 위한 주석은 삭제하기
- 반복되는 HTML은 {% include %} 이용하여 파일 분리 (대표적으로 nav와 footer)
{% include "nav.html" %}
<!-- main -->
{% include "footer.html" %}
이 중 몇 개는 실천 했지만, 몇 개는 실천하지 못하였다.
결국 팀원들과의 소통이 중요하다는 걸 다시금 깨달았다.
소소한 에러 모음집
a 태그가 왜 작동을 안 할까?
정말 이상한 일이다.
메인 페이지의 nav에서만 a 태그가 작동하지 않았다.
아무런 오류 메시지도 없고, 메뉴 클릭은 안되고, 그저 리로딩만 되었다.
뭐가 문제인지 찾기 위해 메인 페이지 내 다른 곳에 a 태그도 넣어보고, 코드를 한참 들여다보다 헛웃음이 나왔다.
동적으로 생성되는 로그아웃 버튼에 href를 달아주려고 만들었던 event가 나를 붙잡고 있었다😅
nav 자체에 e.preventDefault() 걸어놓고 계속 window.location.href=’/’ 해놓으니까 당연히 리로딩되지… 멍청쓰~
if문으로 id가 로그아웃일 때만 작동하도록 분기 처리해주었다.
document.getElementById('navbarsExample09').addEventListener('click', (e)=>{
if (e.target.id === 'logout-btn') {
e.preventDefault();
$.removeCookie('mytoken');
window.location.href = '/';
}
})
render_template()으로 내려주는 데이터를 왜 못 받지?
현재 메인 페이지는 render_template() 함수로 index.html과 함께 인기 메뉴에 출력한 음료 리스트, 로그인한 회원의 고유 id와 닉네임을 전달하고 있다.
이렇게 여러 개의 파라미터를 전달해주는 건 처음이었는데, 왜인지 음료 리스트가 출력되지 않았다.
메인 페이지를 맡았던 팀원 분과 함께 코드를 여러 번 살펴보다 해당 함수를 호출하고 있지 않다는 걸 알게 되었다.
render_template() 함수에 여러 개의 파라미터를 보내주는 방식이 뭔가 잘못된 줄 알았는데 아니었다..!
이렇게 여러 개의 데이터를 내려주고, 프론트단에서 변수 이름으로 받으면 된다. Jinja2 참 편한다.
return render_template('index.html', variable=result, nickname=user_info["nick"], uid=user_info["uid"])
Path Variable로 id 넘겨주기
에러가 났던 건 아니지만, 새로운 방식으로 구현했기에 적어본다.
지금까지는 GET 방식으로 서버에 정보를 넘겨줄 때 query parameter로 전달하고, request.args.get('query string')으로 받았었다.
이번에 커피 상세 조회 페이지 부분을 구현하면서 path variable을 사용해보았다.
# 커피상세정보 HTML
@app.route('/coffee/<coffee_id>')
def detail(coffee_id):
token_receive = request.cookies.get('mytoken')
try:
payload = jwt.decode(token_receive, SECRET_KEY, algorithms=['HS256'])
user_info = db.user.find_one({"id": payload['id']})
return render_template('coffeeDetail.html', coffee_id=coffee_id, nickname=user_info["nick"], uid=user_info["uid"])
except jwt.ExpiredSignatureError:
return render_template('coffeeDetail.html', coffee_id=coffee_id)
except jwt.exceptions.DecodeError:
return render_template('coffeeDetail.html', coffee_id=coffee_id)
# 커피상세정보 API [GET]
@app.route('/api/coffee/<coffee_id>', methods=["GET"])
def get_coffee_detail(coffee_id):
coffee_id = int(coffee_id)
coffee_detail = list(db.coffee.find({'coffee_id': coffee_id}, {'_id': False}))
# print(coffee_detail)
return jsonify({'detail': coffee_detail})
/coffee/<전달받을 부분> 이런 식으로 작성하고, 해당 변수를 함수의 파라미터로 받아 함수 내에서 자유롭게 사용할 수 있다.
기존에는 query parameter로 전달한 값을 받기 위해 JS 쪽에서 URSerarchParams 객체를 반환하는 URL 인터페이스 속성을 사용했었다.
// url에서 board_id 가져오기
const param = window.location.search;
const paramData = new URLSearchParams(param)
const board_id = paramData.get('id')
뭔가 복잡하고.. 가독성이 좋지 않다 느꼈는데 path variable 방식으로 화면에 해당 변수를 내려주고, Jinja2로 받아서 JS로 넘겨주니 훨씬 간편하고, 사용하기 좋았다.
Query Parameter와 Path variable은 각각 언제 쓰는 것이 좋을까?
어떤 resource를 식별하고 싶다 👉 Path Variable
정렬이나 필터링, 페이징을 한다 👉 Query Parameter
기술 매니저님과의 질문&답변
Q. 아이디 중복 검사는 GET 방식? POST 방식?
A. POST. 조회는 통상적으로 GET을 쓰지만 회원 정보와 관련된 로직은 보안상의 이유로 POST를 사용한다. 정답이 있다기보단 상황에 맞게 사용하는 게 중요.
Q. 유효성 검사는 서버에서 하는 건지?
A. 양쪽에서 해주는 게 맞다.
Q. 해당 회원이 즐겨찾기를 했는지에 대한 여부를 리스트에 출력하려면?
A. 로그인한 유저의 즐겨찾기 정보를 가져오는 api를 만들고, 해당 리스트를 반복문으로 돌릴 때 조건문을 걸어 일치하는 정보에 class를 준다던가 하는 방식으로 구별.
Q. 페이징은 어떤 식으로 구현해야 하는지?
A. 현재 페이지 정보와 한 번에 가져올 limit을 서버 쪽으로 보내주면(/api/board?page=1&limit=10) 서버가 받아서 해당하는 데이터를 보내주는 방식으로 구현.
Q. 앞으로의 진행에 대해
A. 반드시 구현해야 하는 메인 기능과 우선순위를 정해 보는 걸 추천.
문제 해결 세션
질문이란?
- 모르는 것을 알고자 하여 묻는 것
- 가장 효율적인 방법 → 시간이 적게 걸린다는 의미
질문 잘하는 법
- 일단 검색은 영어로
- 구글링에 검색 제한 걸기 → site:stackoverflow
- 깃헙에서 검색 → 기초 세팅 많음
- 항해99 슬랙 질문방에 올리기
- 동료를 많이 이용하기
오늘의 나는
문제 해결 세션에서 잘하는 개발자란 흐름 파악을 잘할 줄 아는 개발자라 했다.
데이터의 흐름, 프로젝트의 진행 흐름들을 잘 파악하는 것이 결국 프로젝트의 완성도를 결정짓는 것 같다.
그 말은 즉슨, 현재 어떤 상황에 처해있는지를 주의 깊게 살펴보고 방향성을 제시할 줄 알아야 한다는 의미라고 생각한다.
팀원들에게 그런 개발자, 동료가 될 수 있도록 하자.
'📝 TIL' 카테고리의 다른 글
[TIL] 1주차 알고리즘ㅣ주간 시작 (0) | 2022.11.18 |
---|---|
[TIL] 1주차 미니 프로젝트ㅣ발표 (0) | 2022.11.18 |
[TIL] Flask 로그인/회원가입 구현하기(JWT, 유효성 검사) (0) | 2022.11.15 |
[TIL] 1주차 미니 프로젝트ㅣ시작 (2) | 2022.11.15 |
[TIL] Java 열거 타입(Enum) (4) | 2022.11.12 |