Java 소켓 프로그래밍을 통해 HTTP 웹 서버를 직접 구현하는 학습 프로젝트
- Spring MVC, 톰캣, 서블릿 컨테이너가 내부적으로 어떻게 동작하는지 직접 구현하며 이해하는 것이 목표
- HTTP 요청/응답 구조 및 프로토콜 원리 이해
- 서블릿 컨테이너가 하는 일을 직접 구현하며 체득
- FrontController(DispatcherServlet) 패턴 이해
- 세션/쿠키 기반 인증 흐름 이해
- Java 21
- Gradle (Kotlin DSL)
- JUnit 5
# 빌드
./gradlew build
# 실행
./gradlew run
# 테스트
./gradlew test서버 실행 후 브라우저에서 http://localhost:8080 접속
구현 계획은 초안으로 진행 상황에 따라 유동적으로 변경될 수 있습니다.
-
환경 세팅 및 최소 HTTP 서버 구현
- ServerSocket으로 연결 수락
- 하드코딩된 HTTP 응답 전송
-
HTTP 요청/응답 파싱
- Request Line 파싱 (Method, Path, Version)
- Header 파싱
- Body 파싱 (POST)
- HttpRequest / HttpResponse 클래스 설계
- 단위 테스트 작성
-
RequestHandler 구현
- InputStream → HttpRequest
- HttpResponse → OutputStream
- 기본 요청 흐름 통합 테스트
-
Servlet / ServletContainer
- Servlet 인터페이스 정의
- URL → Servlet 매핑
- StaticResourceServlet 구현
- 컨테이너와 서블릿 책임 분리
-
FrontController & 라우팅
- Controller 인터페이스 정의
- RouteKey(HttpMethod + Path) 기반 라우팅 구조
- FrontControllerServlet 구현
- Spring MVC DispatcherServlet 구조 이해
-
로그인 & 세션
- User / UserRepository 구현
- SessionManager 구현 (Cookie 기반)
- 회원가입, 로그인, PRG 패턴 적용
- 로그인 여부 확인 로직
-
멀티스레드 서버
- ExecutorService로 요청 병렬 처리
- 공유 저장소 동시성 고려
- thread-safe 자료구조 도입 (
ConcurrentHashMap,AtomicLong)
-
TODO LIST 기능 (간단 버전)
- Todo / TodoRepository
- TODO 목록 조회 (GET)
- TODO 추가 (POST)
- 사용자별 TODO 관리
-
JDBC Foundations
-
DataSource → Connection → PreparedStatement → ResultSet흐름을 코드로 확인 (DataSource인터페이스 대신DriverManager직접 사용,DatabaseConfig) -
autoCommit=true/false차이 재현 (부분 커밋 vs 원자성) -
commit / rollback직접 호출해 트랜잭션 경계 체감 -
close()타이밍(commit 전/후, 예외 시) 차이 관찰 - “트랜잭션 = Connection 상태”를 설명할 수 있다
-
-
JDBC Repository (직사용 버전)
-
JdbcTodoRepository구현 (CRUD 최소 세트) (JdbcTodoRepositoryV2가 직사용 버전,JdbcTodoRepository는 이후JdbcExecutor기반 버전) - try/finally로
Statement/ResultSet/Connection자원 해제 보장 -
SQLException을 Runtime 예외로 변환해 전파 - 부분 커밋이 실제로 발생하는 유즈케이스를 서비스 레벨에서 재현
-
-
Spring JDBC 책임 1: 실행 흐름 템플릿화 (JdbcTemplate)
-
JdbcTemplate#update(sql, PreparedStatementSetter)구현 -
JdbcTemplate#query(sql, PreparedStatementSetter, RowMapper<T>)구현 -
JdbcTemplate#queryForObject(...)구현 (0건/2건 이상 정책 포함) -
PreparedStatementSetter도입 (파라미터 바인딩 책임 분리) -
RowMapper<T>도입 (ResultSet 매핑 책임 분리) - Repository에서 JDBC 반복 코드(획득/해제/예외 처리)를 제거
-
-
Spring JDBC 책임 2: 트랜잭션-커넥션 동기화 (Connection Binding)
-
TransactionSynchronizationManager구현 (ThreadLocal 리소스 바인딩) (ConnectionContext로 구현) -
ConnectionHolder구현 (Connection + 최소 상태 보관) (Connection을 ThreadLocal에 직접 바인딩) -
DataSourceUtils#getConnection(DataSource)구현 (ConnectionProvider로 구현)- 트랜잭션 중이면 바인딩된 Connection 반환
- 아니면 새 Connection 반환
-
JdbcTemplate이dataSource.getConnection()대신DataSourceUtils를 통해 커넥션을 얻도록 변경 (JdbcExecutor가ConnectionProvider사용) - “같은 트랜잭션 = 같은 Connection” 재현 (여러 DAO 호출에서 동일 커넥션 사용)
-
-
Spring JDBC 책임 3: 트랜잭션 경계 관리 (TransactionManager)
-
PlatformTransactionManager(최소 인터페이스) 정의 (인터페이스 없이SimpleTransactionManager단일 클래스로 구현) -
DataSourceTransactionManager구현 (SimpleTransactionManager로 구현)- begin:
autoCommit=false+ Connection 바인딩 - commit/rollback
- cleanup: 바인딩 해제 + close
- begin:
- 트랜잭션 유무에 따른 동작 차이 테스트
- 트랜잭션 없음: 호출마다 새 Connection + 즉시 커밋
- 트랜잭션 있음: 하나의 Connection 공유 + 마지막에 commit/rollback
-
-
(Optional) 선언적 트랜잭션 맛보기
-
TransactionTemplate#execute(...)형태로 경계 분리 - (선택) 애노테이션 기반 프록시로
@Transactional흐름 최소 재현 - self-invocation / 스레드 경계(ThreadLocal)의 한계 설명 가능
-
-
연결 재사용 지원
- 요청 1회 처리 후 소켓 유지
- 동일 연결에서 다중 요청 처리
-
요청 경계 처리 강화
-
\r\n\r\n기준 헤더 파싱 안정화 -
Content-Length기반 바디 정확히 읽기 - 남은 버퍼 재사용
-
-
연결 종료 정책
-
Connection: close지원 -
keepAliveTimeout적용 -
maxRequestsPerConnection제한
-
-
응답 정합성 보장
-
Content-Length정확히 설정 - keep-alive / close 헤더 일관성 유지
-
-
통합 테스트
- 동일 연결 다중 요청 성공
- close / timeout 정상 동작 확인