leetcode는 알고리즘 문제를 제공하는 사이트입니다. 세계적으로 유명한 알고리즘 사이트 중 하나인데 난이도 별로도 정렬을 할 수 있습니다. 문제를 한 문제 한 문제 풀다 보면 우리는 세계 기업들이 특정 수준을 요구하는 프로그래밍 사고도 충족시킬 수 있습니다. 또한 leetcode는 python뿐만 아니라 자바스크립트, 자바, c, c++ 등 무수한 많은 언어로 알고리즘 문제를 풀 수 있도록 지원합니다.
이렇게나 큰 이점을 갖고 있는 알고리즘 문제를 순번 별로 문제들을 풀어보도록 하겠습니다.
그렇게 풀어 본 문제가 1.Two Sum 문제입니다.
문제를 보고 로컬에서 풀어 봅니다.
한 문제를 풀 때 너무 오랜 시간 동안 고민하지 마세요. 1시간, 2시간 스스로가 정한 시간 동안 고민을 하고 문제를 풀어보세요. 로컬에서 돌려보고 됐다 싶으면 leetcode에서 돌리면 내가 작성한 알고리즘에 대해서 판단을 해줍니다.
올바른 답은 없습니다.
단지 더 나은 방법이 있을 뿐입니다. 더 나은 방법이 있으면 배우고 익혀서 사용하시면 됩니다.
하지만 그전에 분명히 자신의 생각이 있어야 되고 직접 문제를 풀어 보셔야 더 많은 걸 배우실 수 있습니다.
그래야 내가 생각한 방법과 더 나은 방법을 비교를 해봐야 성장할 수 있기 때문입니다.
(더 나은 방법을 배우셨다면 스스로 복기를 다시 해보세요)
from typing import List
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
idx = 0
for i in nums:
find_data = target - i
idx += 1
if find_data in nums[idx:]:
return [idx-1, nums[idx:].index(find_data)+idx]
if __name__ == '__main__':
print(Solution().twoSum([2, 7, 11, 15], 9))
위의 문제는 로컬에서 풀면서 작성한 코드입니다.
1문제를 풀면서도 for문, if 문을 사용하고 리스트의 index를 이런 방식으로 찾을 수 있구나 배웁니다.
다시 URL에 들어가면 에러가 발생했지만 서버가 구동이 된 모습을 보실 수 있습니다. (조금 전에는 서버가 구동이 안 됐습니다.)
4. ec2에 Package 설치
이제부터는 eb logs 명령어를 통해서 직접 하나씩 하나씩 확인을 해보겠습니다. (위의 화면은 로컬에서는 노란 화면으로 debug 모드로 확인이 가능하나, 상용에서는 debug 모드가 False로 되어 있어 로그가 보이지 않습니다. 상용에서도... 보고 싶으시다면 세팅에서 변경 가능합니다.)
-> DEBUG = env.bool("DJANGO_DEBUG", False)
(아래 내용을 먼저 말씀드리자면, 사실 아직 Django가 설치가 되어 있지 않아 아무 동작도 안됩니다.)
로그 내용을 확인하겠습니다.
에러 내용은 다음과 같습니다. ModuleNotFoundError: No module named 'django'
장고 모듈을 찾을 수 없다고 합니다. aws에는 장고 관련 모듈을 설치하지 않아 발생하는 에러입니다.
장고 모듈을 설치하겠습니다.
파이썬에서 필요로 하는 패키지를 설치하기 위해서는 루트 위치에 requirements.txt 파일을 만들어주세요.
from django.core.management.base import BaseCommand
from django.contrib.auth import get_user_model
class Command(BaseCommand):
def handle(self, *args, **options):
User = get_user_model()
User.objects.create_superuser('iamadmin', 'iamadmin@gmail.com', 'adminpass')
유저 모델을 갖고 와서 슈퍼 유저를 생성하는 코드입니다.
커밋 후 디플로이를 해주세요 :)
어드민까지 정상적으로 접속되는 모습이 보입니다. (접속 후에 패스워드 변경 필수입니다.)
작업 이후에는 위에서 추가한 createuser 명령어와 ebuser.py 파일 내의 계정 정보를 꼭 삭제해주세요.
(작업할 때는 커밋만 하고 이후에는 정보를 지운 후에 rebase나 amend작업으로 다시 커밋 푸시 진행)
9. 리액트를 사용하신다면
리액트를 다루신다면 PUBLIC_URL도 꼭 추가를 해주셔야 됩니다.
JS파일이 로컬에 있는 것처럼 보여 발생하는 문제인데요. S3로 경로를 설정해주셔야 됩니다.
장고 어드민 개발자 환경에서 s3 주소를 갖고 와 리액트 환경의 .env에 PUBLIC_URL을 추가해주시면 됩니다.
PUBLIC_URL='https://hello.s3.amazonaws.com'
yarn build 실행!!!
commit 후에 다시 eb deploy!!!
(로컬에서 작업하실 때는 다시 PUBLIC_URL을 풀어주셔야 됩니다.)
정상적으로 배포를 완료하였습니다 :)
환경이 달라 조금은 다른 점이 있겠지만 큰 흐름은 이렇습니다.
배포가 생각하는 것처럼 쉽지가 않습니다. 위의 내용을 참고하면서 문제점들에 대한 로그를 보면서 해결하신다면 배포를 하실 수 있겠습니다.
장고 프레임워크에서는 뷰를 만들지 않고 모든 뷰는 리액트에서 담당하게 되는 것이죠. 리액트(뷰 단) -> 장고(서버 단)로 API 호출을 합니다.
로컬 주소는 localhost 또는 도커를 사용한다면 서버는 0.0.0.0이 될 것입니다. 포트는 리액트는 3000번, 장고는 8000번을 사용하게 됩니다. 개발할 때는 프런트-서버 모두 구동한 상태로 개발을 하지만 실서버에서 사용할 8000번 포트를 사용하게 됩니다.
우리가 해야 될 것은 1) 개발에 필요한 리액트에서 장고로 API 호출을 할 수 있게끔 만들고, 2) 실제 상용에서는 8000번(장고 서버)만 구동해도 프런트엔드가 나오게끔 만들어야 됩니다.
그럼 작업을 시작하겠습니다.
1.
python 패키지 중 django-cors-headers 패키지를 설치해주세요.
django는 자신 이외 다른 도메인이 리소스에 접근하는 것을 허락하지 않습니다. 이를 컨트롤하기 위해서 패키지를 설치하는 겁니다.
pip install django-cors-headers
2.
문서의 따라 base.py로 들어가셔서 앱과 미들웨어에 django-cors-headers를 추가해주세요.
## base.py
# app에 추가
INSTALLED_APPS = [
...
' corsheaders ' ,
...
]
# 미들웨어에 추가
MIDDLEWARE = [
...
' corsheaders.middleware.CorsMiddleware ' ,
...
]
# 맨 아래 위치에 추가
CORS_ORIGIN_ALLOW_ALL = True
위의 내용들을 설정을 위해서 추가를 해주시면 됩니다 :)
3.
다음으로 우리는 8000번(장고)만 구동해도 프런트가 보여야 됩니다. 프런트단에서 빌드를 하게 되면 빌드 파일이 만들어집니다. 빌드 파일 안에는 statice파일이 만들어지는데 이를 장고가 가리키도록 해야 됩니다. 장고가 가리키는 방법은 간단합니다.
base.py 안에 STATICFILE_DIRS = [ ... ] 라인이 있습니다. 여기에 빌드된 프런트 파일을 담아주시면 됩니다.
예시를 들자면 다음과 같습니다.
STATICFILES_DIRS = [
str(APPS_DIR.path("static")), # 기존 존재
str(ROOT_DIR.path('front', 'build', 'static')), # 추가
]
기존에는 장고에서 생성된 static파일이 있었습니다. 하지만 우리의 프런트를 사용하기 위해서 빌드된 static 위치를 위와 같이 추가로 작성을 해주시면 됩니다.
4.
root URL에 url을 추가를 해주세요.
path("", views.ReactAppView.as_view()),
우리는 프런트에서 만든 경로들을 프런트로 보내주기 위해서 가장 아래쪽 위치 작성을 해주세요.
서버에서 만든 api들은 방금 작성한 코드 위에 위치할 것이고 맨 아래 작성한다면 장고에 없는(매칭이 안 되는) url들은 이곳을 경유하여 view를 호출할 것입니다.
5.
위에서 호출할 수 있게끔 뷰 파일을 만들어주세요.
from django.views.generic import View
from django.http import HttpResponse
from django.conf import settings
import os
class ReactAppView(View):
def get(self, request):
try:
with open(os.path.join(str(settings.ROOT_DIR),
'front',
'build',
'index.html')) as file:
return HttpResponse(file.read())
except:
return HttpResponse(status=501,)
작성을 하시면 장고 서버만 구동해도 프런트 쪽으로 호출이 됩니다. (프런트를 빌드 후에 front/build/ 위치에 파일이 있는지 확인을 하고 실행을 시켜주세요.)
6.
마지막으로 리액트 package.json 파일에 proxy를 추가해주세요.
"proxy": "http://0.0.0.0:8000",
프런트에서도 3000번에 url이 없는 경우에 8000번으로 연결이 됩니다. (저는 도커로 구동하여 0.0.0.0입니다. 디폴트 구동 시 localhost로 되어 있습니다.)
이를 설정을 해주시면 로컬에서 프런트-서버 api 호출이 가능하겠습니다.
이상 없이 서버 구동이 되었으며 8000번 호출 시 프런트엔드 뷰가 보이는 모습을 확인하였습니다.