프로그래머스 과제 테스트 <api 서버만들기에서도 봤고, 이번 관통플젝에서도 보여셔 쓴다. 또한 이번에 네트워크 공부하고 보니까 또 다르게 보이는 것,백엔드 처리 흐름 이해도 강화하게 되었고, 나와 같은 사람에게 도움이 되겠다 싶어 적는다.
이 코드 다 볼 필요보다. 아래의 사진과, 몇 가지 메소드만 보면 되지 싶다.
package com.ssafy.yumyumcoach.app;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.file.Path;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.ssafy.yumyumcoach.manager.FoodManager;
import com.ssafy.yumyumcoach.manager.MealManager;
import com.ssafy.yumyumcoach.manager.NutritionAnalysisManager;
import com.ssafy.yumyumcoach.manager.UserManager;
import com.ssafy.yumyumcoach.repository.FoodRepository;
import com.ssafy.yumyumcoach.repository.MealRepository;
import com.ssafy.yumyumcoach.repository.UserRepository;
import com.ssafy.yumyumcoach.web.AuthController;
import com.ssafy.yumyumcoach.web.FoodController;
import com.ssafy.yumyumcoach.web.HttpSupport;
import com.ssafy.yumyumcoach.web.MealController;
import com.ssafy.yumyumcoach.web.SessionManager;
import com.ssafy.yumyumcoach.web.StaticFileHandler;
import com.ssafy.yumyumcoach.web.UserController;
import com.sun.net.httpserver.HttpServer;
/** Spring 없이 JDK HttpServer로 실행하는 웹 애플리케이션 진입점이다. */
public class YumYumWebApplication {
private static final int DEFAULT_PORT = 8080;
private YumYumWebApplication() {
}
public static void main(String[] args) throws IOException {
int port = Integer.getInteger("server.port", DEFAULT_PORT);
// 모든 화면과 API가 같은 객체를 사용하도록 한 번만 생성해 연결한다.
UserRepository userRepository = new UserRepository();
FoodRepository foodRepository = new FoodRepository();
MealRepository mealRepository = new MealRepository();
UserManager userManager = new UserManager(userRepository);
FoodManager foodManager = new FoodManager(foodRepository);
MealManager mealManager = new MealManager(
mealRepository,
foodRepository
);
NutritionAnalysisManager nutritionManager =
new NutritionAnalysisManager(
mealRepository,
foodRepository
);
SessionManager sessionManager = new SessionManager(userRepository);
HttpServer server = HttpServer.create(
new InetSocketAddress(
InetAddress.getLoopbackAddress(),
port
),
0
);
server.createContext(
"/api/auth",
new AuthController(sessionManager)
);
server.createContext(
"/api/users",
new UserController(userManager, sessionManager)
);
server.createContext(
"/api/foods",
new FoodController(foodManager, sessionManager)
);
server.createContext(
"/api/meals",
new MealController(
mealManager,
nutritionManager,
foodRepository,
sessionManager
)
);
server.createContext("/api/health", exchange ->
HttpSupport.handle(exchange, () -> {
if (!exchange.getRequestMethod().equals("GET")) {
HttpSupport.methodNotAllowed(exchange, "GET");
return;
}
HttpSupport.sendJson(
exchange,
200,
Map.of("status", "UP")
);
})
);
server.createContext(
"/",
new StaticFileHandler(Path.of("web"))
);
int threadCount = Math.max(
4,
Runtime.getRuntime().availableProcessors()
);
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
server.setExecutor(executor);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
server.stop(1);
executor.shutdown();
}));
server.start();
System.out.println("YumYumCoach 웹 서버가 시작되었습니다.");
System.out.println("접속 주소: http://localhost:" + port);
System.out.println("종료: Ctrl+C");
}
}

기본적인 구조도는 이러하다.
그리고 번거로운 메서드들은 나는 다음과 같았다.
지금까지 대화 나누면서 질문하신 YumYumWebApplication.java 파일 내의 주요 구성 요소 및 메서드 목록입니다.
YumYumWebApplication() (생성자)new YumYumWebApplication()으로 객체를 생성하지 못하게 막는 인스턴스화 방지(private 생성자) 패턴.HttpServer.create(...)InetSocketAddress, 0)InetSocketAddress) 및 요청 대기 큐 크기(backlog) 설정.server.createContext("/api/auth", new AuthController(...))server.createContext("/api/meals", new MealController(...))server.createContext("/api/health", exchange -> ...)HttpSupport) 활용.if (!exchange.getRequestMethod().equals("GET")) (Health Check 내부)405 Method Not Allowed를 응답하고 차단하는 예외 처리.server.createContext("/", new StaticFileHandler(Path.of("web")))web 폴더 내 정적 파일(HTML/CSS/JS)을 클라이언트에 응답하기 위한 루트 경로 핸들러 연결.Runtime.getRuntime().addShutdownHook(...)Ctrl+C 등) 진행 중인 요청을 정리하고 스레드 풀 및 서버를 안전하게 닫는 셧다운 후크(Graceful Shutdown).Executors.newFixedThreadPool(...) / `server.setExecutor(...)`HttpServer 기본 스레드 그거 없어? 우리가 executor service 만든 거야? 왜? / 스프링에서는 알아서 했던 건가?HttpServer는 기본 멀티스레딩 스레드 풀이 없어서 직접 ExecutorService를 넘겨줘야 함과 스프링 부트 내장 Tomcat과의 비교.Application.java가 왜 두 개야? 시작점은 하나 아니야?main 진입점을 나누어 둘 수 있음.