항해99

항해99 1주차 프로젝트 [공유문화] [WIL]

Brad Daeho Lee 2021. 3. 6. 01:34

 

기획 배경

팀원인 민규님과 제가 공통적으로 관심있는게 전시/공연이여서 그것에 관련된 정보를 공유하는 웹 사이트를 만들어 봤습니다. 컨셉이 정보 공유라서 공유를 등장시켰습니다.

 

 

구현한 기능(API 목록)

1. 크롤링으로 db에 저장되어있는 전시/정보 데이터를 Jinja2(서버사이드 렌더링)를 이용해서 가져왔다

이번 프로젝트를 통해서 서버사이드 렌더링에 대해서 처음 알게 되었는데, jinja2를 라이브러리를 이용해서 구현해보았다. 먼저 서버에서 데이터를 불러서 해당 html주소로 보내주는 형식이기 때문에 클라이언트로 데이터가 도달하는 시간이 매우 빠르다. 프로젝트를 할 때 처음에는 ajex를 이용해서 데이터를 요청했는데 그 때는 데이터를 다 가져오는데 2~3초정도 시간이 걸렸던것같다. 하지만 jija2로 데이터를 불러오니까 1초도 안걸렸던것같다. 직접 서버사이드 렌더링의 장점을 체험할 수 있어서 좋은 경험이였다. 

 

그리고 jinja2는 밑에 코드를 보면 알겠지만 코드 쓰는 방식이 ajex보다 훨씬 간편한 것을 볼 수 있다. jinja2 코드에 대해서 잠깐 설명하자면, html코드 맨위에 blogs는 서버에서 받아온 db데이터 리스트이고 blog는 그 리스트에있는 하나의 값들이라고 보면 될것 같다. blogs는 서버에서 받아온 정해진 변수이지만 blog는 blog말고 아무 값이나 써도 된다. for in 반복문이 돌면서 blogs라는 리스트안에 값들이 blog라는 변수로 나온다고 보면 된다. 그리고 이제 blog라는 사전에서 필요한 데이터를 필요한곳에 넣어주면 된다.

 

@app.route('/artShow', methods=['GET'])
def artShow():
   data = list(db.Share_artShow.find({}, {'_id': False}))
   return render_template('artShow.html', blogs = data)
{% for blog in blogs %}
    <div class="card" class="card-padding">
      <div class="card-img">
          <a href="{{ blog['url'] }}">
              <img class="card-img-Top"
                  src="{{ blog['image'] }}"
                  alt="image">
          </a>
      </div>
      <div class="card-body">
          <a target="_blank" href="{{ blog['url'] }}" class="card-title">{{ blog['title'] }}</a>
          <hr style="border: solid 1px grey;">
          <div class="card-text">{{ blog['date'] }}</div>
          <hr style="border: solid 1px grey;">
      </div>
      <div class="card-footer">
          <div class="loc">{{ blog['loc'] }}</div>
          <div class="loc-detail">{{ blog['loc_detail'] }}</div>
      </div>
    </div>
  {% endfor %}

 

2.  회원가입 할 때 아이디와 비밀번호를 POST로 서버에 보내주고 서버에서 패스워드를 암호화시켜서 db에 저장시켰다.

 

회원가입을 하면 아이디랑 비밀번호가 db에 저장이 되는데 저장이 될 때 비밀번호가 그대로 저장되게 되면 db관리자가 그 회원의 아이디와 비밀번호를 알게 되기 때문에 db에 비밀번호를 저장할 때 hashlib을 이용해서 암호화를 시키고 db에 저장 시킨다. 패스워드는 보안을 위해서 꼭 암호화를 시켜야되는것 같다.

 

@app.route('/sign_up/save', methods=['POST'])
def sign_up():
   username_receive = request.form['username_give']
   password_receive = request.form['password_give']
   password_hash = hashlib.sha256(password_receive.encode('utf-8')).hexdigest()
   doc = {
      "username": username_receive,                              
      "password": password_hash,                                  
      "profile_name": username_receive,                           
   }
   db.user_info.insert_one(doc)
   return jsonify({'result': 'success'})

 

 

3. 로그인을 할 때 클라이언트에서 제공한 아이디랑 비밀본호가 맞는지 서버에서 db정보를 가져와서 확인을 했고 db랑 맞았을 때 jwt를 사용해서 토큰을 만들어 클라이언트에 보내주었습니다.

JWT는 사용자가 로그인을 했을 때 JSON형식으로 암호와된 token을 안전하게 클라이언트로 넘겨줍니다.
세션/쿠키와 비교해 봤을 때 별도의 저장하는 곳이 필요없기 때문에 더 간편합니다. token을 발급 받은후에 가지고 있는지 검증만 하면 됩니다.

 

먼저 로그인을 할 때 클라이언트에서 받은 아이디와 비밀번호 값에서 비밀번호를 회원가입할 때 암호화 시켰던것 처럼 똑같이 암호화를 시키고 user_info db에서 저장되어있는 아이디랑 비밀번호중에 같은 값이 있는지 확인하고 같은 값이 있으면 아이디와 expire시간정보암호화한 token을 만든다. 그리고 그 토큰을 클라이언트에 전해줍니다. 그리고 클라이언트는 토큰을 받으면 쿠키에 저장시킵니다. 

 

 

 

 

@app.route('/sign_in', methods=['POST'])
def sign_in():

   username_receive = request.form['username_give']
   password_receive = request.form['password_give']

   pw_hash = hashlib.sha256(password_receive.encode('utf-8')).hexdigest()
   result = db.user_info.find_one({'username': username_receive, 'password': pw_hash})

   if result is not None:
      payload = {
      'id': username_receive,
      'exp': datetime.utcnow() + timedelta(seconds=60 * 60 * 24) 
      }
      token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')

      return jsonify({'result': 'success', 'token': token})

   else:
      return jsonify({'result': 'fail', 'msg': '아이디/비밀번호가 일치하지 않습니다.'})
$.ajax({
                type: "POST",
                url: "/sign_in",
                data: {
                    username_give: username,
                    password_give: password
                },
                success: function (response) {
                    if (response['result'] == 'success') {
                        $.cookie('mytoken', response['token'], {path: '/'});
                        alert("로그인 되었습니다.")
                        window.location.reload()
                    } else {
                        alert(response['msg'])
                    }
                }
            });

 

 

4. 리뷰를 작성했을 때 제목과 리뷰내용을 서버로 보내주고 서버에서 토큰을 decode해서 아이디를 같이 db에 보내줬다 그리고 리뷰 보기를 하면 데이터를 가져와서 리뷰를 보여준다.

먼저 작성한 리뷰의 타이틀이랑 리뷰를 받아오고 클라이언트에 token을 요청해서 받은 token을 해독하고 token 에서 id값을 가져와서  artshow_review db에 저장했습니다.

 

@app.route('/review/artshow', methods=['POST'])
def submit_artShow_review():
   token_receive = request.cookies.get('mytoken')
   payload = jwt.decode(token_receive, SECRET_KEY, algorithms=['HS256'])
   title_receive = request.form['title_give']
   review_receive = request.form['review_give']
   doc = {
      "username" : payload["id"],
      "title" : title_receive,
      "review" : review_receive
   }
   db.artshow_review.insert_one(doc)
   return jsonify({'msg':'저장완료!'})

 

프로젝트 진행 중에 겪었던 어려움

1. 깃을 처음 사용해보고 깃헙으로 팀 프로젝트를 처음해봐서 자료를 주고 받을 때 자료가 깃헙으로 잘 올라가지 않고 깃헙에서 다른 팀원이 올린 자료를 받으면 파이선이 실행이 안될 때가 있었습니다.

 

2. 코딩 양이 많아지다 보니까 사소한거를 하나만 틀려도 뭐가 틀렸는지 찾기가 힘들었습니다.

 

어려움을 극복한 방법

1. 모르는게 생겼을 때 남에게 먼저 물어보기 보다는 제 스스로가 정보를 찾고 그것을 이해하고 제 코드에 사용하려고 노력했습니다. 그리고 몇시간을 알아봤는데도 모를 때는 같이 공부하는 분이나 튜터분들에게 물어봐서 해답을 얻었습니다.

 

2. 작성한 코드에서 오류가 날 때 파이썬에서는 print()를 사용하고, 자바스크립트에서는 console.log()를 사용해서 데이터를 잘 가져오는지 보았습니다. 그리고 데이터를 불러올 때 잘 불러왔는데 화면상으로만 안보이는 건지 알기위해서 개발자도구에서 element를 보고 확인했습니다. 그렇게 하니 어떤게 문제가 있는지 알기 비교적 쉬웠습니다.

 

 

아쉬웠던점 & 개선사항

1. 프로젝트 계획을 짤 때 프로젝트에 꼭 들어가야되는 회원가입 로그인 기능에 대해서 모르는 상태에서 하다보니 해당 기능을 더 잘 활용한 프로젝트를 구성하지 못한 것 같다. 그래서 다음에 프로젝트를 할 때는 약간은 공부를 한 상태에서 프로젝트 계획을 세우는것도 좋을 것 같다.

 

2. 프로젝트를 할 때 팀 리더로써 기능구현에 좀 더 신경을 썼어야 했는데, 웹 디자인에 너무 신경을 쓴게 아닌가라는 생각이든다. 그리고 bulma나 bootstrap을 사용해서 시간을 절약하고 기능구현에 신경을 더 쓸 수 있었는데 스스로 웹페이지를 구현하다 보니 시간이 오래거렸다. 이번 프로젝트를 통해서 css 프레임워크에 필요성을 깨달았고 다음 프로젝트에는 사용해보도록 하겠다.

 

 

프로젝트 관련자료

 

공유문화 | 전시 공연 정보 길잡이

공유와 함께 하는 전시공연 정보

shareculture.shop

 

 

leedaeho1188/hanghae99-first-project

Contribute to leedaeho1188/hanghae99-first-project development by creating an account on GitHub.

github.com