본문 바로가기
일기/항해99

1 주차 4일차 개발일지

by 고구밍 2022. 3. 11.

 

1주차 4일 동안 첫 프로젝트를 만들었습니다.

 

4.개발해야 하는 기능들

 

기능 METHOD url request response 담당
후보리스트 조회 get /candidates   후보리스트 윤선식
후보검색 get /candidates/search   검색한후보리스트 윤선식
공약내용조회 get /detail   공약내용(새창) 윤선식
회원가입 post /membership {'id' : id, 'pw' : pw} 회원가입성공메세지 윤선식
회원가입중복 get /membership   중복메세지 윤선식
로그인 post /login {'id' : id, 'pw' : pw} 로그인성공메세지 최고은
로그인여부 get /login {'id':id} 로그인상태 최고은
댓글작성 post /posts/reply {'id':id, 'can_num':can_num} 댓글작성성공메세지 최고은
댓글조회 get /posts/reply   댓글리스트 최고은
뉴스크롤링 post? /posts     엄성훈
좋아요 작성 post /posts/like {'id':id,'can_num':can_num,'like':like} 좋아요성공메세지 최은아
좋아요 취소 patch /posts/unlike     최은아
좋아요 조회 get /posts/like   후보좋아요 수 최은아
좋아요 여부 get /posts/like/personal {'id':id,'can_num':can_num} 좋아요 상태 최은아

 

1. 4일동안 한 작업들

 

더보기

처음에 뉴스크롤링하는 부분을 (기사를 보여줘야 하는 부분이라 가장 중요한 기능입니다) 맡았지만,

 

ifream 태그기능을 구현하는데 있어서, 네이버/구글/다음과 같은 검색 플랫폼을 통한 접속이 차단되어서 크롤링은 어려웠습니다.

하지만, 기술매니저님의 "사이트에 직접 들어가서 보는거는 어떤가요?" 조언을 통해서

 

ifream태그로 조선/한겨레/MBC뉴스 등의 사이트를 비출 수 있다는 사실을 알게되었습니다.

 

하이퍼링크를 클릭하면 traget이 ifream을 지정하여 src 안의 url주소를 바꿔주는 것을 알게되었지만, 

 

jinja2기능의 이해부족으로, 팀장님인 최은아님이 대신 작업해 주셨습니다.

<div style="width: 100%; height: 88%">
      <iframe id="newsview" name="newsview" width=99% height="100%" margin=auto src="https://news.kbs.co.kr/special/election2022/president/vote_counting.html"></iframe>
</div>
<p onclick="locaction_move('https://www.joongang.co.kr/search?keyword=','{{ word }}')">중앙 일보</p>

 

그 다음에 맡은 기능은, 회원가입기능을 구현해 보는 것이였습니다.

 

4주차 6~8강 내용을 토대로, 하룻동안 로그인과 회원가입 기능을 구현해 보는것을 목표로 하였고,

 

그중 서버(파이썬)과 html(클라이언트)의 코드와 css를 복사 붙여 놓기한 뒤,

 

@app.route('/membership')

 

url 주소를 수정하여 만들어 보았습니다.

 

강의 자료에서는 아이디 / 아이디 중복확인 / 비밀번호 / 비밀번호 재입력 코드를 제공받았고,

 

추가적으로 사용자이름 / 남자 & 여자 (라디오 테그) / 이메일 주소의 input박스를 추가하였습니다.

 

 

01234567

 

조금 어려웠던 부분은 라디오버튼이였습니다.

 

선택한 버튼의 value값을 회원가입 값에 보내줘야 하는데,

 

input박스와는 다른 방법으로 값을 가져와야 되서 방법을 찾는데 많이 어려움을 느꼈습니다. 

 

<script>
 function sign_up() {
            let username = $("#input-username").val();
            let password = $("#input-password").val();
            let password2 = $("#input-password2").val();
            let name = $("#input-name").val();
            var gender = $('input[name=list]:checked').val();
            let email = $("#input-email").val()
</script>

<body>
<div class="control">
    <label><input type="radio" name="list" checked value="남자">남자</label>
    <label><input type="radio" name="list" value="여자">여자</label>
</div>
</body>

 

그리고, 미기입한 부분이 있을 때 아래와같이 if문을 넘어서면, 다음 단계로 넘어갑니다.

 

만약이 값이 false이면 텍스트 .text("요청내용")와 색깔이 변하고,

 

.focus가 해당하는 input박스를 가르켜 주는 부분이 신기 했던 것 같습니다.

 

모든 단계가 마치면 ajax를 통해서 서버에서 몽고db로 저장을 하는 순서로 진행됩니다.

 

<Bulma라는 프레임워크를 사용했어요>

function sign_up() {
    let username = $("#input-username").val();
    let password = $("#input-password").val();
    let password2 = $("#input-password2").val();
    let name = $("#input-name").val();
    var gender = $('input[name=list]:checked').val();
    let email = $("#input-email").val()


    if ($("#help-id").hasClass("is-danger")) {
        alert("아이디를 다시 확인해주세요.")
        return;
    } else if (!$("#help-id").hasClass("is-success")) {
        alert("아이디 중복확인을 해주세요.")
        return;
    }

    if (password == "") {
        $("#help-password").text("비밀번호를 입력해주세요.").removeClass("is-safe").addClass("is-danger")
        $("#input-password").focus()
        return;
    } else if (!is_password(password)) {
        $("#help-password").text("비밀번호의 형식을 확인해주세요. 영문과 숫자 필수 포함, 특수문자(!@#$%^&*) 사용가능 8-20자").removeClass("is-safe").addClass("is-danger")
        $("#input-password").focus()
        return
    } else {
        $("#help-password").text("사용할 수 있는 비밀번호입니다.").removeClass("is-danger").addClass("is-success")
    }
    if (password2 == "") {
        $("#help-password2").text("비밀번호를 입력해주세요.").removeClass("is-safe").addClass("is-danger")
        $("#input-password2").focus()
        return;
    } else if (password2 != password) {
        $("#help-password2").text("비밀번호가 일치하지 않습니다.").removeClass("is-safe").addClass("is-danger")
        $("#input-password2").focus()
        return;
    } else {
        $("#help-password2").text("비밀번호가 일치합니다.").removeClass("is-danger").addClass("is-success")
    }
    if (name == "") {
        $("#help-name").text("이름을 입력해주세요.").removeClass("is-safe").addClass("is-danger")
        $("#input-name").focus()
        return;
    } else {
        $("#help-name").text("이름이 입력되었습니다.").removeClass("is-danger").addClass("is-success")
    }
    if (email == "") {
        $("#help-email").text("이메일을 입력해주세요.").removeClass("is-safe").addClass("is-danger")
        $("#input-email").focus()
        return;
    } else if (!email.includes("@")) {
        $("#help-email").text("이메일이 아닙니다.").removeClass("is-safe").addClass("is-danger")
        $("#input-email").focus()
        return;
    } else if (!email.includes(".")) {
        $("#help-email").text("[ . ]를 입력해주세요.").removeClass("is-safe").addClass("is-danger")
        $("#input-email").focus()
        return;
    } else {
        $("#help-email").text("이메일이 입력되었습니다.").removeClass("is-danger").addClass("is-success")
    }


    $.ajax({
        type: "POST",
        url: "/sign_up/save",
        data: {
            username_give: username,
            password_give: password,
            name_give: name,
            gender_give: gender,
            email_give: email
        },
        success: function (response) {
            let result = response['result'];
            if(result == 'success')
                alert("회원가입을 축하드립니다!")
            else
                alert("회원가입 실패 동일한 사람이 존재합니다.")
            {#window.location.replace("/login")#}
        }
    });

}

 

 

 

 

2. 팀 프로젝트 결과물

 

 

 

더보기

 

먼저 로그인을 하게되면 mongodb 내에 미리 저장되어있는 대통령후보에 대한 값을

 

jinja2를 통해서 해당 박스에 사진/이름/정당을 붙여줍니다.

 

사진을 누르게되면 후보의 공약내용을 보여줍니다.

 

0123

 

012

 주소(key값)와 jinja2를 통해 버튼별로 적용된 것들입니다.

1.  우선 서버에서 posts.html으로 후보 리스트에대한 정보를 보내주어야합니다.

 

2. 아래와 같이 go_list는 db의 candidate안에 있는 전체 리스트를 정의했습니다.

-> 전체리스트를 처음부터 끝까지 반복하기 위함 (jinja2)

 

3. cans_list는 db의 candidate안의 속성(name)이 "keyword"에 해당되는 리스트를 정의합니다.

(전체 리스트 중에 이름(name)이 "keyword"인 있는 리스트를 고르기)

 

4. 클라이언트로 데이터를 보내줄 때,

return render_template('이름.HTML', 보내주고 싶은 내용(부를이름 = 서버에서 정한 이름)을

넣어주면 전달이 된다고 한다.

 

@app.route('/posts/<keyword>')
def posts(keyword):
    go_list = list(db.candidate.find({}, {'_id': False}))
    can_list = list(db.candidate.find({"name":keyword}))
    word_receive = request.args.get("word_give")
    return render_template('posts.html', go_list = go_list, list = can_list, word=keyword )

 

{%  for who in go_list %}에서 for는 반복이고

-> who는 한사람의 정보(이름, 정당, 이미지 등) in은

-> go_list는 위에서 정의한 모든리스트의 정보의 의미를 갖고 있다고 한다.

-> 즉 전체리스트 중 한개의 리스트 씩 {{ 요청한 정보 }}반복해서 넣어준다는 의미라고 한다.

 

아래와 같은경우는 who라는 하나의 리스트 정보 중에 .name

즉 리스트중 "name"의 값을 넣어주라는 의미이고,

 

{{who.symbol}}은 who라는 한 리스트 정보 중에 "symbol"의 값을 넣어 주라는 의미이다.

 

따라서 <a onclik="reload_can('이름')>기호1번</a>으로 기입이되고,

우리의 눈에는 "기호1"이라는 버튼이 보이게 된다.

예시 )

+ go_list(전체리스트)의 리스트개수가 14개면 -> 14개의 버튼이 만들어진다.

                                                 10개면  -> 10개의 버튼이 만들어진다.

 

즉, 개발자가 손수 전체 버튼을 안 만들어도 리스트의 내용을 반복해서 붙여주기 때문에

시간과 데이터 정보를 절약 할 수 있다.

 

<클라이언트 (html) body의 버튼에 적용된 jinja2>

		<ul>
            {% for who in go_list %}
            <li>
                <a onclick="reload_can('{{ who.name }}')">{{who.symbol}}</a>
            </li>
            {% endfor %}
       </ul>

참고로 넣은 자바스크립트의 reload_can함수이다.

1. 기호1번을 누르게 되면, 위의 {{ who.name }}의 값인 함수에 들어가게되어

 

2. 아래 함수에서 page_reload라는 객체를 정의할 떄 '/posts/'라는 문자열과 {{ who.name }}인 값

즉, 이름을 더한 문자열을 정의한다.

 

3. 따라서 [page_reload = /posts/'이름] 이 된다.

 

4. 이것을 다른페이지로 이동하기 함수인 [window.location.href=]에 대입한다.

 

5. 선택한 이름의 주소로 이동하게 되면,

미리 입력한 jinja2를 통해서 선택한 이름에대한 ifream과 후보정보 등이 자동으로 붙여지게된다. 

 

<script>
        
            function reload_can(name)
            {
                let page_reload = '/posts/'+name;
                console.log(page_reload);
                window.location.href= page_reload;

            }

            function locaction_move(url,can_nm){
                console.log(url + can_nm);
                $('#newsview').attr('src',url+can_nm);

            }
            function move_page(page_address)
            {
                total_ads = page_address + "/index"
                location.replace(total_ads);
            }
</script>

 

위의 내용은 은아님이 설명해 주신 jinja2를 이용한 홈페이지의 설명을 나열해 보았습니다.

 

jinja2를 이용한다면 데이타를 html이라는 껍데기에 어떤 방식으로 끼워 넣을 것이가 고민해야 된다는 점을 알게되었습니다.

 

3. 느낀점

더보기

이번 프로젝트를 하면서, 스스로가 문제 해결능력이 부족하다는 점을 알게 되었습니다.

 

그 이유는 주어진 임무나 문제가 발생할 때

-> 해결하기위해 검색하는 방법과 왜 이런 함수를 사용했는지에 대한 접근

    문제를 집요하게 파고들는 것이 부족했던 것 같습니다.

 

또한 유연한 사고능력이 필요하다고 생각 하였습니다.

왜냐하면, 회원가입시 회원의 중복체크 기능을 구현해 보기 위해서 구글링과 함수를 만들 어 보았지만,

 

단순히 자바스크립트 내에서만 ture와 false을 이용하여 and값을 어용하려 했고,

선식님의 서버(파이썬)에서 디비로 저장되기 전에,

db내의 리스트에서 a조건과 b조건의 and값이 ture인 것을 정의한 뒤,

저장되기 위해 넘어온 리스트의가 0보다 클 때 저장하지 않는다는 함수를 보면서

 

-> 문제해결에 대한 다양한 접근법이 있다는 점을 새로 알게되었습니다.

def sign_up():
    username_receive = request.form['username_give']
    password_receive = request.form['password_give']
    name_receive = request.form['name_give']
    gender_receive = request.form['gender_give']
    email_receive = request.form['email_give']
    password_hash = hashlib.sha256(password_receive.encode('utf-8')).hexdigest()
    doc = {
        "username": username_receive,                   # 아이디
        "password": password_hash,                      # 비밀번호
        "name": name_receive,                           # 이름
        "gender": gender_receive,                       # 성별
        "email": email_receive				# 이메일
    }
    user_list = list(db.users.find({'name': username_receive, "gender":gender_receive}))
    len_user = len(user_list)				# recive값과 중복된 리스트의 갯수
    if len_user == 0:					# 중복된 값이 없음
        db.users.insert_one(doc)
        msg = 'success'					# 성공 메시지
    else:
        msg = 'fall'					#회원중복 / 실패 메시지
    return jsonify({'result': msg})