728x90

(1) WIL(Weekly I Learned) - 7~8주차

  • 4/9일 항해를 시작한 후 처음으로 프로젝트 진행 기간이 2주인 미니 프로젝트 주차가 시작되었습니다.
  • 팀은 총 4인 백엔드(Spring) 2분(저 포함), 프론트엔드(React) 2분으로 구성되었으며 다시 팀장을 맡게되었습니다.
  • 이전 클론코딩에서의 부족함을 느낀분들을 위해 캐치업 조가 새로 생겨 프로젝트 조, 캐치업 조를 본인이 선택 하여 들어갈 수 있도록 변화가 생겼습니다.

(2) 일정

  • 4/9 - S.A 제출 / 주제 선정 / 와이어프레임 / API설계 / 중간점검 목표 / 2주 진행 계획
  • 4/10 - 튜터 서면 피드백
  • 4/14 - Deer, 알파카 협력사 발표
  • 4/16 - 팀 별 중간체크 / 발제 없음1) WIL(Weekly I Learned) - 7주차
  • 4/22 자정까지 - 결과물 제출
  • 4/23 10:00 ~ 11:00 - 둘러보기
  • 4/23 11:00 - 실전프로젝트 발제

(3) 배운점

  • Web Socket 통신을 이용한 채팅
  • Embedded Redis 사용
  • Spring Security 와 JWT 혼합 사용
  • HtmlEmail객체를 이용한 Email 보내기
    • 비밀번호 찾기를 위해 사용
  • 카카오 소셜로그인
    • 프론트엔드에서 처리 후 카카오에서 받은 Token을 백엔드로 넘겨주어 해당 유저 정보를 DB에 저장 및 JWT 생성 후 프론트엔드로 새로 생성된 Token을 발급

(4) 미니 프로젝트


(5) 느낀점

  • 다들 자신의 주특기에 자신있는 분들을 만나 프로젝트를 순조롭게 진행 할 수 있어 4/16 중간체크 이전 까지 주요 기능인 채팅을 완성할 수 있었습니다.
  • 지금까지 정확한 시간계획 없이 프로젝트 진행, 주특기 공부 등을 하고 있어 정리가 잘 안되는 느낌을 받아 항해 99에서 만난 분들과 시간을 정해 알고리즘 공부를 하기로 하였습니다. 21:30 ~ 23:30 까지 Python 을 이용하여 프로그래머스, 백준 알고리즘 을 풀어 서로 도움되는 시간을 가질 수 있고, 지속적으로 알고리즘을 공부함으로 알고리즘에 익숙해 질 수 있을 것 같습니다.
  • 채팅을 만들며 기본 CRUD를 사용하는 것이 아닌 WebSocket통신을 접할 수 있어 알림, 채팅 등 실시간으로 이루어지는 것에 대해 조금이나마 이해할 수 있었습니다. 아직 Redis에 대해서는 더 공부해야 할 필요성을 느꼇습니다.
  • 처음 WebSocket을 이용하여 채팅을 구현한 것이여서 기분이 매우 좋았으며, 팀원분들과 직접 구현한 채팅 페이지에서 채팅을 하며 소소한 즐거움을 얻을 수 있었습니다.
  • 카카오 소셜로그인은 심화 Spring강의에서 한 프로젝트 안에 백엔드, 프론트엔드가 공존할때에만 구현한 경험이 있어 이를 토대로 소셜로그인을 React와 같이 하려 했지만 Redirect하는 부분에서 Token을 어떻게 넘겨줘야하는지에 문제가 있어 프론트엔드에서 카카오Token을 백엔드로 넘겨주는 방식으로 해결하였습니다. 이게 올바른 방법인지는 아직 해답을 찾이 못하였으나 마지막 코드리뷰때 문의할 예정입니다.
  • 비밀번호 변경하는 방법을 메일보내는 것을 통해 구현하였습니다. 비밀번호 찾기 시 랜덤한 인증번호를 메일과 프론트엔드에 보내어 인증번호를 올바르게 입력하였을때 비밀번호를 변경 할 수 있는 페이지에 나오게 하였는데, 그리 어려운 기능은 아니였지만 Spring boot 코드에서 메일을 보내는 기능을 추가 하여 재밌는 경험이였습니다.

반응형
728x90

(1) WIL(Weekly I Learned) - 6주차

  • 4/2일 아쉬웠던 주특기(Spring) 심화가 끝나고 드디어 기다리던 클론코딩 프로젝트가 시작되었습니다.
  • 팀은 총 4인 백엔드(Spring) 2분(저 포함), 프론트엔드(React) 2분으로 구성되었으며 또 다시 팀장을 맡게되었습니다.

(2) 일정

  • 4/2 1차멘토링 전까지 - S.A완료
  • 4/5 ~ 4/6 - 2차 멘토링
  • 4/8 - '쌀 팔다 개발자' 김병욱님 강연
  • 4/8 자정까지 - 클론코딩 결과물 제출
  • 4/9 10:00 ~ 11:00 - 다른조 클론코딩 둘러보기
  • 4/9 11:00 - 미니프로젝트2 발제

(3) 배운점

  • S3를 이용한 이미지 업로드
  • CORS - 타 IP에서 접근을 허용
  • Spring Boot 에서의 JWT 토큰 사용
  • @Valid - 유효성 검사
  • Git - Pull Request
  • Controller 예외처리 및 에러 메세지 보내기

 

 


(4) 클론 코딩


(5) 느낀점

  • 처음으로 백엔드와 프론트엔드로 나누어 프로젝트를 진행하는 경험을 할 수 있었습니다. 혼자만의 속도가 아닌 팀원 전체의 속도에 맞추다보니 완벽하게 프로젝트를 마무리 하지 못하여 아쉬움이 있었지만 그래도 여러사람과의 협업을 통해 프로젝트를 진행 해보았다라는것에 의미가 있었습니다.
  • 매 주차마다 제출하는 단원평가에 코드리뷰, 피드백이 없다 등 아쉬움점을 적어서 인지 스파르타에서 14시~16시에 튜터님이 상시 대기하며 질문 받는 코너가 새로 생겨 프로젝트를 진행 하다 막히는 부분이나 이론상 이해가 안되는 부분이 있으면 물어볼 수 있어 좋았습니다.

반응형
728x90

(1) WIL(Weekly I Learned) - 5주차

  • 3/26일 이전 주특기(Spring)기본을 끝마치고 5주차 주특기(Spring)심화 가 시작되었습니다.
  • 이전과 달리 두분 다 처음보는 분들과 팀원이 되었으며, 랜덤으로 지정된다는 팀장역할을 처음 하게되었습니다.

(2) 일정

  • 3/29 (13:30 ~ 16:30) - 소규모 면담 (신청자 한에서)
  • 3/31 (19:00 ~ 20:00) - 항해톡 (SSL, JWT, index(database), ORM) 크루원 중 신청자 발표
  • 4/1 까지 숙제 완료!
  • 4/2 (~10:00) - 클론 코딩 발제

(3) 배운점

  • Controller
    • Servlet
    • Controller
    • RestController
  • DI
  • Bean
  • IoC
  • 스프링 시큐리티
    • 소셜로그인(카카오)
    • OAuth
  • 테스트 케이스
    • JUnit
    • Mock, Mockito
    • 통합 테스트
  • 영속성

(4) 기본 과제

  • 조건
    • 회원가입
      • 닉네임, 비밀번호 조건에 안맞는경우 에러메세지
    • 로그인 및 검사
    • 소셜로그인
    • 게시글 / 댓글 조회
    • 댓글 작성 / 수정 / 삭제 (로그인 및 자기가 작성한 사용자만)
    • 회원가입 테스트 코드 작성
  • 링크 - loafly.shop/ (현재 닫은 상태)

(5) 느낀점

  • 심화에서는 기본에서 배웠던것에 대한 전체적인 리뷰와 Servlet을사용한 코드, Controller와 RestController를 사용한 코드 등 여러 방법에 대해 배웠습니다.
  • Spring 시큐리티를 이용한 로그인 기능과 소셜로그인 기능을 구성 해 봄으로써 Spring에서 로그인은 기본적으로 도움을 주는 기능들이 있구나 느꼇습니다.
  • 전체적으로 강의 내용이 코드를 전체복사, 붙여넣기 방식으로 진행되어 이해하지 못한부분도 많이 있어 다른강의를 보거나 개인적으로 공부하여 스프링에 대해 더 자세히 알아야 할 필요가 있다고 느꼇습니다.
  • 과제를 해도 코드리뷰, 과제답안 등 피드백이 없어 과제를 잘했는지 잘 못했는지 감을 잡을 수 없어 아쉬움이 있습니다.

반응형
728x90

(1) WIL(Weekly I Learned) - 4주차

  • 3/19일 이전 알고리즘주차(2주)를 끝마치고 4주차 주특기주차가 시작되었습니다.
  • 주특기(Spring)을 선택한 저는 Spring을 선택한 분들과 같은조가 되었다.
  • 이제 본격적인 주특기를 배워봅시다!

(2) 일정

  • 3/23 (16:00 ~ 18:00) - 소규모 면담 (신청자 한에서)
  • 3/24 (19:00 ~ 20:00) - 항해톡 (try-catch예외처리, Git Github, 쿠키 세션 캐시, DNS) 크루원 중 신청자 발표
  • 3/25 까지 숙제 완료!
  • 3/26 (~10:00) - 주특기 심화 발제

(3) 배운점

  • IntelliJ
  • 자바
    • 자바 기초문법
    • 클래스
    • private, public
    • Getter, Setter
  • Gradle이란?
  • RDBMS
  • Spring boot
    • H2
    • JPA
    • Lombok
    • DTO
    • Controller
    • Service
    • Repository
  • ARC

(4) 기본 과제

  • 조건
    • 서비스 완성
      • 전체 게시글 목록 조회 페이지
      • 게시글 작성 페이지
      • 게시글 조회 페이지
    • AWS 배포
      • RDS 연결
      • EC2 배포
  • 링크 - loafly.shop/

(5) 느낀점

  • 기본적인 RestFul api 사용, IntelliJ 사용법 에 대해 익혀 간단한 게시판을 만들었습니다.
  • Spring을 배우면서 Getter, Setter 등 여러 어노테이션을 배우면서 사용에 대한 편리함을 느꼇습니다.
  • 이전 Python Flask를 이용하여 만든 경험이 있어 그렇게 어려운부분은 없었으나 RestController에서 페이지 이동하는 방법을 몰라 많은 고민을 했었습니다. 결국 Controller를 따로 추가 하여 View에 접근하는 것을 해결했습니다.
  • JPA가 Java를 SQL언어로 자동으로 번역 해주는 편리성을 가지고 있어 스프링에 또한번 반했습니다.
  • ARC를 통해 프론트엔드를 만들지 않고 api를 테스트 해볼수 있다는것이 신기했고 새로운걷을 배워 좋은 경험을 했습니다.

반응형
728x90

(1) WIL(Weekly I Learned) - 3주차

  • 3/12일 이전 2주차가 알고리즘을 이어서 3주차 알고리즘이 시작되었습니다.
  • 2주차 동안 같이 프로젝트를 진행했던 팀원분들과는 헤어지고 랜덤으로 생성된 다른 팀으로 재조정 되었습니다.
    • (2주차에서 같은조였던 분과 3주차에서도 같은조가 되었습니다.)
  • 2주차 보단 어려운 문제들로 이루어져 총 35문제를 각자의 속도로 제시된 문제들을 모두 풀면 됩니다.

(2) 일정

  • 3/12 (09:00 ~ 12:00) - 항해 99내에서 진행하는 코딩 테스트 진행(3문제) 및 코드설명(youtube올리기) 1문제
  • 3/12 ~ 3/18 - 권장요일에 맞는 문제풀이 
  • 3/17 (15:00 ~ 16:00) - 주특기 면담
  • 3/17 (22:00) - 주특기 선택 완료
  • 3/19 (09:00 ~ 12:00) - 항해 99내에서 진행하는 코딩 테스트 진행(3문제) 및 코드설명(youtube올리기) 1문제
  • 3/19 - Spring, Node.js, React, React Native 주특기가 같은 주특기끼리 조 변경

(3) 배운점

  • 알고리즘
    • 브루트포스
    • 그리디 알고리즘
    • 분할정복
    • 백트래킹

(4) 문제풀이


(5) 느낀점

  • 항해99를 시작한지 겨우 3주(21일)밖에 안지났는데 하루 최소 12시간 이상 씩 매일 하다보니 체감상 3달은 된거 같습니다. 적은 일수로 많은 것을 해내기 위해 필요한 것들만 배울 수 있도록 커리큘럼이 짜여져 있어 항해 99가 끝난 후에 어떻게 되었을지 기대가 많이 됩니다.
  • 몰랐던 알고리즘(백트래킹, 분할정복, 다익스트라)을 적용해야만 풀 수 있는 문제도 있어 혼자 고민하면서 시간을 흘러보내며 결국 인터넷을 찾아봐서 알게되었지만 문제를 해결하려고 시도한 덕분에 알고리즘에 더욱 익숙해질 수 있었습니다.
  • 2주동안 배우고 연습했던 알고리즘으로 3/20 Startup Coding Festival을 지원해 시험을 봤습니다. 4시간동안 총 6문제를 풀면되는데, 6문제 중 2문제만 정답으로 처리되고 2문제는 예제만 통과해 많이 아쉬웠고, 열받았습니다. 알고리즘 공부를 나름 열심히 했다고 생각했는데 더욱 더 열심히 해야하는 생각이 들었습니다. (지속적으로 최소 하루에 2~3문제는 풀기)
  • 다음 커리큘럼(3/19) 부터 각자 선택한 주특기(Spring)에 대해 배우게 되는데, 이제 본격적으로 서비스를 만드는 준비를 하는거 같아 설렘을 느끼고있습니다.

반응형
728x90

(1) WIL(Weekly I Learned) - 2주차

  • 3/5일 이전 1주차가 끝남과 동시에 2주차 커리큘럼인 알고리즘이 시작되었습니다.
  • 1주차 동안 같이 프로젝트를 진행했던 팀원분들과는 헤어지고 랜덤으로 생성된 다른 팀으로 재조정 되었습니다.
  • 알고리즘에 대해 이해할 수 있는 문제들이 제시 되어 해당 요일들을 권장요일에 맞춰 문제를 푸는 형태이며, 별도의 수업은 없으며 사전지식이 없는 경우를 대비해 스파르타 코딩클럽에서 운영하고 있는 알고리즘, 파이썬 기본문법을 수강할 수 있도록 무료로 열어 주어 개개인의 실력차를 스스로 맞춰나갈 수 있도록 진행되었습니다. 
  • 3/5일 ~ 3/11일 까지 21문제가 제시 되었고, 각각 난이도는 하하 ~ 중상 까지 있었습니다.

(2) 일정

  • 3/5 ~ 3/11 - 권장요일에 맞는 문제풀이
  • 3/5 ~ 3/11 - 모르는 부분을 채우기 위한 동영상 강의 보기 (스스로 부족한 부분만 봐도 무방)
  • 3/10 (19:00 ~ 20:00) - 항해톡 진행 (항해99 크루원(참가자) 중 지원한 4명을 선정해 각각 RestAPI, https, 프로세스와 스레드, 시간복잡도 에 대한 설명)
  • 3/10 (20:00 ~ 21:00) - 튜터님의 <알고리즘을 대하는 자세> 특강

(3) 배운점

  • 성능
    • 시간복잡도
    • 공간복잡도
    • 점금표기법
  • 자료구조
    • 링크드 리스트
    • 트리
    • 그래프
  • 알고리즘
    • 이진탐색
    • 정렬
      1. 버블정렬
      2. 삽입정렬
      3. 병합정렬
    • 해쉬
    • DFS & BFS
    • DP(Dynamic Programming)

(4) 문제풀이

 


(5) 느낀점

  • 3/5 초반부 문제들은 사칙연산, 조건문, 반복문, 문자열 등 대체로 쉬운부분 이여서 무난하다 후반부분에서 익숙치 않은 알고리즘을 만나 시간을 많이 소모하기도 했습니다. 1주차에 비해 팀원분들과 소통하는 시간은 유일하게 풀었던 문제 코드리뷰, 또는 모르는 문제 물어보기 밖에 없어 개개인이 각자 문제 푸는 시간이 많고, 팀원들과의 속도가 맞지 않아 쉬는 시간을 더 많이 갖고, 집중력도 떨어져 열심히 안한것 같아 나 자신에게 실망했습니다. 
  • 그래도 후반부에 나오는 DFS/BFS, DP, 이분탐색 등 코딩 테스트에 자주 출제하는 알고리즘을 사용해야하는 문제들을 알려주고, 배우며 익숙해지고있어 만족스러웠습니다.

반응형
728x90

(1) WIL(Weekly I Learned) 시작

  • 3월 1일, 빨간날과 상관없이 항해 99가 시작되었습니다.
  • 공식적으론 아침 9시 ~ 저녁 9시까지 공부를 해야 한다고 나와있지만 부족한 점이 많기에 아침 9시 ~ 새벽(자기전) 까지 계속 진행되었습니다.
  • 항해 99를 시작 하기 전 웹 개발에 대해 지식을 조금이나마 채울 수 있도록 항해 99에선 웹 개발 종합반 수업을 열어 사전학습을 하도록 한 후 3월 1일 부터 바로 3명의 랜덤 팀원들과 미니 프로젝트를 진행하게 되었으며, 1주일 간 배운 것을 회고할 수 있도록 WIL을 추천하여 이 글을 쓰게 되었습니다.

(2) 일정

  • 3/1 ~ 3/4 - 팀 배정 및 웹 개발 미니 프로젝트
  • 3/5 - 3/1 ~ 3/4 동안 만들었던 미니 프로젝트 발표 및 팀 배정
  • 3/6 ~ 알고리즘 문제풀이

(3) 배운점


(4) 미니 프로젝트

 


(5) 느낀점

  • 팀 배정을 받은 후 3/4일 자정까지 부족한 시간으로 프로젝트를 진행하게 되었습니다. 공대생 3명으로 이루어진 팀이여서 그런지 프로젝트 완성 후에도 디자인이 너무 투박해 아쉬운 면도 있지만 팀원들과의 협업을 통해 하나의 프로젝트를 완성했다는 것이 만족스러웠습니다.
  • 프로젝트를 진행 하면서 JWT를 사용하라는 조건이 있어 JWT에 대해 자연스럽게 알게되었으며, 또 한번 사용해보게 되어 공부가 많이 되었습니다. 또한 조건에 없는 경우에도 프로젝트를 만들면서 필요한기능을 하나 둘 씩 생각하고 찾아보면서 몰랐던 부분을 새롭게 알게되었고, 혼자 아침 9 시부터 자기전 까지 계속 컴퓨터 앞에 앉아 공부하는 것이 쉽지만은 않은데 Gather을 통해 마이크, 웹캠을 키고 진행을 하게 되어 온라인이지만 오프라인에서 공부하는 느낌이 들어 팀원들과 힘을 내 매일매일 9시부터 자기전까지 개발을 할 수 있었습니다.
  • 3/5일 다른 팀 총 32개조의 미니 프로젝트를 보면서 여러 아이디어를 보며 사전학습에 배웠던 '크롤링'만으로 여러 가지를 할 수 있구나를 보며 신기했습니다.
  • 3/6일 부터 알고리즘 주차가 시작되었습니다. 항해 99 튜터 분들이 정해 놓은 문제를 하나 둘 씩 풀면서 푼 문제는 팀원들과 코드리뷰, 어려운 문제가 있는 경우 서로 도와주며 진행하고있으나, 아직 쉬운문제이기에 다음주에는 항해 99에서 열어준 알고리즘 수업을 듣고 문제를 푸는 방식으로 갈 예정입니다.

반응형
728x90

(1) 강의내용

  • AWS
    • AWS 서버 구매하기
    • 서버 세팅하기
    • flask 서버 실행해보기
    • AWS에서 포트 열어주기
    • Robo3T에서 DB연동
    • 포트 포워딩
    • nohup 설정하기
  • 도메인 구입
  • og 태그 만들기
  • 5주차 숙제
    • 도메인 올리기

(2) AWS

  • EC2 서버 구매하기
    1. aws.amazon.com/ko/ <- aws링크에서 회원가입 및 로그인
    2. EC2를 사용하여 클릭
    3. Ubuntu Server 18.04 LTS(HVM), SSD Volume Type - 64비트(x86) 선택
    4. 검토 및 시작
    5. Key Pair를 저장 후 런치
  • EC2 서버에 접속하기
    • git bash로 입력
    • ssh -i 받은키페어를끌어다놓기 ubuntu@AWS에적힌내아이피

 

 

  • 서버 세팅하기
    1. Filezilla 실행
    2. Connect 버튼 클릭
    3. New Site 버튼 클릭
    4. Protocol : SFTP, Host : AWS에 적힌 아이피, Port : 22, Logon Type : Key File, User : ubuntu,                                     Key File : Key pair 위치
    5. Filezilla에 아래 initial_ec2.sh 다운
    6. sudo chmod 755 initial_ec2.sh 로 환경 세팅
  • AWS에서 포트 열어주기
    1. EC2 관리 콘솔로 이동
    2. 해당 인스턴스 클릭
    3. 보안 클릭
    4. 보안 그룹 클릭
    5. 인바운드 규칙 편집
      • HTTP / TCP / 80 / 사용자 지정 / 0.0.0.0/0
      • HTTP / TCP / 80 / 사용자 지정 / ::/0
      • SSH / TCP / 22 / 사용자 지정 / 0.0.0.0/0
      • 사용자 지정 TCP / TCP / 5000 / 사용자지정 / 0.0.0.0/0
      • 사용자 지정 TCP / TCP / 5000 / 사용자지정 / ::/0
      • 사용자 지정 TCP / TCP / 27017 / 사용자지정 / 0.0.0.0/0
      • 사용자 지정 TCP / TCP / 27017 / 사용자지정 / ::/0
  • Robo3T DB 연동
    1. Connect 클릭
    2. Create 클릭
    3. Connection Settings
      • Connection
        • Type : Direct Connection
        • Name : dbName
        • Address : AWS에 적힌 아이피 : 27017
      • Authentication
        • Perform authentication 체크
        • Database : admin
        • User Name : test
        • Password : test
    4. Test 후 저장
    5. Python Code 변경
client = MongoClient('mongodb://test:test@localhost', 27017)
  • nohup 설정하기
    • nohup이란? SSH 접속을 끊어도 서버가 계속 동작하고 있음
# 아래의 명령어로 실행하면 된다
nohup python app.py &

# 아래 명령어로 미리 pid 값(프로세스 번호)을 본다
ps -ef | grep 'app.py'

# 아래 명령어로 특정 프로세스를 죽인다
kill -9 [pid값]

 

initial_ec2.sh
0.00MB


(2) 도메인 구입하기

  • 도메인 구입/연결
    1. www.gabia.com/ <- 가비아링크에서 회원가입 및 로그인
    2. 도메인 구입
    3. DNS 관리 툴 클릭
    4. 해당 도메인 설정 클릭
    5. 값/위치 에 IP 작성 후 저장

(3) og 태그

  • Code
<meta property="og:title" content="내 사이트의 제목" />
<meta property="og:description" content="보고 있는 페이지의 내용 요약" />
<meta property="og:image" content="{{ url_for('static', filename='ogimage.png') }}" />
 

카카오계정 로그인

여기를 눌러 링크를 확인하세요.

accounts.kakao.com

 

공유 디버거 - Facebook for Developers

공유 디버거를 사용하면 Facebook에 공유될 때 콘텐츠가 표시되는 모습을 미리 보거나 오픈 그래프 태그를 사용하여 문제를 디버깅할 수 있습니다. 이 도구를 사용하려면 Facebook에 로그인하세요.

developers.facebook.com


(4) 5주차 숙제


(5) 느낀점

드디어 마지막 5주차가 끝났습니다. 현재 취준생인 저로써는 하루에 1주차씩 5일정도를 소모하여 5주차를 완료할 수 있었습니다.

웹개발 종합반을 들으면서 대단한건 아니지만 처음부터 끝(도메인)까지 개발한 경험을 얻을 수 있어 의미있는 시간이였고, 학생들이 흥미를 느낄 수 있도록 수업 커리큘럼이 잘 짜여진 것 같습니다. 하지만 짧은 시간을 들여서 경험한 전체적인 틀을 조금조금씩 다루는 정도 여서 깊이는 조금 아쉬웠습니다. 


반응형
728x90

(1) 강의내용

  • Flask
    • Flaks 패키지 설치
    • html 파일 불러오기
    • Get / Set
  • 미니프로젝트1
  • 미니프로젝트2
  • 4주차 숙제

(2) Flask

  • Flask 란?
    • 파이썬으로 작성된 웹 프레임워크 중 하나로, Werkzeug툴킷과 Jinja2 템플릿 엔진에 기반을 둔다.
  • Flask 패키지 설치
    • New Project를 통하여 Virtualenv(가상환경)을 같이 만들어 준 후 3주차 Python과 동일하게 Flask 패키지를 다운받는다.
    • 이미 프로젝트가 있을경우 Terminal에서 명령어 python3 -m venv .venv를 입력해준 후 패키지를 다운받는다.
  • html 기본코드
from flask import Flask, render_template
app = Flask(__name__)

## URL 별로 함수명이 같거나,
## route('/') 등의 주소가 같으면 안됩니다.

@app.route('/')
def home():
   return render_template('index.html')

if __name__ == '__main__':
   app.run('0.0.0.0', port=5000, debug=True)
  • html 파일 불러오기
@app.route('/login')
def home():
   return render_template('login.html')
  • Get / Set
@app.route('/login', methods=['GET']) //안쓸경우 GET
def login_get():
   return render_template('login.html')

@app.route('/login', methods=['POST'])
def test_post():
   id_receive = request.form['id_give']
   print(id_receive)
   return jsonify({'result':'success', 'msg': '이 요청은 POST!'})

(3) 미니프로젝트1 ,미니프로젝트2

  • 모두의 책 리뷰
  • 나홀로메모장

1~3주차동안 배운 내용을 통해 프로젝트를 만들고 Flask 서버로 실행시켜보기


(4) 4주차 숙제

  • app.py
from flask import Flask, render_template, jsonify, request

app = Flask(__name__)

from pymongo import MongoClient

client = MongoClient('localhost', 27017)
db = client.dbhomework


## HTML 화면 보여주기
@app.route('/')
def homework():
    return render_template('index.html')


# 주문하기(POST) API
@app.route('/order', methods=['POST'])
def save_order():
    userName_receive = request.form['userName_give']
    count_receive = request.form['count_give']
    userAddress_receive = request.form['userAddress_give']
    userPhoneNumber_receive = request.form['userPhoneNumber_give']

    doc = {'userName': userName_receive,
           'count': count_receive,
           'userAddress': userAddress_receive,
           'userPhoneNumber': userPhoneNumber_receive,
           }
    db.orders.insert_one(doc)

    return jsonify({'msg': 'good'})


# 주문 목록보기(Read) API
@app.route('/order', methods=['GET'])
def view_orders():
    orders = list(db.orders.find({}, {'_id': False}))
    return jsonify({'all_orders':orders})


if __name__ == '__main__':
    app.run('0.0.0.0', port=5000, debug=True)
  • index.html
<!doctype html>
<html lang="en">

<head>
    <!-- font   -->
    <link href="https://fonts.googleapis.com/css2?family=Play&display=swap" rel="stylesheet">

    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
          integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
            integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
            crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
            integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
            crossorigin="anonymous"></script>

    <title>스파르타코딩클럽 | 부트스트랩 연습하기</title>

    <style>
        * {
            font-family: 'Play', sans-serif;
        }

        .TextGroup {
            text-align: left;
            margin-bottom: 30px;
        }

        .TextGroup_span {
            font-size: 20px;
        }

        .Exchange_Rate {
            text-align: left;
            color: blue;
            padding-bottom: 30px;
        }

        .InputGroup {
            margin-bottom: 20px;
        }

        .col-auto {
            margin-bottom: 15px;
        }

        .wrap {
            width: 600px;
            margin: auto;
            text-align: center;
        }

        .table {
            margin-top: 30px;
        }

    </style>

    <script>
        $(document).ready(function () {
            $.ajax({
                type: "GET",
                url: "https://api.manana.kr/exchange/rate.json",
                data: {},
                success: function (response) {
                    let Exchange_Rate = response[1]['rate'];
                    $('#Id_Exchange_Rate').text('달러-원 환율 : ' + Exchange_Rate);
                }
            })
            getOrder();
        });

        function postOrder() {
            let userName = $('#inlineFormInputGroup').val();
            let count = $('#inlineFormInputGroup2').val();
            let userAddress = $('#inlineFormInputGroup3').val();
            let userPhoneNumber = $('#inlineFormInputGroup4').val();

            $.ajax({
                type: "POST",
                url: "/order",
                data: {
                    userName_give: userName,
                    count_give: count,
                    userAddress_give: userAddress,
                    userPhoneNumber_give: userPhoneNumber
                },
                success: function (response) { // 성공하면
                    alert(response["msg"]);
                    window.location.reload();
                }
            })
        }

        function getOrder() {
            $.ajax({
                type: "Get",
                url: "/order",
                data: {},
                success: function (response) { // 성공하면
                    let orders = response['all_orders']

                    for (let i = 0; i < orders.length; i++) {
                        let userName = orders[i]['userName'];
                        let count = orders[i]['count'];
                        let userAddress = orders[i]['userAddress'];
                        let userPhoneNumber = orders[i]['userPhoneNumber'];

                        let temp_html = `<tr>
                                            <td>${userName}</td>
                                            <td>${count}</td>
                                            <td>${userAddress}</td>
                                            <td>${userPhoneNumber}</td>
                                        </tr>`

                        $('#order_table').append(temp_html)
                    }
                }
            })
        }

        function btn_OnClick() {
            alert('주문이 완료되었습니다');
            postOrder();
        }
    </script>


</head>

<body>
<form>
    <div class="wrap">
        <img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxISEhUTExIVFRUWGBUZFRYYGBUaGBcYFxkZFhUYFRYYHSkgGBolHRYWITEjJSkrLi4uFx81ODUsNygtLisBCgoKDg0OGhAQGzAlICUtLy0tLy0tLS0tLS0tLy0vLS0tLS0tLSstLS0tLS0tLS0tLS0rLS0tMC0tLS0tLS0tLf/AABEIAOEA4QMBEQACEQEDEQH/xAAbAAEAAgMBAQAAAAAAAAAAAAAAAwQCBQYHAf/EAEcQAAEDAgMDCAUICQQCAwEAAAEAAhEDIQQSMQVBUQYTIjJhcYGRB0JyobEUIzNSU5LB8DQ1Q2KCsrPR0hYkk/Gi4UTC4hX/xAAbAQEAAwEBAQEAAAAAAAAAAAAAAQIEAwUGB//EAD0RAAIBAgQCBQoFAwMFAAAAAAABAgMRBBIhMUFRBRNhgbEUIjIzcZGhwdHwFTQ1QuEjUlOi0vEGJGJygv/aAAwDAQACEQMRAD8A9xQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAfHOAEkwOJQEdLEMdOV7XRrBBjvhASoAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIDV7T5QYehIfUBd9VvSd4gaeMKyi2cp14Q3Zy20eXjzIo0w3959z90WB8SuipczHPGv9q95zOM2pWrOaatRz+k2xPR1GjRYeS6xilsYa1Wc15zGKwVIvLsjc09YCHfeF1Zwi90ZY4irDSMmiWjXr0/o8ViGdnOuePu1cwVXRiaI9JV1vZ930LtLlNtFmlenU7KtET96m5vwVHQ5M0R6W/uj7mXKPL/FN+kwlOoONKqWn7tRv/wBlR0ZGiPSdB73Xd9C9S9JeH/a4fFU+J5sPaP4qbiqOElwNUMVRntJe82GC9IOzKpgYpjTweHUyO/OAFU73ubzCbToVfo61Op7D2u+BQFtAEAQBAEAQBAEAQBAEAQBAEAQBAEAQHE+kDHVGOpsa9zWuaS4AxN4vGoXWmkYsXOSskzhyup5zMVJU+0+s32m/EKUc6mxtK/WPeVcyMiKkqYlCCN6kgicpKkNVod1gD3gH4qHFPctGpKHotop1dm0Tc02+FvdoqOjB8DTDpDER/d7ybDPrUhFHFYinGgFRxH3SYK5vDrgzTDpeovSin8DYYXlftal+3o1xwqU8p82Kjw8uBqh0vTfpJr4m6wfpQrNtXwDjxdRqNd5Mdf3qjpTXA1Q6Qw8v3HQ7O9Imz6tnVXUHfVrMdT/8j0feqNNbmqNWEvRaZ02GxTKgzU3te3i0hw8woLkyAIAgCAIAgCAIAgCAIAgCA4H0i/TU/YPxXWmYMZujlGUHO0B793n4FdbmNQb2JBgDvc0b9e/+yXJ6l8WQhoFQAGRnAB4jNYqyM1XS9jYVdSrmNkZUlTEoQRuUkMhcpKkZQgwchBGUBiVJBiUJPsKCy0O39FlEB9cgACGWAiTLrrLXSVj3eiZSlnbfL5noD3gakDvMLOeu2luYfKGfXb5hTZkZo8x8oZ9dvmEsxmjzHyhn12+YSzGaPMfKGfXb5hLMZo8x8oZ9dvmEsxmjzHyhn12+YSzGaPM+trNNg4E9hCixKknxJEJCAIAgCA4P0g1C2vSI1DD8V1p7GHFyalFrtOZfUqvGabTGoGtu+LrpoZm5yVyDFUC2JMyJ0d8SL+ClHGcXHcjoDps9pvxCsjhU2NjU1KuZGYFSQYlCpE5SQRPUlSNyEGBQgjKkgxKAQoJVj4gud76NKjGsrFzmtlzRcgaAnf3rLXTuj3+iZRVOV3x+RN6SazXUaWVzXQ+8EH1TrCnDK0jn03JSoKz/AHfJnnsLafL6iEGplTiROkiY1jfCO9tC0LZlm24l7bbcOHj5NnLMonOIObfErnSz2841454dzXk6sra+3v1NfC6GLUtHZlYYcYohvN5ojMwuiOt1tJMRE9kdJY1i/OtbQ+nl/wBPWw+fP51r2s7ezb43t36G05DNPy2lA0zz2DKR+K7Yj0DzOh03ik+x+B60vPPsAgCAIAgOC9IjSa1KL9A/FdaZgxiu13nPYcvy5QyZdvHZx42+CucI5stkiDE0Xm+QNgE2JJItcyTx7N6k5zhJ62MG0SypTBIMlpkTHWjeBwV4nCtFx0Lj9VcwmBUkGJQqRvUkMhepKkRQgxKEEVQ2QWLuHZTLW5ss3mXOB1tIjhw4KW5cClONJxWa1/ayYsoibMNhbPU4X9XsPmPGLyOmWj2e9/Q1jiJMCBuHBdDC7X0LTKdHmCS889zlmx0RTjUmNZ7Vz8/P2Gx+TeTK3rL9u3h8youhiOo2fiMLzTAaLcwAzEhpzOsSZIMC8R2dizyU7vU9yhPDdXFOKvx2d2V9sYjDmiQ2k1r5Dg4ANyiBLSAL7ypgpZtXocsVKg6Vox1vpw7hTZVlreeoW0s0i7Z0jgfMKPNtezLtVc2XPEkw4rVTlFWm6Gc6XNbOUB7Q+bAyB0iN8cdDyxW3YRDrarspJ6Zrpdqv9SSphKrqbumPoWvPzMZg5hrAB4N+qQXfWgb0TSffz7i8qdSVN6/tv6O91m3+fOy4nM7R2SKNUsJecrs2XM8U85blLhTJyzHRzRcBTClTbzpanLE4/GU4vDSm8trd3L2XN5yGd/vaX8f8pU4j0GU6H/Nx9j8D1peefYhAEAQBAcVy5qhtekT9m8e9dIGTESUZJvkzmDtAACJ60x3i9++PILpYyuskiCpjgRGU2mIdGoiTYzv81NjnKsnw+JHz+erTMRdouSSelNye9XijPXnmsy0/VXMJiVJBiUII3qSpC9CrIypIMChBG9BYlwdJrngPfkbDiXRMQ0kW3zEeKvJtLQzUYRlO0nZcy23ZjD/8mloTqZtFo439ypnfI0rCQ/yIyGymW/3FIAj62hGoTrHyZPkcP8kfeYUdnMLcxr0wYsJvMgQeG9HN32KxwsHG7qIyq7MYCAMRTIJiZ06OaTG6ej3opvkTLCwTSVRfav8AwfWbKZInE0gDPrd0SPHvsU6x8iVhIX1qI1j2wSOH53LojFJWdi9g9nBzA4vINrBpPxI7PyFRzsa44VSV2/gbHA4U0XEsqkEwJNPcHtePW4sFuHeqSlmWqNFGi6Mm4y+Hanz7CkcVUDnOaWglrGSGvs2nkDYta1Ns+PFWsrWZw6yopOUXbRLZ7K30RHjalSu8OeQXQ1tmkTFhMNiVMUorQpWdSvJOT122f0L3If8ATaX8f8jlTEegzT0P+bj3+DPW1559iEAQBAEBwfpHHzlH2X/ELrT4mDG7x7/kaHCtimDDbh0kxo1zZ13w4hXOcF5qf3uiHa9MiNLlxMR1rB2na1TE54iNrFLDddntN+IV0YqmxsHK5kMSpIMChBG5SQyFyFGYFSQYFBYiqH8EDZ8XQwBAdDs3AUHUM7izNFTNJrTLQDuENgPbudN+4cJzkpWXyPWw+HoSo5pWvZ39Lh8Fa64O5AzZ9IucQ5jm8yXNGe4eKQJJEyIfOqtndu8osNTcm001luteOX68zLamEohjjTZBERLmE7p0rGfBqiEpX1f37icTRpKDcI271/vfgaNdjywgLHMkFrS4Xy3vAnjwVU7q5pnBxnlbJcdh+bIh4dIOhkjvSMr8Ca9Lq3o7mD2ANa7MZOo7PyET1sVlFKCd9WZ/JZp5g68SRIiNI1me8DXzjNrYv1LdPMn2/fabHkT+nUu9/wDK5UxHq2aeiPzce/wZ60vPPsQgCAIAgOD9JHXo+y/4tXWnxMGN3j3/ACOU+U9AsjWLz+9mNl0sZes83KMXjC8RAEOcRxhxmJ36lErEVKuZW7WQYX6RntN+IV0ZqmxsHaq5kPhQgwcpKkbkIIXKSrI4lSRYPtbzUBlnE42k4EmgMxm4JAFxlsDqPeqpSXE1TrUZJtw11+9y1ydZQLaorZJLQGZiBEzcX7tNPFWquV1Yz4CNFxmqlr8Lk8YQ1ndJonEMLQRLBTa7K5uYDKA7MXbwAwSbqvn5e46/9s6r1S89eyyeqvtre/Ky1LGEGE5sEtpSOckuc0OIHO5ZboCczIgHqjwrLPc7Ulhcl2o8eKvxt4r3FenXwrqJGSmKgpOiS4EOyAWJZDnEgm5JkwFZqal3nGM8NKk1ZXyv329mr46u/IkxXyN7XhnNjpDKQC05TUOXriZyakAqF1iauXn5JOElGy19ml+3s3sVqlOgXMI5puUgECoXBzQDd4LOvOp0PAK15We5ycaDlF+ardt7rt037duwi27zJbTNLJm6ecNPdlnogbj5qaea7uc8b1TjF07X1vb4cEUXBnRytBFpAD78Zk69yur2OFRRzaLTv+fyFcstFMtF51k90mNPiivzKzyaWjYmxLKQb0QZtB6d+/MI8lCcrnSpGko6LXv+ZkxlLIDlBdAOlWPzpvS7v/wWUaWS9tf/AKLnIn9Npfx/yuVMR6tnboj83Hv8GetLzz7EIAgCAIDh/SLTLn0Y+rU+LV0p8TFi4t5bdvyOMrUS3XfoutzDKLW5PgsCHjM52UaDtKhyOtKgpq7diGlSLKzWnUPb8VeLMlaLi7PmXHaroYjEoQYlSQROQhkBvYKSp9daw8UIZC4qSpG/+3xQHxdDAEB12N2PSpsov5sHnjhmi56ILQ6oTfV5kdzXLNGpJtq+1z3quEpQjCWX0nBezi/eZHZzPlFRnyehLRU5hgqfSkPa1oqfOGHZZtbU2tZmeVO77SfJ4ddKLpx0vlV99Utdd7cNCttDYzGsxJptzRUeKcu6lOj0qzhJ6V3NbvKmNRtq/wB32ONbBwjCo4K+rt2KPpPt10OYWg8YIC23EOOQlvVA6siVVJWNcpyck2tuRnia5dHRIjxB7xChKwqVHLgzGpinkQWgDuNvM2UqKRWVWbVmvgfW4wZcuXdEyUy6kqusuWxseRP6bS/j/lcueI9WzV0R+bj3+DPWl559iEAQBAEBxPpDdDqJy5rVLeLF0pmTFO2V25/I491WmdQ7z07pK6amNyg9y3S6jImIJt7Tp+AUHdehEixX01I8cnuMfgrQMuM3T7EfXLseYYlCDFyEEFQzYKSp8PRCEMhJUlTb7Hq020apcWzuBygmGkgA63Nv+1zndtHoYSUI0ZuVr/wYOq0QwhpDui4CcrTLG0mgw4XLi0uGli71hCWdwpUVBpa6Ps2UVx4u1138TSLSfPBAdBhdp16kltDO0NoggBxANCCxwP1tbcCVwlCMd3z+J69HEV6t3CndJR5/t27+wo09pOp4l1csGfM9waZhrnzeOybSumROOW5kjiJU8Q6rjrduz4N/QkwHKGvSYaYIc0te0BzWktzmXOBiTfcTCiVKLdy9HpCrTi4bqzWttL8TUroYAgN9TwmI+TfKCG5LAAg5iN7o0A99idFkU1nyn0dXCyWE66+tr2tpb+ERbJp1sS/m6YbJ1cQYaOJIvu0H91etLItDP0bSeKnJS0S5EW0cRWp1HU3RLSRMawdR2SFemlKKZmxkqlCrKm+G2nDgY4zY1SlRZWdEPIht5AIlpNouBMCYkcVSlWc5WO+P6Mjh6KqRbb2f8FvkP+m0v4/5HK2I9Wzj0P8Am49/gz1teefZBAEAQBAcX6RRehE/tNNfVXSmZMVwOIq39aY4iCuphl7S7s8hzcsjM0mJ4H8nzVXozTRWeNuKIa9QGuwAyGlonjGvvVoGTGSTlZcNCQrqecYkqSpG924aoQz5ljTU/myCxO7Zj98Bx0afxO4qjqq5uj0ZWlDNs+RRr0XMMOBB7d/cd66Jp7GCpTlTeWasyAqTmYP/ALfFSQAF0MCVzs+TnJMOdmrtfDfVMgPO+0TlHGb92uSpX4RPocF0RFvNVT04bXfjbx9h0uKphsNa0NaNAAAB3ALI3fc+hjFRVoqyMauAo1hFVjXd4uO5wuPBWjOUdmc62HpVlapFM5nb/I7K01MPmdGtM3MfuHf3arVTxF3aR4OO6Gyxz0Lvs+n0ObGz3tJNVj2NAkktIPAATvJIHiu+dcDyI4Wau6iaS7CHFUg0iDLXAObOsHce0EEeCtF3OVWCi1bZ6o3ox9QsymoA3KQfmz61Pm3HNM9Xt4LMqcU7ntzxtWUHBtWtbZ8rc+RS2Tj30R82XTmBPzYeAWhwESY0ed3BdalNTephweLnh08mt99L7ctUQ4t5qPbmD7NAADIhrR0crc2nkNVMI5Y2RzxFZ16qlNP2W4Lsv8y5tDaFSrTDHB2URlApBuWJAAIdMXi8qkKai7rx/g1YnG1K9PJJaf8Aq/8AcfeQ/wCm0v4/5HKcR6tnPof83Hv8Getrzz7EIAgCAIDivSQQBQN9X6a6NXSmZMW7JHFOrHiHdjhfzXQxOXeV3PvIt2BSc766GeEPzjPaCsjjU2LpN1cymDjuCkgypsvG86n87lDJjG7sjotg7PYBzpEk9WYsOIG4nxt3rjUm9j28DhYRXWcXtfx7yHEGahXI9EvMpMe3K8Bw4H82KlNrYpUpwqLLNXRzW1tiPY/5trnsNxAJjsP91phUTWp89isBOnP+mm177dhSq4B4YZpkEAGe3MBETplJOmoVlJXOE8PKMHeOtr3+Xu+JUpVC1wcNQQR3i4Xdq6sePCThJSW6PZMDXFRjXjRzQ4eIleU1Z2P0CnNVIKa2auVNo9YKC4ooC9TKA5z0g4gtwwaGyHvEu3Ni48T+BWjDK87nj9NTccPltu/ccDjLCmODB7y5w9zgtkeJ8zWVlFdnjd/M7zD8kMGabZrPu0evT4SfVWLyiR9P+D0HHVv4fQk/0Pgvtan36fj6qnymZH4Hh+b96+h8HIrBfbVPv0/8U8pmPwTD83719Cc8h8M4fSVSO+nu/gULES5FpdD0WrNv4fQ5rk7guY2m2lM5HPE8RkMWXerLNSueXgaPU9IdXe9r+B6esJ9UEAQBAEBxHpN6tHvf8AulPcx4z0UcFK6nntHxSQSYT6RnepRyqbFxzrq5mPot3oQXthhprDMJs6O+P7SqVPRNvR6i6yvyf37rnXjRZz6A5yv9Ie9CC/hSgNg0oCLav0FT2HfAq8d0cMT6qfsfgefYPCPquytHedwHElb5SSV2fDUaM6srRPUeTWFfRw7GPMgTlJ4G+m4STC86q1KTaPs8DTlSoqEu778DPaXWC5m0+UEBy21uWNXnDRwjA8iJcSIJJgATrruSwuafaXKTE1GiliaYDXwW5SASRBBDr7nCxB8CutKSjK5hx9CVak4rbls/fr7rGqxFXO4uiNIHAAQ0eAAXoRVkfGVZOU22rfxpY9bwDOgyS4dFtoqaQJ0K8pn6BHZFhtMH1zrwqD8UJLzKYAge8k/FAZoDzvCfrk+2/wDplbJeo++Z85S/VX3+B6IsZ9GEAQBAEBxXpM6lH2n/AAC6U9zJjPRXtOF+Tuy5ot8Y1K6XV7GRUpZM/AgI4H8VJxM8LOdtvf2FWicqy0Lwt3q5lPkoQWNmuIqsIEwRPdv90qs/RZowraqxa5nbSsx9Kc3XPzh70IL+FKEmwYhBhj2l1F7d5YRfiRCtHRo4105U5Jcn4H3krsZo3S1up+s7t7OzuV6s2zz8DhIwVuC+LOte0EQdFnPVaTVmaTaezsSfonsj98EuHiDfxXSLh+4yVY4laUmu9a+JVbyXfUB+UV3PkHoizPFosVbrEvRRwWBqVHevNvsWi9yPNtp4Gpg8S/PzrGky1zIv0gYMiCInyBuuR6SVtCpi3io6nkc9zWCBmAsBGUCGidO1TGLk7I5V68KMHOTM16iPgpyvJs9awbW8227dG7hwE/s+5eSz9CjsjYta+LPHZdsX19TtQk+9P64+8L339BAWab+JE9hlAefYT9cn23/0ytkvUffM+cpfqr7/AAPRFjPowgCAIAgOK9JnUo+074BXgZMXsvaaDEtDSwbgIQ1JJKxp9o4bI+G6G4/t+exdYu6PLr0sk7LiQYU9Nvj8CrxMVbYuEq5mZnRplxgf9dpUN2LQg5uyN1hcOGiGiSd+8lc27no0qajojfNBAAOsBcWevG9tdznqo+cPehJKzGAHIwc4/gOq32j+A9yuo8WZamKSeSCu/gvab/DghozRO+NFU0RvbXcgxmJYAW5hNhG+ToOxSkc6k4pNXOn2dh+bptbviT3m5XOTuy1KGSCRZUHQIAgKuOZSiauSBvdHlKWIlJR1Zw/KnZtFwJoiN46LgJ3tlwvMCO1aqM8u54nSeH61Nxvp2P3HEkLYfLnrGByBjDJDsrdA0xZeSz9Djsi4zEsEgknvA/AoSZjEs4Hy/wD0gJMPVa4iAe+OHbKA4jCfrk+2/wDplbJeo++Z85S/VX3+B6IsZ9GEAQBAEBwvpVfFOh7bv5VeG5jxnor2nOYvEzzZ4tnzAKg2R1SY2iWmiXECQLHvspi9TjiYrq23wNLhak1PE/iu8TxKxdptLjA1Kvczxi5OyN1h6TaYjedeJ7gubZ6NOmoKy3NpstzM3SMO9UEEeUi5VGzbQik7y34GzrMkawdxVTTJX2NFU2PVe85ngN/dtKsnFGSVOvUdpSsuw22CwdOk2GgDtUNtnelRhTVokzqzRvH5soOl0QsZTLxaczmHQ9hHdb4qbuxTLFs2uNx7mVnDnCGtDSWc2TvbN94v7+5Qo3RnqVXGq9dOVin/AP0Kjm9GvBlly3dBzWy+PgrZVfY5ddNx0ny4fwXqG2GtLucqT0oENIjUx3QR3x2qrg+B2jiYxvnfHkXKO06bnZATmvYgjSCde8Kri0rnaNeEpZVuaHaOMNqpiXF4ZOlNjTEjtNiT2xoArxV9DNVq5Epvd7di+/i+SNeNquF87e0E/ER2bl06tGVYtrW6++40/KzAMDaddgAFQGQNxFj7z8V0oTd3FmDpbDwyxrQ47nX4QSxnGG8b277LEz6aOyNgyk6NWDXVoPvlCxKxnHIR3Ae9ATU4kWHu/sgOEwn65Ptv/plbJeo++Z85S/VX3+B6IsZ9GEAQBAEBwfpZ+ioe27+VXhuY8Z6K9pxmHrZmU/3czT4RHuhRJanbDTzU12aFradVvNFhPSIGUbzBBUx3IxMo5HF7mmwJ+c813ieJVOnwOHyCY6ToEd+g/v8A+lEpGihRt7WbA1BTsOt6zt58PwXO19TdKapebHcypV83ReCQbaRfUeKNWJp1c7yyW5tcFUJYM1yCWk8cpInxgFQaI3tqTyoLkRotmSPyVNyuVHyoHeqG+M9vBCGnwPlMuDmZni72QA394WmShHncWdBWrkPMOpTYQ6Q4CJ137yqpaFJTak7NEZxhA69EGwiT2jy096nKU6123RPRxTfXdTm8ZTaN4kqGjpGov3NFphDgCLjUFVOqs9Tm9qYLLZ0hoLjTqbgHHMWPPqwdCbRHaD0jIx1aStaWltn8vv6mvGDAiajYvBzzqZOXeb7lfOZ1hrbvT2lXlFQNSmWQ4ZGywO6xnpEuHbw/6V6Ts7mfHw6ylkXDbxOvwDSKbIa7qt9Zp3dqzM9uOyLOd/1XebFBYZ3/AFXebEBJTLjrI7yPwCA4DCfrk+2/+mVsl6j75nzlL9Vff4Hoixn0YQBAEAQHF+kwDm6GZuYZ3yJj1DcHiFaO5wrpNK6PN62Hc2TScXMABJGrZmzhqCIO7yXTR7mBqcL5HoUc29WOF+JsuT4+eHc74IIq8kdbg/pG+PnB/wDarLY34f1hXLjOpEwTAEgk3md4jw7N8o4ybzbkuEZ0gbmCDJgQB2DsUSeh0oxvO5u8D1J+sXO+8SR7oVDdDa4rY6mww6o0HhIzfd1U2ZEqsIuzaKOJ5Q0WCembxZp7frRwKsoNmepjaUN7+4yxu0ajX5GUXOtOaHRMkRYdm8hQopq5NWtOM8sY303MKOIxJqU8xYxpqUx6oLukDlglxmJtYo8tiE8RKXJfftOuxlSHO+cynhzRdHR4xfQ/BVS0LVJWk9fhfgRzFud4x8yOOXh3Ke74lL/+X+k+tcHFrRVuYj5obwXCZFtPclrcCU1JpKX+nvLbcNVAjnv/AAaq3XI7ZJ/3fAtMaYAJkxc6T2wqnRLTUxbRaDIaAeIAS5CilsjQ8paUPa7iI8R/37l2pvQxYuPnJmywzxkbDqnVbo34dFcTctizhzrd506wjysJQkzNdg1c22twgDazSYDgTwkIDz/Cfrk+2/8AplbJeo++Z85S/VX3+B6IsZ9GEAQBAEByvpC2TVxFBpo3dTcXRvIggx2qU7HGtTc46Hl1Gs4PtLHiAWxYwYII47/NdeBgUpKfJ8j6aLarnQQx5gho6rrXi0yTf++qXsMkajdtHy4GewGFtcgiCA4HvFlPA4xTU7M6rDUS89EwW3BOk7gew6eahmylFuV1wJajZPSY8HfAJB8QCD7lW7O8oxlutSxh8LOrcrd4PWd38B+bIXjDSyVkbGVB1OdrUKPO1MrC5+cB0ueQC+XCGMgkdEnW1vC2d2sZvJKeZz4vtLDXZKzmMotgPpDMxrSQHAFxcZJFzvAtccVF2dY0oR2SL+KZWJ+bc1ojeAbkuk6Tbox3qpc+U8H02l2Rv+4bUED94ZbmIcRrrq7jYSbfG4nGCq8Nq0ObBADYfnE5codDTc5h3z3qy6u2t7mGaxnWPK45eG9/Aiq4jHiwq4cOgHpB+hIA/Z6y5ttbi11K6rtKyWOt5rj8foX8a7F9AMqUBAIqZpEuyNPQsejM63hVWTW51qLE+bka21337N9CrVrY1pg1KIMFx60QNYPNxNjbVW/p9pS2M5x++4s4epi3UTD6RqOzGmYflygsAzSAZu7dvGqr5mbsOiWJ6p3azcN7d5SONxY1rUNP3t05v2e63cLmyt/T7TlbGc4/fcT42nVOHzVnMc9r5lkxlNhrvuEi1m0FSNTqr1LXvw5G5w7w2myx6o0BO7sC5G9EjawJi/3XR5kQgPMNt7BxD8RiXNoPIq1qT2GNWtNOTfTqO1g27QoJLfJfYtenjGPfRc1rWNa4xYEQI7b7xZAZYCoHbYJaQRnfcaWYQfgtslagfM0JKXSja7fA9GWM+lCAIAgCAIDl+VfI6ligXshlXc4aO7HKVKxyq0Y1FrueW43CVMPUdTrtIPE3BjQg7wul77HnuLpytPjxMuT5+eJmei651NxeVbgco+md3s6nlZO91/Dd+e1c2epRhlj7S1Kg7H0IDCpiWNs57QeEifLVTcGNGlmM06D3m8Oy5YnW749yi4L9PZWKdqKdPvJefIQFFwWqfJyfpK1R3Y2GD3X96i4LLNh4en0hTBcCIc6XO1G8oC1U2bSc4uLZLiC7W8ZYkbwMjffxKA+YnZlKoSXNuW5bEjo6xY9gQElfBU3yHNmQRftAB9wCAxZs9gNgRDco6TtCcx37zqd8DgEB8dzdFo1AkgdYmXmTPeboClVZhyA4hxDgYjPfNGawNpzAHsQE1TI+g8MmIcRM6yTv7QVMdznVV4NHDU+R2MIBFQQQCOm7etXlEeR4T6HrN36zxMv9F437QffcnlEf7SPwav8A5fEf6Lxv2g++5PKI/wBo/Bq/+XxPh5FY37Rv33J5RH+0fgtb/L4l/k1yRr0MQyq8sytzTBvdpH4qtSupxtY74LomWHrKo5J2v4HdrMe2EAQBAEAQBAa7bexaOKZkqtng7e3uKFZRUlZnm45K1MJielLqTgcrgCSbjokATK6KWhj8lcaia2Omo4Wu/q0HRxeQwfifcqXNxdpbAru61VjOxrcx83W9yXBcpcm6XruqVOxziB91sBQDY4bZ9Kn1KbG9wCAsoAgCAwrAkGNUBX5+t9iP+Qf4oBz9b7Ef8g/xQDn632I/5B/igHP1vsR/yD/FAOfrfYj/AJB/igMTUq/Yt++P8UAz1YjmW316Y/xQMtUGQ1o4ADyCAzQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEB//9k="
             class="img-fluid" alt="Responsive image">
        <div class="TextGroup">
            <h1>KF-94 마스크 팝니다 <span class="TextGroup_span">가격: 1,500원/개</span></h1>
            <h6>KF94 인증은 평균 0.4μm 크기의 입자를 94% 이상, KF99 인증은 평균 0.4μm 크기의 입자를 99% 이상 걸러낼 수 있는 마스크에 주어진다.</h6>
        </div>
        <div class="Exchange_Rate" id="Id_Exchange_Rate">
            달러-원 환율 : 000.00
        </div>
        <div class="InputGroup">
            <div class="col-auto">
                <label class="sr-only" for="inlineFormInputGroup">Username</label>
                <div class="input-group mb-2">
                    <div class="input-group-prepend">
                        <div class="input-group-text">주문자 이름</div>
                    </div>
                    <input type="text" class="form-control" id="inlineFormInputGroup" placeholder="">
                </div>
            </div>
            <div class="col-auto">
                <label class="sr-only" for="inlineFormInputGroup2">Count</label>
                <div class="input-group mb-2">
                    <div class="input-group-prepend">
                        <div class="input-group-text">수량</div>
                    </div>
                    <select class="custom-select" id="inlineFormInputGroup2">
                        <option selected> -- 수량을 선택하세요 --</option>
                        <option value="1">1</option>
                        <option value="2">2</option>
                        <option value="3">3</option>
                    </select>
                </div>
            </div>
            <div class="col-auto">
                <label class="sr-only" for="inlineFormInputGroup3">UserAddress</label>
                <div class="input-group mb-2">
                    <div class="input-group-prepend">
                        <div class="input-group-text">주소</div>
                    </div>
                    <input type="text" class="form-control" id="inlineFormInputGroup3" placeholder="">
                </div>
            </div>
            <div class="col-auto">
                <label class="sr-only" for="inlineFormInputGroup4">UserPhoneNumber</label>
                <div class="input-group mb-2">
                    <div class="input-group-prepend">
                        <div class="input-group-text">전화번호</div>
                    </div>
                    <input type="text" class="form-control" id="inlineFormInputGroup4" placeholder="">
                </div>
            </div>
        </div>

        <button onclick="btn_OnClick()" type="button" class="btn btn-primary">주문하기</button>

        <table class="table" id="order_table">
            <thead>
            <tr>
                <th scope="col">이름</th>
                <th scope="col">수량</th>
                <th scope="col">주소</th>
                <th scope="col">전화번호</th>
            </tr>
            </thead>
            <tbody>

            </tbody>
        </table>
    </div>
</form>
</body>

</html>


(5) 느낀점

Flask프레워크를 처음알았지만 여러번의 반복학습으로 익숙해질수있었고, 이전 여러 프로젝트를 시작하는 경험은 많았지만 여러 이유로 포기한 적이 많았습니다. 이에 반해 스파르타 웹개발 종합반 1~4주차동안 하나 이상의 프로젝트를 완료한 것이 무척 만족스러웠습니다.


반응형
728x90

(1) 강의내용

  • OpenAPI 붙여보기
  • Python
    • 파이썬 기초공부
    • 파이썬 패키지 설치
    • 파이썬 사용하기
    • 크롤링 기초
    • 크롤링 연습하기
  • MongoDB
    • DB 설치 확인
    • DB 종류
    • pymongo 사용법
    • 크롤링 값 저장하기
  • 3주차 숙제

(2) Python

  • 파이썬 패키지 설치(bs4, requests, pymongo)
    • window의 경우 Pycharm 내부에서 File -> Settings -> Project: Project_Name -> Python Interpreter -> +버튼 ->원하는 Package입력 ->Install Package -> OK

+버튼

  • requests
#requests 라이브러리 설치 필요
import requests 

r = requests.get('open_api 주소')
rjson = r.json()
  • bs4 (BeautifulSoup)
import requests
from bs4 import BeautifulSoup

# 타겟 URL을 읽어서 HTML를 받아오고,
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}

# url = 크롤링하고 싶은 사이트의 url
data = requests.get('url',headers=headers)

# soup이라는 변수에 "파싱 용이해진 html"이 담긴 상태가 됨
soup = BeautifulSoup(data.text, 'html.parser')


# 선택자를 사용하는 방법 (copy selector)
soup.select('태그명')
soup.select('.클래스명')
soup.select('#아이디명')

# 개발자도구(F12)를 열어 원하는 부분을 copy -> copy_selector를 통해 확인 가능
soup.select('상위태그명 > 하위태그명 > 하위태그명')
soup.select('상위태그명.클래스명 > 하위태그명.클래스명')

# 태그와 속성값으로 찾는 방법
soup.select('태그명[속성="값"]')

# 한 개만 가져오고 싶은 경우
soup.select_one('위와 동일')

(3) MongoDB

  • DB 설치 및 확인 - 크롬창에 localhost:27017을 입력 후 아래화면이 나오면 정상

MongoDB정상작동

 

  • DB 종류
    • SQL - 데이터가 정형화 되어있어 분석에 용이하나, 중간에 열을 추가하는 행동이 어려울 수 있다.
    • No-SQL - 데이터가 딕셔너리 형태로 저장되어 일관성이 부족하지만, 중간에 열을 추가하는것에 문제가 없다.
  • pymongo 사용법
from pymongo import MongoClient
client = MongoClient('localhost', 27017)

#dbname = 원하는 db이름
db = client.dbname

#collection_name = 원하는 collection 이름
#collection_name의 모든 값 검색
list(db.collection_name.find({},'_id':False))

#collection_name의 name열에서 Kim 검색
db.collection_name.find_one({'name':'Kim'},'_id':False)

#collection_name의 name열에있는 Kim을 나이 20세로 수정
db.collection_name.update_one({'name':'Kim'},{'$set':{'age':20}})

#collection_name의 name열에있는 Kim을 삭제
db.collection_name.delete_one({'name':'Kim'})

#collection_name의 데이터를 모두 삭제
db.collection_name.remove()

(4) 3주차 숙제

import requests
from bs4 import BeautifulSoup

from pymongo import MongoClient
client = MongoClient('localhost', 27017)
db = client.dbsparta

headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
data = requests.get('https://www.genie.co.kr/chart/top200?ditc=D&ymd=20200403&hh=23&rtm=N&pg=1',headers=headers)

soup = BeautifulSoup(data.text, 'html.parser')

trs = soup.select('#body-content > div.newest-list > div > table > tbody > tr')

for tr in trs:
    rank = tr.select_one('td.number')
    artist = tr.select_one('td.info > a.artist.ellipsis')
    title = tr.select_one('td.info > a.title.ellipsis')

    print(rank.text.split(' ')[0].strip(), title.text.strip(), artist.text.strip() )


(5) 느낀점

크롤링과 db에 대해 필요한 부분만 잘 정리되어있는 수업진행으로 기초 부분을 빠르고 쉽게 이해할 수 있었습니다. 

모든 수업마다 이전에 했던 내용을 복습하며, 금주에 배울 내용에 대해서도 여러 번 반복하여 새로운 Quiz, 숙제를 통하여 이해뿐만 아니라 조금이나마 익숙해 질 수 있었습니다.


 

반응형

+ Recent posts