개발자로 후회없는 삶 살기

SW bootcamp PART.개인 프로젝트 1주차(Flask 스터디) 본문

[대외활동]/[네트워크형 캠퍼스 아카데미]

SW bootcamp PART.개인 프로젝트 1주차(Flask 스터디)

몽이장쥰 2023. 1. 16. 23:58

서론

갑자기 수요조사를 하시더니 백엔드반을 나누겠다고 하셔서 AI 경험이 있는 저는 백엔드반 수업을 듣기로 했습니다. 인공지능 반 수업도 녹화 영상이 올라오기에 도커, 프로메테우스, 쿠버네티스 수업은 개인적으로 듣고 포스팅 하겠습니다. 1~3일차는 인공지능+백엔드 합반 수업이고 4일차부터 백엔드 분반 수업입니다.

 

본론

Flask는 MLOps에서 땔래야 땔 수 없는 필수 코스인 것 같습니다. 개인 프로젝트는 Flask를 활용한 AI 서비스를 만드는 것입니다. 가이드라인(참고 1)대로 프로젝트를 진행합니다. 내용 설명 부분을 보면 플라스크 docs가 있으니 한 번 훑어 보고 진행하겠습니다.

 

 

1일차

꿀벌 이미지 분류 프로젝트로 체감 난이도를 측정하고 체감 난이도와 제출 코드를 토대로 조를 짜, 조별 활동을 할 예정입니다. 원래 제가 사용하던 이미지를 불러오는 코드가 제대로 동작하지 않는 이슈가 있었습니다. 

 

다른 조원이 한 풀이 방법을 보고 이미지를 가지고 오는 다른 방법을 알 수 있었고 잘 하시는 분들도 많아서 더욱 열심히 해야겠다는 생각이 드는 경험이었습니다.

 

 

 

2일차

오전에는 꿀벌 프로젝트 발표를 하였고 오후부터 약품 이미지 분류 프로젝트를 했습니다. 이번에는 깃을 활용하는 것과 fine tuning 하는 것이 추가되었습니다. 다음에는 도커를 추가하는 등 점점 하나씩 기능을 추가하는 시스템으로 진행할 것이라고 하셨습니다. 또한 깃은 무조건 1일 1커밋을 조건으로 하였습니다.

 

3일차

백엔드 보조 강사분이 오셔서 인공지능, 서비스 플랫폼을 만드는 게 목표로 인공지능 서비스와 친화적인 백엔드 개별 프로젝트를 2주 정도 진행하고 후에는 다시 인공지능 팀과 만나 협업을 목표합니다.

 

4일차

깃허브에 조직을 만들어 동료들과 함께 코드를 공유할 repository(레포)를 만들고 pull request(pr)를 하면서 진행할 것입니다. 레포를 fork하면 ㅈ[ 원격저장소에 레포가 생깁니다. 제 원격 저장소에서 수정을 하고 pr을 하여 조직 레포에 적용할 것입니다.

 

+ pr 메세지는 실제 현업에서도 굉장히 중요한 것이라고 하십니다. pr을 하면 제 원격에서의 역할은 끝이고 조직 레포의 관리자가 받은 pr을 merge하면 pr이 닫히며 조직 레포에 적용이 됩니다.

 

> 오픈소스 프로젝트에서 pr을 하는 것은 내가 이 오픈소스를 고쳤다! pr을 받아달라!라는 뜻이고 pr이 되면 contributor가 됩니다.(제가 관리자면 contributor가 되지 않던 이유가 있었습니다.)

 

-> 플라스크 시작

이제 교육에서 본격적으로 백엔드를 배우기 위해 플라스크를 시작합니다. 자바와 스프링의 관계와 파이썬과 플라스크, 장고와 비슷한 관계라고 보면 되는 파이썬의 웹 프레임워크 라이브러리라고 합니다. 플라스크로 간단한 어플을 하나 만들어보고 인공진응에 친화적인 웹을 만들어 볼 것입니다. 

 

 

- 플라스크 docs

서론에서 언급한 플라스크 docs를 읽은 후에 프로젝트에 도입하겠습니다.

 

=> 기본 어플리케이션

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run(debug = True)

실행 1

실행 1

코드를 한 줄 한 줄 설명해 보자면 Flask 클래스를 import하여 이 클래스의 객체를 우리의 어플리케이션으로 사용할 것입니다. 클래스를 생성할 때 인자로 어플리케이션 이름을 주어 Flask 객체를 생성합니다. __name__ 변수에는 모듈 명이 담깁니다.

 

+ app.route()는 Flask에게 어떤 URL이 우리가 작성한 함수를 실행시키는지 알려주고 바로 밑에 실행할 어플리케이션을 함수로 작성합니다.

+ app.run()은 우리가 개발한 어플리케이션을 로컬 서버로 실행하는 명령어입니다.

 

> 실행 1의 서버는 네트워크 상에 있는 다른 컴퓨터에게 접근이 안되고 로컬 서버에서만 접근가능합니다. 그 이유는 실행한 환경이 디버그 모드이기 때문으로 app.run(host='0.0.0.0')으로 내 OS에게 모든 public IP를 접근 가능하도록 설정할 수 있습니다.

 

※ __name__에 모듈명이 담긴다는 것이 무슨 얘기냐면 hello.py라면 hello가 담겨서 route에서 hello/으로 경로를 연결해 주는 것

 

실행 2

@app.route('/')
def hello_world():
    return 'Hello World!!!!'

 

실행 2

-> 디버그 모드

run 메서드는 로컬 개발 서버를 실행시키기에 좋지만 코드 변경 후에 수동으로 재시작 해야합니다. 디버그 모드를 사용하면 서버는 코드 변경을 감지하고 자동으로 리로드하며 문제가 발생하면 문제를 찾을 수 있도록 디버거를 제공합니다. 

> app.run(debug=True) 라고 수정하면 그냥 run일 경우 어플리케이션을 수정하고 새로고침해도 변경 사항이 적용되지 않지만 디버그 모드를 하면 새로고침이 적용됩니다.

 

 

- 라우팅

route() 데코레이터는 함수와 URL을 연결해줍니다. 개발자는 URL을 동적으로 구성할 수 있고 함수에 여러 룰을 덧붙일 수 있습니다.

@app.route('/user')
def show_user_profile():
    return 'User'

 

-> 변수 규칙

@app.route('/user/<str:username>')
def show_user_profile(username):
    return 'User %s'%username

URL의 변수 부분을 추가하기 위해 규칙을 표시할 수 있습니다. 정확히 말하자면 URL 명명 규칙이 아니고 URL에 변수를 같이 보내는 것입니다. <> 꺽쇠 사이에 변수 이름을 적으면 되며 함수 인자로 받은 변수를 넣어줘야합니다. int, float, path 같이 변환기(converter를 선택적으로 줄수도 있습니다.)

 

 

 

※ 여기서 문제가 발생하였습니다. 한 번 str 타입에 정수형을 넣었더니(type error) 서버가 꺼져서 플라스크가 다음 URL 호출을 받지 않았던 것입니다. type error가 발생한 후 다시 제대로 타입을 맞춰서 시도했지만 찾을 수 없는 페이지라고 표시되어 시간을 낭비하였습니다. 다시 켜주어야 합니다.

 

 

 

- HTTP 메서드

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        do_the_login()
    else:
        show_the_login_form()

HTTP는 기본적으로 URL 접근에 대해 GET 방식으로 제공되지만, route()에 methods 인자를 제공하면 다른 방식으로 변경할 수 있습니다.

 

 

- 정적 파일

동적인 웹 어플리케이션은 정적 파일을 필요로합니다. 그것들은 보통 js나 css 파일을 의미합니다. 이상적으로 웹 서버는 정적 파일들을 서비스하지만 개발시에는 플라스크가 그 역할을 대신해줍니다. static이라는 폴더를 개발자가 생성한 프로젝트 아래에 만들거나 모듈 옆에 위치시키면 개발된 어플리케이션에서 /static 위치에서 정적 파일을 제공합니다. ex) /static/style.css로 저장하면 됩니다.

 

 

 

-> 템플릿 보여주기

파이썬 소스코드에서 HTML을 생성해보자 render_template() 메서드를 사용합니다. 개발자는 1) 템플릿(html)의 이름, 2) 템플릿에 보내줄 변수를 키워드 인자로 넘겨주면 됩니다. 이렇게 하고 render_template가 있는 메서드를 URL로 호출하면 플라스크가 templates 폴더에서 템플릿을 찾습니다. 따라서 dir 구조를 신경을 써야합니다.

 

@app.route('/hello/<name>')
def hello(name=None):
    # 1) 템플릿의 이름, 2) 템플릿에 보여줄 변수
    return render_template('hello.html', name=name)

 

ex) 예제를 보면 템플릿 이름과 템플릿에 보여줄 변수를 넣어주는데 코드 분석을 해보자면 <name>으로 변수 규칙으로 URL에 변수를 함께 보내줍니다. > render_template()의 인자 name = 에 변수를 매칭합니다. > 그러면 인자로 name 변수가 전달됩니다.

 

※ 플라스크는 static, templates 등 정해진 규칙이 있습니다. 이것이 프레임워크이기 때문입니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello from Flask</title>
</head>
<body>
    <h1>Hello {{ name }}!</h1>
</body>
</html>

URL에 127.0.0.1:5000/hello/SangBeom이라고 친 결과 HTML에 name 변수가 적용된 결과가 출력됩니다.

 

- 요청 데이터 접근하기

웹 어플에 있어서 클라이언트에서 서버로 보내는 데이터를 처리하는 것은 중요한 일입니다. 플라스크에서 이 정보는 request 객체에 의해 제공됩니다. 그리고 어떻게 이 객체가 글로벌하고 쓰레드 안전하게 처리하는지는 플라스크의 컨텍스트 로컬에 있습니다.

 

+ 요청 객체(request)

메서드에 접근하려면 request.method, 폼 데이터에 접근하려면 .form으로 접근하고 URL로 넘겨진 질의 문자열에 접근하려면 args.을 사용합니다.

 

★ 이제 서비스를 구현해 볼 차례입니다. 하지만 저는 부족함을 느꼈기에 제 블로그에 백엔드 카테고리에 Flask를 만들어서 공부와 서비스를 병행하도록 하겠습니다.

 

- 느낀점

포켓몬 이후로 vscode로 처음 코드도 짜고 실행도 해보고 깃도 연결해본 건데 깔끔하게 잘 했다는 강사님의 말씀에 뿌듯한 하루였다.

 

 

참고

가이드라인

Comments