Skip to content
This repository has been archived by the owner on Apr 3, 2023. It is now read-only.

Process of building

Ha Jeong-Hyun edited this page Aug 23, 2022 · 2 revisions

Cloudmodular가 하나의 Application으로 빌드되는 과정

지금 올라와 있는 Cloudmodular의 웹 서비스 Repository는 BackendFrontend로 나뉩니다. 하지만 프로젝트 특성상, 백엔드와 프론트엔드를 하나의 어플리케이션으로 합쳐야 하므로, Docker Image로 Build할 때는 Backend, Frontend따로 Build하는 것이 아닌 합쳐서 하나의 완전한 어플리케이션으로 build합니다. (실제로 Dockerfile은 Frontend에는 없고 Backend에만 있습니다.) 그렇기 때문에 따로 Frontend를 정적 파일로 Build해서 NginX나 Apache에 붙이지 않아도 Docker Container만 만들어서 실행하면 정적 웹서비스를 사용할 수 있습니다. 이 포스트는 Frontend와 Backend가 어떻게 하나의 어플리케이션으로 합칠 수 있는 지 그 과정을 설명합니다. 실제 빌드 과정은 DockerFile을 통해 확인하실 수 있습니다.

ReactJS 빌드업

ReactJS 뿐만 아니라 다른 Frontend Framework를 경험한 사람이라면 Frontend Framework 위에서 구현된 코드들은 HTML/CSS/JS로 Build될 수 있다는 사실을 알고 계실 것입니다. 이 프로젝트에서도 마찬가지로 아래와 같은 명령어로 정적파일을 빌드합니다.

npm run build

build를 수행한 후 build 디렉토리가 생성되고 해당 디렉토리로 이동하면 결과물을 볼 수 있습니다.

build 디렉토리 분석하기

build 디렉토리가 생성되고, build 디렉토리에 들어가면 아래와 같이 파일/디렉토리가 나열됩니다. 대부분 ReactJS에서 긁어오는 수준이지만 일부는 새로 생성되었습니다.

PS E:\projects\cloudmodular-web\build> ls

    Directory: E:\projects\cloudmodular-web\build

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----        2022-08-03   오전 8:53                static
-a----        2022-08-03   오전 8:53            931 asset-manifest.json
-a----        2022-07-20   오후 2:46           3870 favicon.ico
-a----        2022-08-03   오전 8:53            375 index.html
-a----        2022-07-20   오후 2:46            492 manifest.json
-a----        2022-07-20   오후 2:46             67 robots.txt
  • static: html을 꾸미기 위한 js/css/media가 들어있습니다. media는 각종 이미지같은 asset파일들을 여기로 한 곳에 저장합니다.
  • index.html: ReactJS로부터 긁어온 html파일입니다. 하지만 기존 html/js/css와 달리 모든 URL이 index.html 을 통해서 접근합니다. 후술할 내용이지만, FastAPI에서의 정적 웹 API를 작성할 때 index.html을 적극적으로 활용합니다.

FastAPI에서의 정적 파일 세팅

파일 옮기기

빌드는 했지만, 아직 Frontend Repo에서만 생성되었기 때문에, Backend Repo로 옮겨야 합니다. 리눅스의 mv명령어를 사용해 옮깁니다.

mv /cloudmodular-web/build/* /cloudmodular/web/

Backend로 옮기는데 성공했다면 남은 일은 정적 웹으로의 Route 설정 입니다.

# main.py

# Prod인 경우 staticweb까지 추가
templates = Jinja2Templates(directory='web')
app.mount('/static', StaticFiles(directory='web/static'), name='static')
# static webURL 추가
@app.get('/')
@app.get('/login/{path:path}')
@app.get('/storage/{path:path}')
@app.get('/setting/{path:path}')
@app.get('/error/{path:path}')
@app.get('/accounts/{path:path}')
async def index(request: Request):
    return templates.TemplateResponse('index.html', {"request": request})

Jinja2는 FastAPI의 Template Engine 입니다. 정적 웹을 띄울 때 사용합니다. templates = Jinja2Templates(directory='web')은 html파일의 경로를 설정해 줍니다. build의 내용물을 web으로 옮겼으니, directory를 web으로 설정했습니다.

app.mount('/static', StaticFiles(directory='web/static'), name='static')를 통해 FastAPI내 /static 루트를 실제 루트인 web/static으로 마운트 합니다. 보통 html에서 js/css를 참고할 때 /static에서 파일을 찾기 때문에 /static을 마운트 했습니다. 이렇게 하면 js/css/media 파일을 404에러가 뜨지 않고 찾을 수 있게 됩니다.

이제 Router설정만 남았습니다. Frontend에 사용되는 모든 URL Pattern을 정적파일에 접속하는 함수로 등록합니다.

과거작 Microcloudchip-NATURAL(2021, ReactJS/Django) 에서의 합치는 방법

2021년도 작품인 Microcloudchip-NATURAL 에서도 Frontend(ReactJS)와 Backend(DJango(DRF))를 하나로 합쳐서 Docker Container를 생성합니다. ReactJS의 코드들을 정적 파일로 빌드한 다음, Backend에 부착하는 방식은 동일하나, DJango만의 명령어로 보다 쉽게 정적파일을 DJango에다가 부착합니다.

python manage.py collectstatic

collectstaticsettings.py에 정의된 루트들을 통해 외부의 정적 파일을 DJango 안으로 이동시키는 데 사용됩니다. 정적파일을 이동시켰으면 URL을 아래와 같이 등록합니다.

urlpatterns = [
    url(r'^$', TemplateView.as_view(template_name='index.html'), name='index'),
    url(r'^(storage)|(accounts)|(settings)|(share)/', TemplateView.as_view(template_name='index.html'), name='index'),
    # ... 생략 ...
]

FastAPI때와는 상대적으로 코드가 간결해 보이는데, 그 이유는 DJango의 URL 정규식에서 패턴 or연산이 가능하기 때문입니다. (storage)|(accounts)| ...는 storage나 accounts등 이들 중 하나만 해당되도 포함이 된다는 의미 입니다. FastAPI는 이런것을 지원하지 않기 때문에 Decorator Function을 일일이 적었어야 했습니다.