안녕하세요! 그로스로그 입니다!😊 🌱
무료라고 들었는데 3천원이 청구된 이야기, 그리고 분명 만들어둔 페이지가 404를 뱉던 이야기. 1기 6회차 두 편입니다.
성장일지는 멤버들이 2주에 한 번씩 자신의 성장을 기록하는 활동이에요. 매 회차 운영진이 모든 글을 읽고, 그중 특히 마음에 남은 글을 함께 골라 큐레이션합니다.
이번 회차는 공식 문서가 알려주지 않는 것들을 다룬 두 편입니다.
01
☁️ AWS EC2 서버와 RDS, 12개월 무료로 써보자
곽경훈 님
AWS 프리티어로 EC2 서버와 RDS 데이터베이스를 12개월 동안 무료로 쓰는 구성 방법을 정리했습니다. EC2 30GB, RDS 20GB까지가 무료 범위예요.
단순한 가입 안내가 아니라 실제로 요금이 나올 수 있는 지점들을 짚어줍니다. 신용카드 등록까지 마쳐야 가입이 완료된다는 것부터요.
특히 gp3 스토리지를 골랐다가 3천원이 청구된 경험을 그대로 적어두셨습니다. 프리티어 범위 안이라고 생각했는데 아니었던 거죠. 이런 함정은 공식 안내 페이지만 봐서는 잘 안 보입니다.
개인 프로젝트를 배포하려는 학생과 주니어에게 AWS 프리티어는 사실상 첫 관문입니다. 그런데 여기서 예상치 못한 요금을 맞는 경우가 흔해요.
이 글은 EC2와 RDS를 프리티어 범위 안에서 구성하는 방법을 정리하면서, 어디서 돈이 새는지를 같이 짚습니다. 그중 gp3를 선택했다가 3천원이 나온 경험이 특히 구체적이에요.
조금 더 들어가 보면
AWS 프리티어에서 요금이 새는 이유는 대개 "무료"의 조건이 생각보다 촘촘하기 때문입니다.
프리티어는 크게 세 종류가 섞여 있습니다. 12개월 무료(가입 후 1년간), 상시 무료(계속 무료지만 사용량 제한), 단기 체험(짧은 기간만). 사람들은 보통 "AWS 1년 공짜"로 뭉뚱그려 기억하는데, 서비스마다 어디에 속하는지가 다릅니다.
여기에 인스턴스 타입과 옵션까지 조건에 걸립니다. EC2는 t2.micro 또는 t3.micro만 무료고, 스토리지도 종류가 정해져 있어요. 글에서 걸린 gp3가 바로 이 지점입니다. gp3는 gp2보다 새롭고 성능도 좋은데, 프리티어 대상에서 벗어나는 경우가 있습니다. 화면에서는 그냥 선택지 중 하나로 보이니 모르고 고르기 쉽죠.
초보자가 요금을 맞는 대표적인 경로가 몇 개 더 있습니다.
탄력적 IP(Elastic IP) — 인스턴스에 붙어 있으면 무료인데, 인스턴스를 껐는데 IP는 안 반납하면 과금됩니다. "안 쓰니까 껐다"가 오히려 요금을 만드는 역설이에요.
데이터 전송(아웃바운드) — 서버로 들어오는 트래픽은 무료지만 나가는 트래픽은 월 한도가 있습니다. 이미지가 많은 서비스라면 생각보다 빨리 찹니다.
스냅샷과 백업 — RDS 자동 백업은 편한데, 보관 용량이 무료 범위를 넘으면 조용히 쌓이면서 과금됩니다.
12개월이 끝나는 날 — 가장 큰 함정입니다. 1년 뒤 아무 일도 안 했는데 갑자기 월 몇 만원이 청구돼요. 켜둔 걸 잊고 있다가 카드 명세서로 알게 되는 경우가 정말 많습니다.
그래서 프리티어를 쓸 때 실제로 해야 할 일은 예산 알림 설정입니다. AWS Budgets에서 "1달러 넘으면 메일 보내줘"를 걸어두면 사고가 커지기 전에 알 수 있어요. 이 글처럼 3천원에서 알아채는 것과 3개월 뒤 10만원에서 알아채는 건 완전히 다릅니다.
큐레이터 노트
돈을 물어본 경험을 그대로 적었다는 점에서 뽑았습니다.
클라우드 입문 글은 많습니다. 대부분 "가입하고, 인스턴스 만들고, 접속하면 끝"으로 끝나요. 그런데 실제로 초보자를 곤란하게 만드는 건 그 단계가 아니라 한 달 뒤 날아오는 청구서입니다.
3천원은 큰돈이 아닙니다. 그런데 이 경험을 적어둔 덕분에, 이 글을 읽은 사람은 스토리지 선택 화면에서 한 번 멈추게 됩니다. 작은 실수를 기록하면 남의 큰 실수를 막을 수 있어요.
프리티어 구성을 EC2와 RDS로 나눠 용량까지 명시한 것도 실용적이었습니다. 숫자가 있으면 내 상황과 바로 비교할 수 있으니까요.
02
🧩 스프링부트 코틀린 프로젝트에 JSP 띄우기
오연수 님
스프링부트 코틀린 멀티모듈 프로젝트에 JSP 페이지를 연동하려다 계속 404를 만난 기록입니다.
분명 파일을 만들어뒀는데 페이지를 찾을 수 없다고 나오는 상황이라, 어디서부터 봐야 할지조차 막막했어요.
원인을 세 가지로 나눠 정리했습니다. WAR로 빌드해야 한다는 점,
bootRun으로 실행할 때의 차이, 그리고 JSP 파일이 놓여야 할 정확한 위치. 하나만 어긋나도 똑같이 404가 나기 때문에 셋을 모두 맞춰야 합니다.이 글의 상황이 꽤 얄궂습니다. 파일은 분명히 있는데 404가 납니다. 오타도 아니고 경로도 맞는 것 같은데요.
원인은 하나가 아니라 세 가지가 겹쳐 있었습니다. 빌드 방식, 실행 방식, 파일 위치. 그래서 하나를 고쳐도 여전히 404가 났고, 그게 문제를 더 어렵게 만들었어요.
조금 더 들어가 보면
스프링부트에서 JSP는 의도적으로 홀대받는 기술입니다. 이 배경을 알면 왜 이렇게 까다로운지가 이해돼요.
스프링부트의 기본 철학은 JAR 하나로 실행되는 애플리케이션입니다. java -jar app.jar 한 줄이면 서버까지 내장돼서 뜨는 구조죠. 배포가 단순해지고 컨테이너에 올리기도 좋습니다.
그런데 JSP는 이 구조와 맞지 않습니다. JSP는 실행 시점에 서블릿으로 변환되어야 하는데, 이 과정이 내장 톰캣이 JAR 안을 들여다보는 방식에서는 제대로 동작하지 않아요. 그래서 스프링부트 공식 문서도 JSP를 쓰려면 WAR로 패키징하라고 안내합니다. Thymeleaf 같은 템플릿 엔진을 권하는 것도 이 때문이고요.
여기에 bootRun의 함정이 겹칩니다. 개발 중에는 IDE나 Gradle의 bootRun으로 띄우는 게 편한데, 이건 실제 배포와 실행 방식이 달라요. 클래스패스 구성과 리소스 탐색 경로가 미묘하게 다르기 때문에, bootRun에서는 되는데 빌드하면 안 되거나 그 반대인 상황이 생깁니다.
마지막이 파일 위치입니다. JSP는 src/main/webapp/WEB-INF/jsp/ 같은 경로에 있어야 하는데, 이건 스프링부트의 일반적인 리소스 위치(src/main/resources/)와 다릅니다. 관례를 따라 resources 밑에 두면 조용히 못 찾습니다.
여기에 멀티모듈까지 얹히면 난이도가 한 단계 더 올라갑니다. 어느 모듈의 webapp 디렉터리를 봐야 하는지, 빌드 산출물이 어디로 모이는지가 프로젝트 구조에 따라 달라지거든요.
정리하면 이 404는 세 개의 독립적인 조건이 모두 맞아야 사라지는 문제였습니다. 하나씩 고치면서 계속 404를 보면 "이것도 아닌가" 하고 방향을 잃기 쉬운데, 그걸 원인별로 갈라서 정리해둔 게 이 글의 값어치예요.
📝 원문에서는 이렇게 맞춥니다
세 조건이 각각 어디에 적히는지가 글에 그대로 나옵니다. 먼저 의존성입니다.
dependencies {
// jsp 관련 의존성 추가
implementation("org.apache.tomcat.embed:tomcat-embed-jasper")
implementation("org.glassfish.web:jakarta.servlet.jsp.jstl")
implementation("jakarta.servlet:jakarta.servlet-api")
implementation("jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api")
}
tomcat-embed-jasper가 앞서 말한 JSP 번역기입니다. 이게 없으면 톰캣은 .jsp 파일을 그냥 모르는 파일로 취급합니다.
그다음이 뷰 리졸버 설정입니다.
spring:
mvc:
view:
prefix: /WEB-INF/jsp/
suffix: .jsp
컨트롤러가 "main"을 반환하면 스프링이 앞뒤를 붙여 /WEB-INF/jsp/main.jsp를 찾습니다. 문자열 하나가 파일 경로로 바뀌는 규칙을 여기서 정하는 거예요.
마지막으로 그 파일이 실제로 놓여야 할 자리입니다.
project-root
└── bootstrap
└── src
└── main
├── kotlin
│ └── com/example/Application.kt (main 함수)
└── webapp
└── WEB-INF
└── jsp
└── yourJspFile.jsp
kotlin과 webapp이 나란히 있다는 점을 눈여겨보세요. resources 밑이 아닙니다. 설정 두 개를 아무리 정확히 써도 파일이 이 자리에 없으면 여전히 404입니다.
큐레이터 노트
원인을 세 개로 나눠 정리한 구조가 좋았습니다.
같은 증상(404)에 원인이 여럿일 때, 사람들은 보통 마지막에 고친 것만 기록합니다. "이거 고쳤더니 됐어요"로요. 그런데 실제로는 앞의 두 개도 이미 고친 상태였을 수 있거든요. 그러면 그 글을 읽고 따라 한 사람은 여전히 404를 보게 됩니다.
이 글은 셋을 다 적었습니다. 덕분에 읽는 사람이 자기 상황에서 뭐가 어긋났는지 대조할 수 있어요. 체크리스트로 쓸 수 있는 글이 됐습니다.
그리고 JSP처럼 요즘 잘 안 쓰지만 실무에서는 여전히 만나는 기술을 다룬 것도 의미가 있습니다. 최신 스택 글은 넘치는데, 레거시를 붙들고 있는 사람을 위한 글은 훨씬 적거든요.
💡 두 편을 겹쳐 읽으며
한 편은 클라우드 요금 이야기고, 한 편은 404 추적기입니다. 공통점은 공식 안내를 따랐는데도 안 됐다는 점이에요.
AWS 콘솔은 gp3를 선택지에 보여줬습니다. 그게 프리티어에서 벗어난다는 경고는 그 자리에 없었고요. 스프링부트는 JSP를 지원한다고 되어 있습니다. 다만 WAR로 빌드해야 하고, 파일은 특정 위치에 있어야 하고, 실행 방식에 따라 다르게 동작한다는 조건들이 여기저기 흩어져 있을 뿐이죠.
문서가 틀린 게 아니라, 조건이 흩어져 있는 겁니다. 그리고 그 조건들이 만나는 지점에서 사람들이 넘어집니다.
두 분 다 그 지점을 지나면서 흩어진 조건을 한자리에 모아 기록했습니다. 3천원의 함정과 404의 세 가지 원인 — 다음 사람은 이걸 한 번에 볼 수 있게 됐어요.
이번 회차에서 가져갈 것
1. "무료"에는 항상 조건이 붙는다. 클라우드 프리티어를 쓴다면 예산 알림부터 걸어두세요. AWS Budgets에서 1달러 기준으로 설정해두면, 사고가 커지기 전에 메일이 옵니다. 그리고 12개월이 끝나는 날짜를 캘린더에 적어두는 것도 잊지 마세요.
2. 같은 에러에 원인이 여럿일 수 있다. 하나 고쳤는데 증상이 그대로면 "이게 원인이 아니었나" 싶지만, 이미 맞춘 조건 하나였을 수도 있습니다. 고친 것들을 목록으로 남겨두면 방향을 잃지 않습니다.
3. 프레임워크가 권하지 않는 길은 원래 험하다. 스프링부트에서 JSP를 쓰는 건 가능하지만 권장 경로가 아닙니다. 이런 선택을 할 때는 "왜 권장하지 않는가"를 먼저 알아두면 어디서 막힐지 예상할 수 있어요.
1기 6회차입니다. 이제 8월, 첫 기수의 막바지로 접어들 무렵이에요.
돌아보면 1기 멤버들의 글이 회차를 거듭하며 점점 구체적으로 변했습니다. 초반엔 "무엇을 공부했다"에 가까웠다면, 이 시기엔 "어디서 막혔고 어떻게 뚫었다"로 옮겨가 있었어요. 성장일지가 습관이 되면 자연스럽게 일어나는 변화 같습니다.
좋은 글 남겨주신 곽경훈 님, 오연수 님께 감사드립니다. 그리고 지금 AWS 콘솔 앞에서 "이거 진짜 무료 맞나" 고민하고 계신 분들께도요! 😊
다음 큐레이션으로 다시 찾아오겠습니다! 🌱
- 에디터 · 성장일지 큐레이터 -
※ 본 큐레이션은 각 저자가 공개한 글을 소개하는 것이며, 모든 원문의 저작권은 저자에게 있습니다. 저자 본인의 요청이 있을 경우 즉시 수정 또는 삭제합니다.
'성장일지' 카테고리의 다른 글
| [GL 2기] import 정렬 자동화부터 언리얼 이동 동기화까지 (성장일지 1회차 큐레이션) 🌱 (0) | 2026.08.07 |
|---|---|
| [GL 1기] Cypress로 시작하는 E2E 테스트, 그리고 4주 만에 동작한 웹크롤러 (성장일지 7회차 큐레이션) 🌱 (0) | 2026.08.07 |
| [GL 1기] React-Flask 배포 시행착오와 환경별 설정 분리 (성장일지 5회차 큐레이션) 🌱 (0) | 2026.08.07 |
| [GL 1기] FCM 푸시 알림 붙이기와 간헐적 ChunkLoadError 추적 (성장일지 4회차 큐레이션) 🌱 (0) | 2026.08.07 |
| [GL 1기] EC2에서만 멈추는 스트리밍, 500줄짜리 검색 쿼리 (성장일지 3회차 큐레이션) 🌱 (0) | 2026.08.07 |