안녕하세요 트윅히입니다.
앞으로 비전공자의 전공자 되기 글을 꾸준히 올려보겠습니다. :)
저와 같은 비전공자 베이스 개발자분들이 많은 도움 받으시길 바랄게요
구독도 많이 신청해주세요!!
가끔은 비전공자라서 서러울 때도 있습니다.
저도 제 적성을 좀 더 일찍 알았더라면 대학도 그쪽으로 갔을 텐데.. 많이 아쉽긴 해요..
제가 하고 싶은 걸 깨달았을 땐 대학교 4학년즈음이어서 전과를 하기엔 많이 늦었던 것 같습니다.
아쉽지만 전공이 아닌 건 사실이고 부족한 부분은 채워나가야죠 ㅎㅎㅎ
우리 모두 화이팅입니다.!!

웹 개발을 하다 보면 "URL이랑 URI가 뭐가 다르냐"는 질문을 꼭 한 번은 마주치게 됩니다.
오늘은 이 개념 정리를 시작으로, 초창기 웹부터 현재 서비스 구조까지 흐름을 같이 따라가 보겠습니다! 🚀
📚 목차
- URI vs URL, 뭐가 다를까?
- 초창기 웹 - 단방향 정적 문서의 시대
- CGI - 웹을 동적으로 만들려는 첫 시도
- POST 통신과 동적 문서의 탄생 (JSP)
- Java와 JVM - 플랫폼 독립성의 등장
- WS → WAS - 서비스 처리 전문 서버의 등장
- 상태를 기억하는 방법 - DB, Cookie, Session
- 기기가 다양해지면서 - JSON과 SPA의 등장
- 보안 위협과 방어 전략
- HTTPS와 서버 앞단 보안 구성
1. URI vs URL, 뭐가 다를까?
처음엔 이 둘이 그냥 같은 말처럼 느껴지죠. 하지만 엄밀히 따지면 URI가 더 큰 개념입니다.
용어 풀네임 설명
| URI | Uniform Resource Identifier | 리소스를 식별하는 모든 방식 |
| URL | Uniform Resource Locator | 리소스의 **위치(주소)**를 나타냄 |
즉, URL ⊂ URI 입니다. URL은 URI의 한 종류예요.
protocol://address:port/path
예) https://example.com:443/index.html
💡 naver.com을 입력하면 서버가 자동으로 naver.com/index.html로 변환해서 응답합니다.
이때 실제로 불러오는 **리소스(파일)**가 존재하기 때문에 URL이라고 부를 수 있는 거예요.
2. 초창기 웹 - 단방향 정적 문서의 시대
웹이 처음 세상에 나왔을 때는 지금과 많이 달랐습니다.
- 통신 방식: HTTP + GET (단방향)
- 전송 내용: HTML 문서 (정적 파일)
- 사용자 인터랙션: 거의 없음
처음엔 그냥 문서를 읽어오는 게 전부였어요. 클릭하면 다른 페이지로 이동하고, 또 다른 HTML 파일을 받아오는 방식이었죠.
시간이 지나면서 JavaScript가 더해지면서 조금씩 동적인 요소가 생기기 시작했습니다.

3. CGI - 웹을 동적으로 만들려는 첫 시도
정적인 HTML만 보여주는 것이 한계에 부딪히자, 사람들은 이런 생각을 했습니다.
"서버에서 프로그램을 실행해서, 그 결과를 HTML로 내보내면 어떨까?"
그게 바로 CGI (Common Gateway Interface) 입니다.
웹 서버와 외부 프로그램(C 언어 등) 사이의 연결 통로 역할을 했어요.
사용자의 요청이 들어오면, CGI를 통해 C 프로그램을 실행하고, 그 결과를 HTML로 반환하는 방식이었습니다.
다만 C 언어는 플랫폼 의존성이 강해서,
운영체제가 바뀌면 코드를 다시 작성해야 하는 문제가 있었습니다. 그리고 요청마다 프로세스를 새로 생성하는 구조라 성능도 좋지 않았죠.
결국 CGI는 역사 속으로 사라지게 됩니다. 😅

4. POST 통신과 동적 문서의 탄생 (JSP)
GET만 있던 시절에서 한 발 더 나아가, POST 방식이 등장했습니다.
- GET: 서버에서 데이터를 가져옴
- POST: 클라이언트의 데이터를 서버로 전송
이제 사용자가 입력한 정보를 서버로 보낼 수 있게 된 거예요!
그리고 서버에서는 HTML 파일에 구멍을 뚫어놓고,
데이터를 동적으로 집어넣는 방식이 생겼습니다. 이게 바로 JSP (JavaServer Pages) 의 핵심 아이디어입니다.
<!-- 예시: JSP에서 동적으로 이름 출력 -->
<html>
<body>
<h1>안녕하세요, <%= request.getParameter("name") %>님!</h1>
</body>
</html>
서버가 이 템플릿에 실제 데이터를 넣어서 완성된 HTML을 클라이언트로 보내주는 거죠. 이게 서버 사이드 렌더링(SSR) 의 원형입니다.
5. Java와 JVM - 플랫폼 독립성의 등장

C 언어의 플랫폼 의존성 문제를 해결하기 위해 Java가 등장합니다.
"Write Once, Run Anywhere"
Java의 핵심 철학은 어떤 운영체제에서도 동일하게 동작한다는 것이었어요. 그 비결은 바로 JVM (Java Virtual Machine) 입니다.
Java 소스 코드 (.java)
↓ 컴파일
Java 바이트코드 (.class)
↓ JVM 실행
각 OS에서 동작
Java 코드는 컴파일되면 바이트코드가 되고, 이 바이트코드를 JVM이 각 운영체제에 맞게 실행해줍니다. OS에 직접 의존하지 않고, JVM이라는 논리적인 가상 머신 위에서 동작하는 구조예요.
덕분에 웹 서버 개발에도 Java가 적극 활용되기 시작했습니다.
6. WS → WAS - 서비스 처리 전문 서버의 등장
웹 서버(Web Server, WS)가 정적 리소스 제공을 담당하는 동안, 비즈니스 로직 처리를 전담하는 서버가 따로 필요해졌습니다.
그게 바로 WAS (Web Application Server) 입니다.
클라이언트
↓ 요청
Web Server (WS) ← 정적 리소스 (HTML, CSS, 이미지 등)
↓ 동적 처리 필요 시
Web Application Server (WAS) ← 비즈니스 로직, DB 연동
↓
Database (DB)
이렇게 역할을 분리함으로써 서버 구성이 훨씬 유연해졌습니다.
대표적인 WAS로는 Tomcat, JBoss, WebLogic 등이 있죠.
요즘은 WAS와 ws 의 경계가 흐려졌습니다.
원래 역할 구분
| 역할 | 정적 파일 서빙, SSL 종료, 리버스 프록시 | 동적 비즈니스 로직 처리 |
| 잘하는 것 | 대용량 정적 콘텐츠, 커넥션 관리 | 애플리케이션 실행 |
왜 경계가 흐려졌냐면
- Spring Boot의 내장 Tomcat — 별도 Nginx 없이 단독으로 HTTPS, 정적 파일, 리버스 프록시 없이 직접 서빙 가능
- 클라우드 환경 — ALB/NLB가 SSL 종료, 로드밸런싱을 담당하면서 Nginx의 전통적 역할을 가져감
- 컨테이너/K8s — Ingress Controller(nginx-ingress 등)가 ws 역할을 하면서, 앱 레벨에선 WAS만 두는 구성이 일반화
7. 상태를 기억하는 방법 - DB, Cookie, Session
HTTP는 기본적으로 Stateless 프로토콜입니다.
요청을 처리하고 나면 서버는 클라이언트를 기억하지 못해요.
그래서 상태를 기억하기 위한 방법들이 생겨났습니다.
🗄️ 서버 측 - DB
서버는 사용자 정보나 처리 결과를 데이터베이스에 저장합니다.
🍪 클라이언트 측 - Cookie
클라이언트는 쿠키(Cookie) 를 통해 상태를 기억할 수 있어요.
- 브라우저에 파일로 저장됩니다
- 요청 시 자동으로 서버에 전송됩니다
- 만료 시간 설정 가능
🔐 세션 (Session)
HTTP가 Stateless이다 보니, 상태를 유지하려면 세션이 필요합니다.
(요즘은 stateless 방식으로 JWT 같은 토큰을 사용해서 많이 구현을 하고 있죠)
1. 사용자 로그인
2. 서버가 Session ID 생성 → DB or 메모리에 저장
3. Session ID를 Cookie에 담아 클라이언트에 전달
4. 이후 요청마다 Cookie의 Session ID로 사용자 식별
8. 기기가 다양해지면서 - JSON과 SPA의 등장
스마트폰, 태블릿, IoT 기기 등 다양한 클라이언트가 등장하면서 문제가 생겼습니다.
"서버에서 HTML을 만들어서 보내줄 수가 없잖아...
각 기기마다 화면 구성이 다른데?"
그래서 서버는 HTML 대신 데이터(JSON) 만 보내주고, 클라이언트가 직접 화면을 그리는 방식으로 진화했습니다.
// 서버가 보내는 JSON 데이터 예시
{
"userId": 1,
"username": "joohee",
"email": "user@example.com"
}
클라이언트는 이 데이터를 받아서 React, Vue, Angular 같은 클라이언트 사이드 프레임워크로 HTML을 동적 생성합니다.
이게 바로 SPA (Single Page Application) 구조예요.
그리고 이런 WAS와 DB의 상태를 모니터링하기 위한 APM (Application Performance Management) 도구도 발전했습니다.
대표적으로 Scouter 같은 도구들이 있죠.
9. 보안 위협과 방어 전략
서비스가 복잡해질수록 보안 위협도 다양해졌습니다.
원칙은 하나입니다.
⚠️ 원격 사용자의 입력은 절대 신뢰하지 말고, 무조건 검증하라!
💉 XSS (Cross-Site Scripting)
사용자 입력에 JavaScript 코드가 포함되어 실행되는 공격입니다.
<!-- 악의적인 입력 예시 -->
<input value="<script>document.cookie 탈취 코드</script>">
입력값에서 HTML 태그나 스크립트를 이스케이프(escape) 처리해야 합니다.
🎭 CSRF (Cross-Site Request Forgery)
공격자가 만든 스크립트를 통해, 피해자의 권한으로 원치 않는 요청을 실행시키는 공격입니다.
예) 악성 사이트 방문만으로 쇼핑몰에서 결제가 이루어지는 상황
CSRF Token이나 SameSite Cookie 설정으로 방어할 수 있어요.
🗃️ SQL Injection
입력값에 SQL 구문을 넣어 DB를 조작하는 공격입니다.
-- 악의적인 입력 예시
username: ' OR '1'='1
-- 결과: WHERE username = '' OR '1'='1' → 모든 행 반환
Prepared Statement 또는 ORM 을 사용하면 대부분 방어됩니다.
🌐 CORS (Cross-Origin Resource Sharing)
브라우저는 보안상 다른 출처(Origin) 에서 리소스를 요청하는 것을 기본적으로 차단합니다.
https://my-frontend.com → https://api.my-backend.com ← 다른 출처!
서버에서 신뢰할 수 있는 출처를 명시적으로 허용해줘야 합니다.
CORS 설정이 필요한 이유가 바로 여기에 있어요.
10. HTTPS와 서버 앞단 보안 구성
현대 서비스에서 서버 앞단에는 여러 겹의 보안 레이어가 존재합니다. (꼭 이런 건 아니지만여)
클라이언트
↓ HTTPS (암호화 통신)
[IPS] - 침입 탐지/차단
↓
[SSL/TLS 종료] - 암호화 해제
↓
[WAF] - 웹 애플리케이션 방화벽 (XSS, SQL Injection 등 필터링)
↓
Web Server / WAS
구성 요소 역할
| IPS | 네트워크 수준 침입 탐지 및 차단 |
| SSL/TLS | 통신 구간 암호화 (HTTPS의 핵심) |
| WAF | 웹 애플리케이션 레벨 공격 필터링 |
🔒 SSL/TLS와 PKI
HTTPS는 SSL/TLS 프로토콜을 통해 통신을 암호화합니다.
이 암호화의 신뢰 체계를 PKI (Public Key Infrastructure) 라고 합니다.
1. 서버가 인증서 발급 (CA에서 서명)
2. 클라이언트가 인증서 신뢰 여부 확인
3. 공개키/개인키로 대칭키 교환
4. 이후 통신은 대칭키로 암호화
신뢰할 수 있는 인증 기관(CA)이 서버의 신원을 보증하는 방식이라, 중간자 공격(MITM)을 방어할 수 있습니다.
🎯 마무리
지금까지 웹의 발전 흐름을 큰 그림으로 살펴봤습니다.
정적 HTML (초창기)
→ CGI로 동적 처리 시도
→ JSP + Java로 서버 사이드 렌더링
→ WAS 분리로 아키텍처 고도화
→ JSON + SPA로 프론트엔드 독립
→ 다양한 보안 위협과 방어 체계 구축
기초처럼 보이는 개념들이지만, 이 흐름을 이해하고 있으면 새로운 기술을 배울 때도 "아, 이 기술은 이런 문제를 해결하려고 나온 거구나" 하는 맥락이 잡힙니다.
다음에는 HTTP 메서드나 REST API 설계 원칙에 대해서도 정리해볼게요! 😊
'✨ 1일 1개발지식' 카테고리의 다른 글
| [비전공자 전공자 되기 Part 4] 💻 개발자라면 알아야 할 운영체제 핵심 개념 정리(커널과 OS..등) (1) | 2026.03.23 |
|---|---|
| [비전공자 전공자 되기 Part 3] 💻 컴퓨터는 어떻게 계산할까? — 디지털 회로부터 메모리 관리까지 (0) | 2026.03.22 |
| [비전공자 전공자 되기 Part 2] 💻 컴퓨터는 어떻게 데이터를 이해할까? — 비트(bit)부터 이미지까지 (1) | 2026.03.16 |
| ☕ JVM, JRE, JDK의 차이점은? (0) | 2025.12.20 |
| StringBuilder vs StringBuffer 차이가 뭘까? (0) | 2025.10.23 |