Developer's Development
[플레이데이터 SK네트웍스 Family AI 캠프 17기] 24주차 회고 본문
Hello World 👋🏻
이번 주는 에디터 속의 코드를 넘어, 실제 사용자가 접속할 수 있는 '진짜 서버'를 구축하는 데 집중한 시간이었습니다.
📁 최종 프로젝트 기록
- Django 시스템 구현 & AWS 배포
드디어 AWS EC2 인스턴스에 Django 서버를 무사히 안착시켰습니다.
백엔드의 핵심 로직들은 구현이 완료되었고, 이제 AI 모델(Runpod API) 연동만을 남겨두고 있어요.
단순히 runserver를 띄우는 게 아니라, Nginx와 Docker, Django를 유기적으로 연결하여 실제 서비스가 가능한 견고한 아키텍처를 잡는 데 집중했습니다.
아직 Runpod 연동이라는 큰 산이 남았지만, 가장 단단한 뼈대를 세웠다는 점에서 큰 의미가 있는 주였습니다.
- Troubleshooting 1. static 파일 못 가져옴
배포 직후 사이트에 접속했는데 CSS가 다 깨지고 이미지가 나오지 않는, 일명 '액박' 사태가 발생했어요.
Django 컨테이너가 모아둔 static 파일들을 웹 서버인 Nginx 컨테이너는 볼 수 없는 게 원인이었습니다.
해결을 위해 docker-compose에서 volumes를 선언해 두 컨테이너가 파일을 공유할 수 있는 '공용 폴더'를 만들어주었고, Nginx 설정(default.conf)에서 alias를 통해 경로를 명확히 이어주었습니다.
# settings.py
# 로컬 정적 파일 설정
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
# docker-compose.yml
services:
# 1. Django 컨테이너 (파일을 제공하는 쪽)
web:
# ... 기존 설정 ...
volumes:
- ./:/code
- static_volume:/code/staticfiles # <--- 이 줄 추가 (이름:경로)
- media_volume:/code/media # <--- 이 줄 추가
# 2. Nginx 컨테이너 (파일을 받아 보여주는 쪽)
nginx:
# ... 기존 설정 ...
volumes:
- static_volume:/static # <--- Django의 staticfiles를 Nginx의 /static에 연결
- media_volume:/media # <--- Django의 media를 Nginx의 /media에 연결
depends_on:
- web
# 3. 맨 아래에 볼륨 선언
volumes:
static_volume:
media_volume:
# nginx/default.conf
server {
# 👇 여기를 수정
location /static/ {
alias /static/; # docker-compose에서 연결한 그 경로
}
}
- Troubleshooting 2. Docker 빌드를 계속해서 서버 뻗음 이슈
t2.micro 같은 프리티어 서버(램 1GB)에서 Docker 빌드를 하면 메모리가 부족해서 서버가 멈추는 현상이 매우 흔하다고 합니다.
1. SSH로는 아무것도 할 수 없는 상태이니, AWS 콘솔에서 깨워주기
- EC2 > 인스턴스 > 인스턴스 상태: 인스턴스 재부팅 (중지 아님. 중지하면 IP 바뀜.)
2. 재발 방지
- 프리티어 램에 2GB의 가상 메모리(swap)를 더해줘서, 도커 빌드할 때 서버가 멈추지 않게 해주기 (Gemini가 알려줌)
# 한 줄씩 실행
# 2GB짜리 스왑 파일 만들기
sudo fallocate -l 2G /swapfile
# 권한 설정 (보안상 필수)
sudo chmod 600 /swapfile
# 스왑 영역으로 지정하고 활성화
sudo mkswap /swapfile && sudo swapon /swapfile
# 재부팅 해도 유지되게 설정 (fstab 등록
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# 확인 (Swap: 부분에 2.0Gi 숫자 떠 있으면 성공)
free -h
- Troubleshooting 3. 카카오페이 API 연동
배포 후 카카오디벨로퍼스에 등록한 앱에 EC2 IP를 등록하려고 했는데, 아무리 찾아봐도 로컬 주소를 등록했던 그 화면을 찾을 수가 없는 거예요.....?

구글링도 해보고 과거 기억을 되살려봐도,
앱 > 일반 > 플랫폼 키 쪽에 REST API 키며 JavaScirpt 키 다 등록해 봐도, 변화는 없었고..
정답은 앱 > 제품 링크 관리 > 웹 도메인에 있었습니다. (언젠가 또 카카오페이 api를 연동할지도 몰라 남겨두는 기록)

- Troubleshooting 4. 이미지 404 이슈
액박 때 저희 화해한 거 아니었냐며,,, 제 이미지 다 어디 갔냐며,,,,,,,,,,,,,,
이게 또 사이트 전체에서 그런 건 아니고, 특정 이미지만 404 이슈로 못 가져오는 문제가 있더라고요??


그래서 아래 코드로 Nginx 컨테이너 안에 저장된 실제 파일 이름을 확인해 보니 소문자였고, 코드에서 부르는 이름은 대문자라 가져오지 못하고 있었습니다.
# Nginx 컨테이너 안의 teams 폴더 내용 조회
docker-compose exec nginx ls -F /static/images/teams/
Windows/Mac은 대소문자를 구별하지 않지만(a.jpg == A.jpg) 배포한 Linux(EC2) 서버는 대소문자를 칼같이 구분한다는 건 웹 개발할 당시에도 여러 번 마주했던 이슈인데, 너무 정신이 없어 당연한 거 마저도 놓치고 있다는 게 당황스럽기도 했어요.
- 남겨놓는 코드 기록
1. 도커 끄고 프로젝트 폴더 삭제 및 재설치, 실행까지
cd ~/SKN17-FINAL-DJANGO
docker-compose down -v
cd ~
# 폴더 강제 삭제
sudo rm -rf SKN17-FINAL-DJANGO
# 깃허브에서 다시 받기 (본인 레포지토리 주소 입력!)
git clone https://github.com/mylee99125P/SKN17-FINAL-DJANGO.git
# 폴더로 이동
cd SKN17-FINAL-DJANGO
# 로컬의 .env 파일 서버로 보내기 (로컬에 pem키 있는 폴더에서 새로운 git bash로 실행)
scp -i bais-key.pem .env ubuntu@54.116.12.113:/home/ubuntu/SKN17-FINAL-DJANGO
# 빌드 및 실행
docker-compose up -d --build
# 정적 파일 모으기
docker-compose exec web python manage.py collectstatic --noinput
# 권한 부여
docker-compose exec web chmod -R 755 /code/staticfiles
docker-compose exec web chmod -R 755 /code/media
# Nginx 재시작
docker-compose restart nginx
# django-web, nginx_proxy 모두 up 상태인지 확인
docker ps
2. 사이트가 https가 아니라 http라서, 보안 규칙 안 보낸다고 설정하기
- 신뢰할 수 있는 출처(Origin) 등록하는 과정
- (index):1 The Cross-Origin-Opener-Policy header has been ignored,~~ 오류 해결하는 과정
nano ~/SKN17-FINAL-DJANGO/SKN17_FINAL_3TEAM/settings.py
# 아래 내용들 추가해주기
# HTTPS가 아닌 HTTP 환경에서도 쿠키가 동작하게 설정 (필수!)
CSRF_COOKIE_SECURE = False
SESSION_COOKIE_SECURE = False
CSRF_TRUSTED_ORIGINS = [
'http://localhost:8080',
'http://127.0.0.1:8080',
'http://54.116.12.113:8080',
]
CORS_ALLOW_ALL_ORIGINS = True
CORS_ALLOW_CREDENTIALS = True
# HTTP 환경에서 COOP 에러 방지
SECURE_CROSS_ORIGIN_OPENER_POLICY = None
# settings.py Ctrl+O -> Enter, Ctrl+X로 나와서 할 일
docker-compose restart web
3. 서버에서 파일 수정하려고 할 때, nginx/defalut.conf처럼 관리자 권한이 필요하여 권한 거부 뜰 경우
sudo nano nginx/default.conf
# default.conf는 고친 파일을 컨테이너 안으로 강제 복사
docker cp nginx/default.conf $(docker-compose ps -q nginx):/etc/nginx/conf.d/default.conf
# Nginx 재시작
docker-compose restart nginx
4. KeyError: 'ContainerConfig' 에러 해결
# 모든 컨테이너 강제 삭제
docker rm -f $(docker ps -a -q)
# 네트워크/캐시 정리
docker system prune -f
# 깨끗한 상태엔서 다시 실행
docker-compose up -d --build
5. 413 Request Entity Too Large 에러 해결
파일이 너무 커서 서버(Nginx)가 거부했다 → Nginx 설정에서 허용 용량 늘려주기
nano nginx/default.conf
server {
listen 80;
server_name localhost;
# [추가할 내용] 파일 업로드 용량 제한 늘리기 (원하는 만큼)
client_max_body_size 3G;
location / {
# ... 기존 설정들 ...
}
# ... 나머지 설정들 ...
}
docker-compose restart nginx
💭 KPT
Keep
이번 주 가장 잘한 점은 끝까지 파고드는 끈기입니다.
서버가 멈추고, 이미지가 깨지고, API 설정이 바뀌어 있는 난관의 연속이었지만, 안되면 될 때까지라는 마음으로 로그를 뒤지고 해결책을 찾아냈어요.
인프라 설정이 낯설고 어려웠지만, 피하지 않고 정면 돌파하여 직접 환경을 구축해 낸 경험은 앞으로 큰 자산이 될 것 같습니다.
Problem
배포와 환경 설정 이슈를 해결하느라 시간을 많이 쏟다 보니, 정작 핵심 기능 코드의 퀄리티를 챙길 여유가 부족했어요.
급하게 서버에서 직접 파일을 수정(nano 편집기)하고 덮어씌운 경우도 있어서, 로컬 코드와 형상 관리가 꼬이지 않았는지 걱정이 됩니다.
코드가 더 복잡해지기 전에 동기화 작업이 시급해 보입니다.
Try
다음 주는 미뤄두었던 Runpod AI 모델 API 연동을 최우선으로 진행할 예정입니다.
그리고 이번 주에 급하게 처리하느라 지저분해진 설정과 환경 변수 파일들을 깔끔하게 정리하려고 해요.
이번 주는 현실의 서버비(?)가 나가는 환경과 싸우느라 유독 길게 느껴졌던 한 주였어요.
하지만 까만 터미널 창에 초록색 Running 문구가 떴을 때의 그 안도감은 무엇과도 바꿀 수 없더라고요.
산더미 같은 에러 로그 앞에서도 굴하지 않고 묵묵히 해결해 나간 저 자신에게 박수를 보내며,
마지막 한 주도 지치지 않고 즐겁게 달려보겠습니다. 화이팅! 🔥🏃🏻♀️
'회고' 카테고리의 다른 글
| [플레이데이터 SK네트웍스 Family AI 캠프 17기] AI 부트캠프 수료 후기 (2) | 2025.12.25 |
|---|---|
| [플레이데이터 SK네트웍스 Family AI 캠프 17기] 25주차 회고 (0) | 2025.12.25 |
| [플레이데이터 SK네트웍스 Family AI 캠프 17기] 23주차 회고 (0) | 2025.12.07 |
| [플레이데이터 SK네트웍스 Family AI 캠프 17기] 22주차 회고 (0) | 2025.12.07 |
| [플레이데이터 SK네트웍스 Family AI 캠프 17기] 21주차 회고 (0) | 2025.11.24 |