* 참고

일반 예외로 선언할 경우 Exception을 상속받아 구현 (컴파일러가 체크)

실행 예외로 선언할 경우에는 RuntimeException을 상속받아 구현


1. CustomException을 사용하는 이유

상세한 예외 정보를 제공, 이름으로도 정보 전달이 가능

Enum과 함께 사용하여 예외에 대한 응집도를 높일 수 있음

@ControllerAdvice, @RestControllerAdvice에서 해당 Custom Exception에 대한 자세한 후처리가 가능 (전역적인 예외 처리)

 

2. 총 4가지의 클래스

1. Exception이 발생하였을때 알려준 Status 상태와 메시지를 담은 enum 클래스

package org.example.exception;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;

@Getter
@RequiredArgsConstructor
public enum CustomErrorCode {

    //== 400 ==//
    NOT_SUPPORTED_HTTP_METHOD(HttpStatus.BAD_REQUEST, "지원하지 않는 Http Method 방식입니다."),
    NOT_VALID_METHOD_ARGUMENT(HttpStatus.BAD_REQUEST, "유효하지 않은 Request Body 혹은 Argument입니다."),


    BAD_REQUEST(HttpStatus.BAD_REQUEST, "ᕕ( ᐛ )ᕗ 잘못된 요청입니다."),
    NOT_FOUND(HttpStatus.NOT_FOUND, "ᕕ( ᐛ )ᕗ 리소스를 찾을 수 없습니다."),


    //== 500 ==//
    INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "서버 내부 오류가 발생했습니다.");

    private final HttpStatus httpStatus;
    private final String message;

}

2. Dto 역할을 하고있는 CustomErrorResponse

package org.example.exception;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

public record ResponseMessage <T> (HttpStatus status, String message, T data) {

    public static ResponseEntity<ResponseMessage> error(CustomException e) {
        return ResponseEntity
                .status(e.getCustomErrorCode().getHttpStatus())
                .body(new ResponseMessage<>(
                        e.getCustomErrorCode().getHttpStatus(),
                        e.getCustomErrorCode().getMessage(),
                        null
                ));
    }

    public static <T> ResponseEntity<ResponseMessage> success(HttpStatus status, String message, T data) {
        return ResponseEntity
                .status(status)
                .body(new ResponseMessage<>(
                        status,
                        message,
                        data
                ));
    }
}

3. RuntimeException을 상속받아 커스텀화 해준 클래스

package org.example.exception;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public class CustomException extends RuntimeException {
    private final CustomErrorCode customErrorCode;

}

4. 커스텀화 한 클래스 및 다른 Exception들의 Handler 클래스

package org.example.exception;

import feign.FeignException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@Slf4j
@RestControllerAdvice // CustomException 발생 시, 프런트로 보낼 ErrorDTO 를 생성하고, ErrorDTO 를 전달하는 handler
public class CustomExceptionHandler {

    @ExceptionHandler(value = CustomException.class)
    public ResponseEntity<ResponseMessage> handleCustomException(CustomException e) {
        // 에러에 대한 후처리
        log.error("[handleCustomException] {} : {}", e.getCustomErrorCode().name(), e.getCustomErrorCode().getMessage());
        return ResponseMessage.error(e);
    }

    // HttpRequestMethodNotSupportedException 처리
    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    public ResponseEntity<ResponseMessage> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e) {
        log.error("[handleHttpRequestMethodNotSupported] {}", e.getMessage());
        return ResponseEntity
                .status(HttpStatus.BAD_REQUEST)
                .body(new ResponseMessage<>(
                        HttpStatus.BAD_REQUEST,
                        CustomErrorCode.NOT_SUPPORTED_HTTP_METHOD.getMessage(),
                        null
                ));
    }

    // MethodArgumentNotValidException 처리
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ResponseEntity<ResponseMessage> handleMethodArgumentNotValid(MethodArgumentNotValidException e) {
        log.error("[handleMethodArgumentNotValid] {}", e.getMessage());
        return ResponseEntity
                .status(HttpStatus.BAD_REQUEST)
                .body(new ResponseMessage<>(
                        HttpStatus.BAD_REQUEST,
                        CustomErrorCode.NOT_VALID_METHOD_ARGUMENT.getMessage(),
                        null
                ));
    }

    // 전역 예외 처리 (기타)
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ResponseMessage> handleGeneralException(Exception e) {
        log.error("[handleGeneralException] {}", e.getMessage(), e);
        return ResponseEntity
                .status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ResponseMessage<>(
                        HttpStatus.INTERNAL_SERVER_ERROR,
                        CustomErrorCode.INTERNAL_SERVER_ERROR.getMessage(),
                        null
                ));
    }
}

 

 

참고 : 

https://mangkyu.tistory.com/204

https://veneas.tistory.com/entry/Java-%EC%BB%A4%EC%8A%A4%ED%85%80-%EC%98%88%EC%99%B8-%EB%A7%8C%EB%93%A4%EA%B8%B0Custom-Exception

'Spring' 카테고리의 다른 글

필터와 인터셉터  (0) 2025.02.07
ArgumentResolver  (0) 2025.01.19
디버깅 모드  (0) 2025.01.19
FeignClient  (1) 2025.01.19
멀티 모듈 (Multi-Module)  (0) 2025.01.17

1. 필터 

- 스프링 외부의 서블릿에서 제공하는 공통처리 기능

- 스프링 내로 요청이 들어오기 전과 스프링의 요청이 나갈 때 처리 가능 

- 조금 더 low level 처리 가능

 

1-2. 필터 흐름 : HTTP 요청 > WAS > 필터 > 서블릿(스프링의 디스패쳐 서블릿) > 컨트롤러

- 적절하지 않은 요청인 경우 필터는 서블릿 호츨 X

 

1-3. 

필터 인터페이스를 구현하고 등록하면 서블릿 컨테이너가 필터를 싱글톤 객체로 생성하고 관리

- init() : 필터 초기화 메서드, 서블릿 컨테이너가 생성될 때 호출

- doFilter() : 고객의 요청이 올 때마다 해당 메서드 호출, 필터의 로직을 구현하면 된다

- destroy() : 필터 종료 메서드. 서블릿 컨테이너가 종료될 때 호출 

 

2. 인터셉터

- 스프링MVC 에서 제공하는 공통처리 기능 

- 실제 매핑된 handler 정보 확인 가능 (어떤 것이 실제 내 요청 처리하는지 확인 가능)

- 조금 더 상세한 조건식과 세부적인 스펙(post, pre, after) 를 통해 구체적인 시점에 구체적인 동작 가능

- AOP 와 비교한다면 AOP 는 인터셉터보다 더 구체적인 조건 (어노테이션, 파라미터, 주소 등) 과 동작 위치 (afterThrowing 등) 을 갖음

 

2-1. 인터셉터 흐름 : HTTP 요청 > WAS > 필터 > 서블릿 > 스프링 인터셉터 > 컨트롤러

- 스프링 인터셉터는 디스패쳐 서블릿과 컨트롤러 사이에서 컨트롤러 호출 직전에 호출

- 스프링 MVC가 제공하는 기능이기 때문에 결국 디스패쳐 서블릿 이후에 등장

(스프링 MVC 의 시작점 = 디스패쳐 서블릿)

- 인터셉터의 URL 패턴은 서블릿의 URL 패턴과 달리 매우 정밀함

- 적절하지 않은 요청인 경우 인터셉터는 컨트롤러 호출 X

예시. 인터셉터 체인

ex. 로그를 남기는 인터셉터 1 > 로그인 여부를 체크하는 인터셉터 2 

 

2-2. HandlerInterceptor 를 구현 (implements)

- 호출 전 / preHandle() :

- 호출 후 / postHandle() : 컨트롤러 예외 발생시 호출 X

- 요청 완료 이후 / afterHandle() : 항상 호출, 예외랑 무관하게 공통처리시 사용

 

더보기

* 서블릿 필터의 경우 단순하게 doFilter() 하나만 제공

* 서블릿 필터의 경우 단순히 request, response 만 제공했지만,

인터셉터는 어떤 컨트롤러(handler)가 호출되는지 , 어떤 (modelAndView) 가 변환되는지 응답 정보도 받을 수 있다.

 

참고 : https://mangkyu.tistory.com/173

'Spring' 카테고리의 다른 글

CustomException  (0) 2025.02.07
ArgumentResolver  (0) 2025.01.19
디버깅 모드  (0) 2025.01.19
FeignClient  (1) 2025.01.19
멀티 모듈 (Multi-Module)  (0) 2025.01.17

1. 핵심 개념

 Spring MVC에서 HTTP 요청을 처리할 때, 요청의 파라미터를 메서드 인자로 변환하는 역할
 일반적으로 컨트롤러 메서드에서 요청 파라미터를 처리하기 위해 사용
 HandlerMethodArgumentResolver를 확장하여 구현하며, 이를 통해 커스텀 인자 변환을 처리

* HandlerMethodArgumentResolver: 
Spring MVC의 @RequestMapping 메서드나 기타 핸들러 메서드의 매개변수를 자동으로 변환하는 인터페이스

2. 동작 원리

더보기

사용자가 웹 브라우저를 통해 요청하면 DispatcherServlet이 이를 받음

> DispatcherServlet은 해당 요청에 맞는 URI를 HandlerMapping에서 검색

> 이 때, RequestMapping으로 구현한 API를 찾게 되는데, 이들은 RequestMappingHandlerAdapter가 모두 가지고 있음

> 원하는 Mapping을 찾은 경우, 첫 번째로 Intercepter를 처리

> Argument Resolver 처리

> Message Converter 처리

> Controller Method Invoke

1.	클라이언트 요청: 
	클라이언트가 HTTP 요청을 보내면, Spring MVC는 요청 파라미터를 컨트롤러 메서드의 인자로 변환준비
2.	ArgumentResolver의 역할: 
	컨트롤러 메서드의 매개변수에 맞는 값을 찾고, 이를 해당 타입으로 변환
    예를 들어, @RequestParam이나 @PathVariable로 요청 파라미터를 전달받는 것처럼, 
    ArgumentResolver는 파라미터에 적합한 값을 동적으로 설정
3.	컨트롤러 메서드 실행: 
	매개변수가 해결되면, Spring MVC는 이를 컨트롤러 메서드에 전달하고, 해당 메서드를 실행

3. 핸들러 메서드 인자 처리 방식

기본적으로 Spring은 여러 종류의 인자 변환을 지원하지만, 
특정 요구 사항에 맞는 사용자 정의 변환이 필요하다면 커스텀 ArgumentResolver를 구현하여 사용

* (참고)기본 ArgumentResolver

	•	@RequestParam: URL 쿼리 파라미터를 메서드 인자로 변환
	•	@PathVariable: URI 경로에서 변수를 추출하여 메서드 인자로 변환
	•	@RequestBody: HTTP 요청 본문을 객체로 변환 (예: JSON을 POJO로 변환)
	•	@ModelAttribute: 모델 객체를 생성하여 요청 데이터를 바인딩

4. 커스텀 ArgumentResolver 구현 예

@Component
public class CustomArgumentResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        // 특정 파라미터 타입에 대해서만 이 리졸버가 동작하도록 설정
        return parameter.getParameterType().equals(Long.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        // HTTP 요청에서 헤더 "X-User-Id"를 가져와 Long 타입으로 반환
        String userId = webRequest.getHeader("X-User-Id");
        return userId != null ? Long.parseLong(userId) : null;
    }
}

5. ArgumentResolver 등록

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private CustomArgumentResolver customArgumentResolver;

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(customArgumentResolver);  // 커스텀 ArgumentResolver 등록
    }
}

6. 사용 예시

@RestController
public class UserController {

    @GetMapping("/user")
    public String getUser(@RequestHeader("X-User-Id") Long userId) {
        return "User ID: " + userId;
    }
}

7. 장점과 활용

유연성: 
특정 데이터 변환 규칙에 맞게 요청 데이터를 처리할 수 있어 유연성이 높아짐

재사용성: 
복잡한 파라미터 변환 로직을 여러 컨트롤러에서 재사용 가능

가독성: 
코드의 가독성을 높이고, 중복을 줄이는 데 유리

 

 

참고 : 

더보기

* Interceptor와 ArgumentResolver의 차이
ArgumentResolver는 인터셉터 이후에 동작을 하며, 
어떠한 요청이 컨트롤러에 들어왔을 때, 
요청에 들어온 값으로부터 원하는 객체를 반환하기위해 사용한다. 
반면에 인터셉터는 실제 컨트롤러가 실행되기 전에 요청을 가로채며 특정 객체를 반환할 수 없고 
오직 boolean 혹은 void 반환 타입만 존재한다. 
하지만 파라미터로 받는 객체의 값을 변환하여 컨트롤러에 데이터를 전달할 수는 있다.
 
Request로부터 특정 객체를 추출하는 작업은 ArgumentResolver에서 수행하고
Interceptor는 인증/인가, 로깅 등의 본인만이 할 수 있는 작업을 진행하는 것이 가장 좋다

https://seongwon.dev/Spring-MVC/20220629-ArgumentResolver%EB%9E%80/

'Spring' 카테고리의 다른 글

CustomException  (0) 2025.02.07
필터와 인터셉터  (0) 2025.02.07
디버깅 모드  (0) 2025.01.19
FeignClient  (1) 2025.01.19
멀티 모듈 (Multi-Module)  (0) 2025.01.17

주요 디버깅명령어

 

1. Step Over

기능: 
현재 break 된 파일에서 다음 라인 이동 
break 걸린 라인을 전부 실행 후, 다음라인으로 이동

현재 실행 중인 라인의 코드가 함수 호출을 포함할 경우, 
해당 함수의 내부로 들어가지 않고 함수 호출을 “건너뛰어서” 실행 
함수가 호출되면 함수가 끝날 때까지 기다리지 않고, 그 다음 코드 라인으로 넘어감

사용 예: 
함수 내부를 디버깅할 필요가 없을 때 사용
코드 흐름을 빠르게 따라가되, 내부 동작을 신경 쓰지 않으려는 경우 유용

2. Step Into

기능:
현재 break 된 라인에서 실행하고 있는 라인으로 이동
 
현재 실행 중인 코드 라인이 함수 호출을 포함할 경우, 
그 함수 내부로 들어가서 함수 내에서 실행되는 각 라인도 추적
즉, 함수의 내부를 디버깅할 때 사용

사용 예: 
함수 내부에서 문제가 발생하는지 확인하고 싶을 때 사용
함수 내부 로직까지 상세히 살펴보고 싶을 때 유용

3. Resume Program

기능:  
다음 break point로 이동
첫번째 break point에서 다음 break point로 이동

 

참고 : 

https://jojoldu.tistory.com/149

 

'Spring' 카테고리의 다른 글

필터와 인터셉터  (0) 2025.02.07
ArgumentResolver  (0) 2025.01.19
FeignClient  (1) 2025.01.19
멀티 모듈 (Multi-Module)  (0) 2025.01.17
API(application programming interface), RestAPI  (0) 2023.05.22

1. FeignClient란 ? 

Spring Cloud에서 제공하는 선언적 HTTP 클라이언트

Netflix에서 간단하게 HTTP Client를 사용하기 위해 개발한 기술
RestTemplate, WebClient를 쓸 때보다 훨신 가독성있고 편하게 사용 가능 
HTTP 기반의 외부 서비스와 통신하기 위한 REST 클라이언트를 간단하게 생성할 수 있도록 도와주는 라이브러리

* WebClient : 
Spring webflux의 라이브러리, non-blocking 방식으로 동작 (대용량 트래픽)

2. FeignClient의 주요 특징

1. 선언적 API 호출: 
FeignClient는 HTTP 요청을 메서드 인터페이스로 선언할 수 있어, 
HTTP 요청을 직접 만드는 코드나 RestTemplate을 사용하는 것보다 
코드가 간결하고 읽기 쉬운 방식으로 API를 호출 가능

2. 자동 retry 및 로드 밸런싱: 
Spring Cloud Feign은 Ribbon과 통합되어 자동으로 로드 밸런싱을 제공하며, 
Hystrix와 결합해 장애 처리 및 retry 메커니즘을 지원

3. 템플릿 기반 요청: 
@FeignClient 인터페이스에서 메서드를 선언하고, 이를 기반으로 HTTP 요청을 템플릿 방식으로 처리

4. 유연한 커스터마이징: 
각종 인터셉터나 오류 처리 메커니즘을 쉽게 추가하여 API 호출 로직을 커스터마이징 가능

3. 기본 사용법

더보기

1. 의존성추가 : 

Spring Cloud OpenFeign

 

2. OpenFeign 관련 컴포넌트 스캔 활성화 : 

@EnableFeignClients 또는 configration 파일 지정된 패키지에서 Feign 클라이언트 인터페이스를 스캔하고, 해당 인터페이스에 대한 구현체를 생성

 

3. FeignClient 구현 (인터페이스 작성) :

구현체는 크게 Feign의 Default, ApacheHttpClient, OkHttpClient

ApacheHttpClient와 OkHttpClient는 추가적인 의존성을 주입해줘야 사용가능

feign.Client.Default는 Feign에서 기본으로 제공, 의존성 주입 없이 사용가능

Default는 내부적으로 java.net의 HttpUrlConnection을 사용, 가볍고 빠르다는 장점

ApacheHttpClient와 OkHttpClient는 Default 구현체보다 설정할 수 있는 값들이 더 많고, 더 편리한 api들을 제공

 

4. dto, controller 등 작성

3-1. FeignClient 인터페이스 정의

@FeignClient(name = "user-service")
public interface UserServiceClient {

    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") Long id);

    @PostMapping("/users")
    User createUser(@RequestBody User user);
}

3-2. FeignClient 호출

@Service
public class UserService {

    @Autowired
    private UserServiceClient userServiceClient;

    public User getUser(Long id) {
        return userServiceClient.getUser(id);
    }

    public User createUser(User user) {
        return userServiceClient.createUser(user);
    }
}

4. 추가 기능 (errorrecoder, decoder , interceptor, retry)

4-1. RequestInterceptor

Feign 요청을 가로채서 수정하거나, 공통 헤더 , 로깅을 추가하는 등의 작업을 할 수 있습니다.
RequestInterceptor를 사용하여 요청을 인터셉트할 수 있습니다.

* RequestIntercepor : @interface, @Override apply 


@Bean
public RequestInterceptor requestInterceptor() {
    return new RequestInterceptor() {
        @Override
        public void apply(RequestTemplate template) {
            // 헤더에 인증 토큰 추가
            template.header("Authorization", "Bearer " + token);
        }
    };
}

@FeignClient(name = "user-service", configuration = FeignConfig.class)
public interface UserServiceClient {
    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") Long id);
}

4-2. ErrorDecoder

Feign 클라이언트를 통해 요청을 보냈을 때 HTTP 응답 코드가 실패한 경우에 처리할 로직을 정의하는 데 사용 
spring cloud openfeign은 ErrorDecoder를 통해 응답값이 200이 아닐 경우 에러 
400, 404, 500 등의 오류가 발생하면 FeignException을 던지고, 이는 기본적으로 5xx 예외로 처리

public class MyErrorDecoder implements ErrorDecoder {
    @Override
    public Exception decode(String methodKey, Response response) {
        if (response.status() == 404) {
            return new NotFoundException("Resource not found");
        } else if (response.status() == 500) {
            return new InternalServerErrorException("Internal server error");
        }
        return FeignException.errorStatus(methodKey, response);
    }
}

@FeignClient(name = "user-service", configuration = MyErrorDecoder.class)
public interface UserServiceClient {
    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") Long id);
}

4-3. Decoder

Feign 클라이언트가 서버에서 받은 응답을 객체로 변환하는 역할

 기본적으로 JSON을 Java 객체로 변환하기 위해 Jackson을 사용하지만, 
 다른 포맷(예: XML, YAML 등)을 처리하려면 Decoder를 구현하여 변환 로직을 커스터마이즈
 
 public class MyCustomDecoder implements Decoder {
    private final JacksonDecoder jacksonDecoder = new JacksonDecoder();

    @Override
    public Object decode(Response response, Type type) throws IOException {
        // 커스텀 디코딩 로직
        if (type.equals(MyCustomType.class)) {
            return customDecodeLogic(response);
        }
        return jacksonDecoder.decode(response, type); // 기본 Jackson 디코더 사용
    }
}

@Configuration
public class FeignConfig {
    @Bean
    public Decoder decoder() {
        return new MyCustomDecoder();
    }
}

@FeignClient(name = "user-service", configuration = FeignConfig.class)
public interface UserServiceClient {
    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") Long id);
}

4-4. Retryer 

Feign 클라이언트가 요청을 보냈을 때 
일시적인 오류(예: 네트워크 오류 등)가 발생하면 자동으로 재시도할 수 있게 해줌,  
재시도할 횟수와 대기 시간 등을 설정

public class MyRetryer implements Retryer {
    private int attempt = 1;
    private static final int MAX_ATTEMPTS = 3;

    @Override
    public void continueOrPropagate(RetryableException e) {
        if (attempt++ > MAX_ATTEMPTS) {
            throw e;
        }
        try {
            Thread.sleep(1000); // 재시도 간 대기 시간
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        }
    }

    @Override
    public Retryer clone() {
        return new MyRetryer();
    }
}

@Configuration
public class FeignConfig {
    @Bean
    public Retryer retryer() {
        return new MyRetryer();
    }
}

@FeignClient(name = "user-service", configuration = FeignConfig.class)
public interface UserServiceClient {
    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") Long id);
}

 

더보기

ex. RestTemplate

참고 : 

https://docs.spring.io/spring-cloud-openfeign/docs/current/reference/html/

https://techblog.woowahan.com/2630/

https://techblog.woowahan.com/2657/

https://mangkyu.tistory.com/278

https://mangkyu.tistory.com/279

'Spring' 카테고리의 다른 글

ArgumentResolver  (0) 2025.01.19
디버깅 모드  (0) 2025.01.19
멀티 모듈 (Multi-Module)  (0) 2025.01.17
API(application programming interface), RestAPI  (0) 2023.05.22
웹 동작방식, HTTP, WAS, Web Server  (0) 2023.05.21

* 모듈(Module) : 독립적으로 배포될 수 있는 코드의 단위

멀티 모듈(Multi-Module) : 코드 뭉치를 하나의 프로젝트 안에서 관리하는것

모듈별 책임을 분리하고 유지보수성과 확장성을 확보하기 위해 멀티모듈을 도입

멀티모듈의 설계 / 구조는 계층 기반으로 구성
하나의 프로젝트를 여러 개의 모듈로 나누어 관리
최상위 프로젝트(root)와  여러 개의 하위 모듈(module)로 구성

project-root/
├── module-api/
│   ├── controller/
│   ├── dto/
│   ├── resources/
│   └── build.gradle
├── module-service/
│   ├── service/
│   ├── utils/
│   └── build.gradle
├── module-domain/
│   ├── entity/
│   ├── repository/
│   └── build.gradle
├── module-core/
│   ├── conf/
│   ├── utils/
│   └── build.gradle
└── build.gradle (루트 설정)

project-root: 전체 프로젝트를 대표하는 루트 프로젝트로, 공통적인 빌드 설정을 관리
module-*: 각 모듈은 서로 다른 기능을 담당
	module-api: 컨트롤러 및 외부와의 통신을 처리
	module-service: 비즈니스 로직과 서비스 계층을 관리
	module-domain: 데이터 모델 및 데이터 접근 계층을 관리
	module-core: 공통 모듈로, 여러 모듈에서 재사용 가능한 유틸리티 및 설정 포함

 

멀티모듈의 주요 특징

1.	모듈화로 인해 코드 분리가 명확함
		각 모듈은 특정한 책임만을 가지며 서로 독립적
		결합도를 낮추고 응집도를 높이는 설계가 가능
2.	재사용성
		공통적인 로직이나 유틸리티를 module-core 같은 공통 모듈에 작성하여, 다른 모듈에서 재사용 가능
3.	빌드 및 배포 효율성
		변경 사항이 있는 모듈만 빌드하여 배포할 수 있어 빌드 시간을 단축
		Gradle이나 Maven을 사용하면 하위 모듈의 의존성과 빌드 순서를 관리 가능
4.	팀 협업 효율성
		각 팀이 서로 다른 모듈을 개발하도록 나누어 작업 가능
		충돌을 최소화하고 생산성 증가

 

멀티모듈 프로젝트의 장점

유지보수성: 각 모듈이 독립적이므로 변경 사항의 영향 범위가 작음
확장성: 새로운 기능을 추가할 때, 기존 모듈에 영향을 주지 않고 새로운 모듈로 추가 가능
재사용성: 특정 모듈을 여러 프로젝트에서 재사용 가능
의존성 관리: 각 모듈이 개별적으로 의존성을 관리하므로 필요하지 않은 의존성을 배제할 수 있음

 

경험한 어려움 및 해결 방안

경험한 어려움 및 해결 방안 
1: 의존성 관리의 어려움
module-service에서도 @Transactional을 사용하려면 spring-boot-starter-data-jpa가 필요
해결 : JPA 의존성을 추가

2. 멀티모듈 간 의존성 순환 문제 
module-core는 최대한 독립적으로 설계하고 PoJo 기반 순수 자바 클래스로 구성
단방향 의존성을 유지하여 의존성 순환 방지 

3. 멀티모듈에서 공통 설정 (Config 파일) 관리
공통 모듈의 역할을 명확하게 정리 → module-core가 비대해지지 않도록 주의

*. Config 위치
	api 로 가는 경우
		- WebMvcConfig: API 요청/응답 설정 (예: 메시지 컨버터, CORS 등)
		- SwaggerConfig: Swagger 문서화 설정
		- SecurityConfig: API 인증/인가 관련 설정 (Spring Security, OAuth)
		- RestTemplateConfig: 외부 API 호출을 위한 RestTemplate 설정
	core 로 가는 경우 
		- LoggingConfig: 로깅 설정
		- GlobalExceptionHandler: 전역 예외 처리
		- CommonConstants: 프로젝트 전반에서 사용하는 상수들
		- EncryptionConfig: 암호화 관련 공통 설정
  그 외 
		- feign : service 또는 (특정 API 모듈에서만 사용된다면) api 
		- Redis  : 	캐싱 또는 비즈니스 로직과 관련(service), 또는 core
		- JPA Config (Audit 등) : domain

 

 


 

멀티 모듈 적용

1. 모듈단위로 잘게 쪼개서 사용하고 싶어서 사용 (재활용) 

2. api / consumer(kafka) / batch  > service > domain > common
	- 엔트리포인트(=접근하는 컨트롤러) 부터 시작
    - core(=common)에는 어떤 엔트리포인트에도 문제없는(=특정기술에 종속 X) 순수한 포조객체 , Utils 메소드
    - domain에는 POJO(plain old Java Object), pojo + entity = jpa entity
    - 항상 단방향 ex. service 모듈 에서 common implement

 

멀티 모듈 회고

1. Api 모듈
	- api 모듈은 프로젝트의 엔트리 포인트
	- 외부로부터의 요청을 처리하는 컨트롤러와 데이터 전달을 위한 객체인 DTO(Data Transfer Object) 포함
    - 그 외 AOP, 공통 설정, 예외 처리 등을 포함 
    - 최상위 계층으로 외부와의 직접적인 인터페이스 역할을 하며, 모든 하위 모듈을 참조할 수 있는 구조로 설계
    - API의 단순히 요청을 라우팅하고 데이터를 가공하는 역할에 집중해야 한다고 생각
    - 그 외 추가적으로 배치, 컨슈머와 같은 다른 엔트리 포인트와도 구조적으로 통일성을 유지

2. Service 
	- 핵심 비즈니스 로직을 처리하고 데이터의 흐름을 제어하는 중간 계층
    - Domain 모듈과 협력하여 데이터 조작 및 검증을 처리하며, API 모듈로부터 요청을 전달받아 로직을 수행
    - 단방향 의존성을 유지하면서 Core 및 Domain 모듈만 참조
    - VO(Value Object) 비즈니스 로직과 관련된 값 객체를 포함 


3. Domain 모듈
	- 프로젝트의 핵심 데이터를 정의하고, 데이터 접근 계층을 처리하는 중요한 역할
	- POJO 기반의 엔티티와 JPA를 활용한 레포지토리 계층으로 구성
    - 특정 비즈니스 로직이 없는 순수한 데이터 계층으로 유지
    - module-core만 참조하도록 설계하여, 특정 비즈니스 로직이 없는 순수한 데이터 계층으로 유지
    - 다른 모듈에서 도메인 객체를 재사용할 수 있도록 돕고, 데이터 계층과 비즈니스 로직 간의 결합도를 낮춤
    - JPA 엔티티와 레포지토리를 포함하여 특정 기술 스택(JPA)에 종속적일 수 있음

4. Core 모듈
	- 공통적으로 사용되는 유틸리티와 설정을 모아둔 가장 하위 계층
    - 특정 기술 스택에 종속되지 않고, 
    배치 작업이나 다른 엔트리 포인트에서도 독립적으로 활용될 수 있도록 POJO 기반의 순수한 자바 클래스로 구성
    - 모든 모듈에서 재사용 가능한 코드를 포함하며, JPA와 같은 기술 의존성을 철저히 배제
    - 기술 변경이나 새로운 기능 추가 시에도 유연하게 대응할 수 있도록 설계
    - ex. 공통 예외 처리나 유틸 메서드처럼 어디서나 필요한 기능

5. Config 위치
	api 로 가는 경우
		- WebMvcConfig: API 요청/응답 설정 (예: 메시지 컨버터, CORS 등)
		- SwaggerConfig: Swagger 문서화 설정
		- SecurityConfig: API 인증/인가 관련 설정 (Spring Security, OAuth)
		- RestTemplateConfig: 외부 API 호출을 위한 RestTemplate 설정
	core 로 가는 경우 
		- LoggingConfig: 로깅 설정
		- GlobalExceptionHandler: 전역 예외 처리
		- CommonConstants: 프로젝트 전반에서 사용하는 상수들
		- EncryptionConfig: 암호화 관련 공통 설정

5. 그 외 
	feign : service 또는 (특정 API 모듈에서만 사용된다면) api 
	Redis  : 	캐싱 또는 비즈니스 로직과 관련(service), 또는 core
	JPA Config (Audit 등) : domain

 

참고 : 

https://www.youtube.com/watch?v=ipDzLJK-7Kc

https://www.youtube.com/watch?v=uvG-amw2u2s

https://www.youtube.com/watch?v=nH382BcycHc

https://techblog.woowahan.com/2637/

https://jojoldu.tistory.com/123

https://mangkyu.tistory.com/304

 

더보기

# 전체 빌드 (test 제외)

./gradlew build --stacktrace --info -x test

# 특정 모듈 빌드 # main 없는 경우 (common, domain, infra)

./gradlew :{project-name}-domain:build

# main 있는 경우 (api)

./gradlew :{project-name}-domain:bootJar

 

bootJar : dependecies와 클래스 파일을 모두 묶어서 빌드

jar : 클래스만 묶어서 빌드

 

 

 

'Spring' 카테고리의 다른 글

디버깅 모드  (0) 2025.01.19
FeignClient  (1) 2025.01.19
API(application programming interface), RestAPI  (0) 2023.05.22
웹 동작방식, HTTP, WAS, Web Server  (0) 2023.05.21
SOLID 원칙  (0) 2023.04.07

API(application programming interface)란? 

서버의 창구, 웹 API는 클라이언트와 웹 리소스 사이의 게이트웨이라고 생각할 수 있습니다.

다른 소프트웨어 시스템과 통신하기 위해 따라야 하는 규칙을 정의합니다. 개발자는 다른 애플리케이션이 프로그래밍 방식으로 애플리케이션과 통신할 수 있도록 API를 표시하거나 생성합니다.

하나의 "약속" 이자, 서로 다른 어플리케이션 간에 약속한 방식으로 요청을 하면 정해진 결과물, 즉 요청을 받아 응답을 돌려주는 식당의 점원

더보기

인터페이스(interface)는 서로 다른 두 개의 시스템, 장치 사이에서 정보나 신호를 주고받는 경우의 접점이나 경계면이다. 즉, 사용자가 기기를 쉽게 동작시키는데 도움을 주는 시스템을 의미한다. 컴퓨팅에서 컴퓨팅 시스템끼리 정보를 교환하는 공유 경계이다. 이러한 교환은 소프트웨어, 컴퓨터 하드웨어, 주변기기, 사람간에 이루어질 수 있으며, 서로 복합적으로 이루어질 수도 있다.

 한 소프트웨어 애플리케이션(또는 시스템)에서 다른 애플리케이션과 상호작용하는데 사용하는 규약 또는 메커니즘을 의미합니다.

API는 애플리케이션과 서비스 간에 데이터를 교환하고 상호 작용하게 할 수 있는 일련의 함수, 메서드, 규약, 프로토콜을 정의합니다. API를 통해, 개발자들은 다른 애플리케이션의 기능을 활용하거나 운영체제, 데이터베이스, 하드웨어와 같은 저수준 자원에 접근할 수 있습니다.

API는 다양한 종류와 형태로 존재합니다:

  1. 웹 API: HTTP 프로토콜을 통해 서버와 클라이언트 간의 통신을 가능하게 하는 API입니다. RESTful API, GraphQL API 등이 이에 속합니다.
  2. 운영체제 API: 운영체제에서 제공하는 기능에 접근하는데 사용되는 API입니다. 예를 들어, 파일 시스템에 접근하거나 새 프로세스를 생성하는 등의 작업을 수행합니다.
  3. 라이브러리/프레임워크 API: 특정 프로그래밍 언어나 소프트웨어 프레임워크가 제공하는 기능에 접근하는 API입니다. 예를 들어, Java의 Swing API는 그래픽 사용자 인터페이스 구성 요소를 만들기 위해 사용됩니다.
  4. 하드웨어 API: 특정 하드웨어 장치의 기능에 접근하는데 사용되는 API입니다. 예를 들어, GPU의 기능을 활용하기 위한 API인 OpenGL이 있습니다.

이처럼, API 다양한 소프트웨어 구성 요소들이 서로 상호 작용하고 통신하는데 있어 중요한 역할을 합니다. API 없이는 각각의 소프트웨어가 어떻게 통신하고 상호 작용해야 하는지를 개발자가 직접 구현해야 하므로 개발 과정이 복잡해지고 시간이 많이 소요될 있습니다.

 

RESTful API(Representational State Transfer)란? 

웹 서비스의 아키텍처 스타일 중 하나입니다. REST는 자원(resource)을 이름(자원의 표현)으로 구분하여 해당 자원의 상태(정보)를 주고 받는 모든 것을 의미하며, 이는 웹의 장점을 최대한 활용할 수 있는 아키텍처 스타일입니다.

RESTful API는 HTTP 기반으로 필요한 자원에 접근하는 방식을 정의한 인터페이스를 의미합니다. 이 방식은 HTTP의 메소드인 GET, POST, PUT, DELETE 등을 이용하여 CRUD(Create, Read, Update, Delete) 연산을 수행합니다.
RESTful API는 웹 서비스를 구축하는 데 널리 사용되며, 주로 HTTP 메서드(GET, POST, PUT, DELETE 등)를 사용하여 리소스에 접근합니다. 이러한 API는 JSON, XML 등의 형식으로 데이터를 교환

RESTful API의 주요 특징은 다음과 같습니다:

  1. Stateless: 각 요청 간 클라이언트의 컨텍스트가 서버에 저장되지 않습니다. 즉, 각 요청은 독립적이며 서버는 이전 요청을 기억하지 않습니다.
    각 요청은 서버에서 클라이언트의 상태를 변경하는 데 필요한 모든 정보를 포함해야 합니다. 이는 서버가 클라이언트의 상태를 기억할 필요가 없다는 것을 의미하며, 이로 인해 서버의 확장성이 향상
  2. Client-Server: 클라이언트와 서버는 서로 독립적이며 서로의 구현 내용을 알 필요가 없습니다.
    인터페이스가 일관되게 유지되는 한 클라이언트와 서버의 구현이 독립적으로 변경될 수 있다는 것을 의미
  3. Cacheable: 클라이언트는 응답을 캐싱할 수 있어야 합니다. 즉, 재사용 가능한 응답은 캐시 가능함을 명시해야 합니다.
  4. Uniform Interface: API는 일관적인 인터페이스를 가져야 합니다. 이를 통해 API의 단순성과 사용성이 증가하고, 코드의 가독성도 높아집니다.
  5. Layered System: 클라이언트는 실제 서버가 직접 연결된 서버인지, 중간 서버인지 알 수 없습니다. 중간 서버를 사용할 경우 보안, 로드 밸런싱, 공유 캐시 등을 제공할 수 있습니다.
  6. Code-On-Demand (optional): 서버는 클라이언트에게 스크립트를 보내서 기능을 확장할 수 있습니다. 이는 선택적 특성입니다.
더보기

RESTful API는 웹사이트들이 서로 '대화'하는 방법 중 하나입니다. 예를 들어, 웹사이트에 로그인하거나 새로운 게시물을 올릴 때, 그 웹사이트는 보통 RESTful API를 통해 서버와 정보를 주고받습니다.

RESTful API는 우편 배달부와 비슷하게 작동합니다. 웹사이트(또는 다른 종류의 애플리케이션)는 특정 정보를 요청하거나 전달하려면 '편지'(즉, 데이터)를 작성하고, RESTful API는 그 '편지'를 목적지인 서버에 전달합니다. 그런 다음 서버는 요청을 처리하고 필요한 정보가 담긴 '편지'를 다시 API를 통해 웹사이트에 전달합니다.

이런 방식으로, 웹사이트와 서버는 서로 정보를 주고받을 있으며, 과정을 통해 웹사이트는 최신 정보를 유지하고 사용자가 원하는 작업을 수행할 있게 됩니다.

 

"API"는 보통 "Application Programming Interface"의 약자로, 소프트웨어에서 다른 소프트웨어와 통신하도록 설계된 규약이나 도구 모음을 일반적으로 가리킵니다. API는 매우 광범위하며, 다양한 유형과 형태가 있습니다.

한편, "RESTful API"는 특정한 종류의 API입니다. RESTful API는 "REST"(Representational State Transfer)라는 아키텍처 스타일을 따르며, 이는 상태를 가지지 않는(stateless) 통신과 클라이언트-서버 모델, 그리고 일관된 인터페이스 등의 원칙에 기반을 둡니다.

RESTful API는 일반적으로 웹 서비스에서 데이터를 주고받는데 사용되며, 이는 대개 HTTP(Hypertext Transfer Protocol)를 통해 이루어집니다.

요약하면, "API" 일반적인 개념이며, "RESTful API" 그것의 특정한 형태 또는 예시입니다. 따라서 모든 RESTful API API이지만, 모든 API RESTful 것은 아닙니다. RESTful 이외의 API로는 SOAP, GraphQL 등이 있습니다.

 

https://aws.amazon.com/ko/what-is/restful-api/

 

 

 

 

 

 

'Spring' 카테고리의 다른 글

디버깅 모드  (0) 2025.01.19
FeignClient  (1) 2025.01.19
멀티 모듈 (Multi-Module)  (0) 2025.01.17
웹 동작방식, HTTP, WAS, Web Server  (0) 2023.05.21
SOLID 원칙  (0) 2023.04.07

1. IP 주소란 ? 

거대한 네트워크망에서 사용자의 컴퓨터를 식별하기 위한 위치 주소, 네트워크라는 공간에서 컴퓨터의 집주소

네트워크상에서의 데이터 송/수신의 기준 

 

2. 브라우저란 ? 

크롬, 사파리, 엣지와 같이 웹페이지, 이미지, 비디오등의 컨텐츠를 송/수신하고 표현해주는 소프트웨어

 

3. DNS 란 ? 

Domain Name Server, 서버의 IP주소와 도메인 이름을 중개해주는 전화번호부와 같은 서버

 

4. HTTP(HyperText Transfer Protocol)란?

메세지 송신자와 수신자가 공유하고 있는 “약속(Protocol)”, 웹 상에서는 HTTP 라는 프로토콜을 통해서 데이터를 송/수신

  1. 데이터를 주고 받는 양식을 정의한 "통신 규약"중 하나
  2. 범용적인 양식을 가지고 있어 전 세계에서 제일 널리 쓰이는 통신 규약(컴퓨터끼리 데이터를 주고 받을때 정해둔 약속)
  3. HTTP에서는 언제나 Request, Response라는 개념이 존재
    • 브라우저는 서버에게 자신이 원하는 페이지(URL 등의 정보)를 요구(Request)합니다.
    • 서버는 브라우저가 원하는 페이지가 있는지 확인하고, 있다면 해당 페이지에 대한 데이터를 실어 응답(Response)해줍니다. 없다면 없는 페이지에 대한 데이터를 반환합니다.
    • 브라우저는 서버에게 전달 받은 데이터를 기반으로 브라우저에 그려줍니다.
  4. HTTP의 구성 요소
    • Method (호출/요청 방식)
      • GET: 이름 그대로 어떤 리소스를 얻을 때 사용됩니다. 브라우저의 주소창에 URL을 입력하면 GET 메서드를 사용해서 서버에 요청을 보냅니다.
      • POST: 웹 서버에 데이터를 게시할 때 사용하는게 일반적입니다. (ex. 회원가입, 게시글 작성, 댓글 작성)
    • Header (추가 데이터. 메타 데이터)
      • 브라우저가 어떤 페이지를 원하는지
      • 요청 받은 페이지를 찾았는지
      • 요청 받은 데이터를 성공적으로 찾았는지
      • 어떤 형식으로 데이터를 보낼지
    • Payload (데이터. 실제 데이터)
      • 서버가 응답을 보낼 때에는 항상 Payload를 보낼 수 있습니다.
      • 클라이언트(브라우저)가 요청을 할 때에도 Payload를 보낼 수 있습니다. 그리고 "GET method를 제외하곤 모두 Payload를 보낼 수 있다" 는게 HTTP에서의 약속입니다.

웹 서버란 ? 

  1. 인터넷을 통해 HTTP를 이용하여 웹상의 클라이언트의 요청을 응답해주는 통신을 하는 일종의 컴퓨터
  2. 오늘날 우리가 자주 사용하는 이메일이나 SNS 등 대부분의 서비스
  3. 웹 서버의 기본 동작 원리
    • 브라우저를 통해 HTTP request로 웹사이트를 웹서버에 요청합니다. 이후 웹서버는 요청을 승인하고 HTTP response를 통해 웹사이트 데이터를 브라우저에 전송합니다. 마지막으로 브라우저는 서버에서 받아온 데이터를 이용해 웹사이트를 브라우저에 그려내는 일을 합니다.
    • 기본적으로 브라우저가 웹서버에 요청을 할때는 항상 GET method로 요청하게 됩니다.

🧩 Quiz

사용자가 브라우저에 주소(URL)를 입력하면 해당 동작에 맞게 HTTP 데이터를 만들어 서버로 보내고 서버는 알맞는 응답 데이터를 브라우저(클라이언트)로 보내 이 데이터가 브라우저에 표현됩니다.

 

1. 웹 서버 (Web Server)는 무엇일까요?

  • 웹 서버(Web Server)는 HTTP를 통해 웹 브라우저에서 요청하는 HTML 문서나 각종 리소스를 전달하는 서버입니다. 대표적인 웹 서버 소프트웨어로는 Apache, Nginx, IIS 등이 있습니다.

2. 웹 서버 (Web Server)와 웹 어플리케이션 서버(WAS)는 어떤 차이점이 있을까요?

  • 웹 어플리케이션 서버(WAS, Web Application Server)는 웹 서버의 기능과 함께 동적인 서비스를 제공하기 위한 어플리케이션 서버의 기능을 모두 가지고 있는 서버입니다. 이는 DB 조회, 다양한 로직 처리 등 비즈니스 로직을 수행할 수 있습니다. 대표적으로 Tomcat, JBoss, WebSphere 등이 있습니다.
  • 웹 서버와 WAS의 가장 큰 차이는 동적인 데이터 처리 여부입니다. 웹 서버는 주로 정적인 컨텐츠를 처리하는데 최적화되어 있고, WAS는 동적인 컨텐츠를 처리하는데 적합합니다.
    더보기

    WAS Web Application Server 약어로, 애플리케이션을 실행하는 필요한 기능을 제공하는 소프트웨어입니다. WAS JSP, Servlet, EJB 등의 기술을 사용하여 동적인 페이지를 생성하고, 데이터베이스 연동, 보안, 트랜잭션 관리, 스레드 관리, 세션 관리 등의 기능을 제공합니다.
    WAS Web Server 가장 차이점은 기능적인 측면입니다. Web Server 정적인 콘텐츠(HTML, 이미지, CSS ) 제공하는 특화된 소프트웨어이며, WAS 동적인 콘텐츠( 애플리케이션) 제공하는 특화된 소프트웨어입니다.
    또한, WAS 보통 Web Server 기능을 내장하고 있으며, 대부분의 WAS 자체적으로 Web Server 기능을 처리합니다. 이러한 이유로, WAS 보다 복잡한 구성을 필요로 하며, Web Server보다 높은 성능과 안정성을 제공할 있습니다.

    따라서, Web Server WAS 기능적인 측면에서 차이가 있으며, 각각의 용도에 따라 적절한 소프트웨어를 선택하여 사용해야 합니다.

웹 서버와 WAS(Web Application Server)는 모두 클라이언트의 요청에 따라 응답을 하는 서버지만, 그들이 처리하는 작업의 유형과 복잡성에서 차이가 있습니다.

  • 웹 서버:
  • HTTP 프로토콜을 통해 클라이언트(일반적으로 웹 브라우저)로부터 요청을 받아, 정적인 컨텐츠(예: HTML 문서, 이미지, CSS, JavaScript 파일 등)를 제공합니다. 웹 서버의 주요 목표는 가능한 빠르고 효율적으로 이러한 정적 컨텐츠를 전달하는 것입니다. Apache, Nginx 등이 대표적인 웹 서버 소프트웨어입니다.
  • WAS(Web Application Server):
  • 동적 컨텐츠를 처리하고 제공하는 역할을 합니다. 클라이언트로부터 요청을 받으면, 해당 요청에 따라 비즈니스 로직을 실행하고, 결과를 생성하여 응답합니다. 이 과정은 데이터베이스 조회, 데이터 처리, 비즈니스 로직 수행 등 복잡한 작업을 포함할 수 있습니다. Java EE, ASP.NET, PHP 등의 플랫폼에서 동작하는 서버를 예로 들 수 있습니다.

기능적으로 , WAS 서버의 기능을 모두 포함하며 추가로 동적인 데이터 처리 비즈니스 로직을 수행하는 기능까지 포함하고 있습니다. 하지만 무조건 WAS 사용하는 것이 좋은 것은 아닙니다. 처리해야 요청이 정적 컨텐츠 위주인 경우, 서버가 효율적일 있습니다. 반면에, 동적 컨텐츠 처리가 많은 경우에는 WAS 사용하는 것이 적합할 있습니다. 많은 경우에 서버와 WAS 함께 사용되며, 각각의 장점을 최대한 활용하는 아키텍처를 구성합니다.

 

3. HTTP Method에서 Get과 Post의 차이점은 무엇이 있을까요?

  • GET: 클라이언트에서 서버로 데이터를 요청할 때 사용합니다. 데이터를 URL에 포함하여 전달하며, 캐싱이 가능합니다. 주로 조회를 할 때 사용합니다.
  • POST: 클라이언트에서 서버의 리소스를 생성하거나 수정하기 위해 데이터를 전송할 사용합니다. 데이터는 HTTP 메시지의 body 포함되어 전송되며, GET 비해 상대적으로 안전합니다.

4. HTTP와 HTTPS의 차이점은 무엇일까요?

  • HTTP와 HTTPS의 가장 큰 차이점은 '보안'입니다. HTTP는 HyperText Transfer Protocol의 약자로, 인터넷에서 정보를 주고받는 프로토콜입니다. 반면, HTTPS는 HTTP에 Secure Socket Layer(SSL)이라는 보안 프로토콜을 추가한 것입니다. HTTPS는 데이터를 암호화하여 전송함으로써, 데이터가 도중에 탈취되더라도 암호를 해독하지 않는 한 원본 데이터를 알 수 없도록 보호합니다.

5. WAS가 필요한 이유는 무엇인가요?

WAS는 Web Application Server의 약자로, 사용자가 웹을 통해 응용 프로그램을 실행하는 데 필요한 환경을 제공하는 미들웨어입니다. WAS는 다음과 같은 이유로 필요합니다:

  1. 동적 콘텐츠 처리: WAS는 클라이언트의 요청에 따라 동적으로 데이터를 처리하고 응답을 생성합니다. 이는 정적 웹 서버가 할 수 없는 기능으로, 사용자의 요청에 따라 콘텐츠를 실시간으로 변경하거나 사용자마다 다른 콘텐츠를 제공할 수 있습니다.
  2. 비즈니스 로직 수행: WAS는 일반적으로 데이터베이스와 연동되어 웹 응용 프로그램의 비즈니스 로직을 수행합니다. 예를 들어, 사용자가 상품을 구매하는 웹 사이트에서 WAS는 사용자의 주문 정보를 데이터베이스에 저장하고, 상품 재고를 업데이트하며, 결제를 처리하는 등의 업무를 수행할 수 있습니다.
  3. 트랜잭션 관리: WAS는 트랜잭션을 관리하여 데이터의 일관성을 유지합니다. 예를 들어, 여러 데이터베이스 작업이 하나의 트랜잭션으로 묶여야 하는 경우 WAS는 이러한 작업이 모두 성공적으로 완료되거나, 실패할 경우 모든 작업을 취소(롤백)하여 데이터의 일관성을 유지합니다.
  4. 보안 기능: WAS는 웹 응용 프로그램의 보안을 관리하는 기능을 제공합니다. 사용자 인증, 권한 부여, 데이터 암호화 등의 기능을 통해 사용자의 정보와 데이터를 보호합니다.
  5. 스케일링 및 로드 밸런싱: WAS는 응용 프로그램의 확장성을 지원하며, 다수의 클라이언트 요청을 효과적으로 처리할 수 있습니다. 또한, 여러 서버에 작업을 분산시키는 로드 밸런싱 기능도 제공합니다.
  6. 세션 관리: WAS는 사용자마다 세션을 생성하고 관리하여, 사용자별 상태 정보를 유지할 수 있습니다. 이를 통해 사용자마다 개인화된 서비스를 제공하거나 로그인 세션을 유지하는 등의 기능을 수행할 수 있습니다.

따라서, WAS는 사용자에게 동적이고, 개인화된 웹 서비스를 제공하며, 응용 프로그램의 비즈니스 로직을 수행하고, 데이터의 일관성을 유지하며, 보안을 관리하는 등의 중요한 역할을 합니다.

  1. 서비스 통합: WAS는 여러 서비스를 통합하는 데 사용될 수 있습니다. 예를 들어, 여러 웹 서비스를 하나의 플랫폼에서 실행하거나 다양한 종류의 데이터베이스 시스템과 연동할 수 있습니다.
  2. API 관리: 웹 애플리케이션 서버는 API를 통해 다른 소프트웨어와 통신하는 기능을 제공할 수 있습니다. 이는 모바일 앱, 데스크톱 앱, 또는 다른 웹 서비스와 통신하는 데 필요합니다.
  3. 장애 복구 및 백업: WAS는 장애 복구와 백업 기능을 제공하여 시스템 장애나 데이터 손실 시 복구할 수 있게 돕습니다.

이처럼 WAS 기반 애플리케이션의 효과적인 운영과 관리에 있어 필수적인 역할을 수행하며, 이러한 다양한 기능을 통해 애플리케이션의 안정성, 확장성, 그리고 효율성을 보장합니다.

 

6. 웹 서버와 WAS를 어떻게 결합하여 사용하나요? 이렇게 하는 이유는 무엇인가요?

웹 서버와 WAS(Web Application Server)를 결합하여 사용하는 구조는 보통 '웹 서버 - WAS 아키텍처'라고 부릅니다. 웹 서버는 보통 정적인 콘텐츠를 처리하고, WAS는 동적인 콘텐츠를 처리하는 역할을 담당합니다.

웹 서버와 WAS를 결합하는 과정은 대략적으로 다음과 같습니다:

  1. 사용자의 요청이 웹 서버에 먼저 도착합니다.
  2. 웹 서버는 요청을 분석하여, 정적인 콘텐츠 요청인 경우 해당 콘텐츠를 반환합니다.
  3. 만약 동적인 콘텐츠 요청인 경우, 웹 서버는 해당 요청을 WAS에 전달합니다.
  4. WAS는 요청을 처리한 후 그 결과를 웹 서버에 반환합니다.
  5. 웹 서버는 WAS로부터 받은 응답을 사용자에게 전달합니다.

이런 구조를 사용하는 이유는 아래와 같습니다:

  1. 성능 향상: 정적 콘텐츠와 동적 콘텐츠를 별도의 서버에서 처리하면 각 서버는 자신의 역할에 최적화되어 있기 때문에 전반적인 성능이 향상됩니다.
  2. 보안 강화: 웹 서버가 외부에서의 직접적인 WAS 접근을 차단함으로써 보안을 강화할 수 있습니다. 또한, 서버 간 통신에서도 보안을 적용할 수 있습니다.
  3. 유연성: 웹 서버와 WAS를 분리하면 각각을 독립적으로 업그레이드하거나 교체하는 등의 유연성을 갖게 됩니다. 서비스의 요구 사항이 변화할 때마다 적절한 서버 환경을 조성할 수 있습니다.
  4. 로드 밸런싱: 여러 대의 WAS를 사용하면 웹 서버가 로드 밸런싱을 수행하여 각 서버에 균등하게 요청을 분산시킬 수 있습니다. 이를 통해 시스템의 과부하를 방지하고 가용성을 높일 수 있습니다.

따라서, 서버와 WAS 결합하여 사용하는 것은 성능, 보안, 유연성, 그리고 로드 밸런싱 여러 가지 이점을 제공합니다.

 

7. 웹 서버만 사용하는 경우와 WAS를 추가로 사용하는 경우, 각각의 장단점은 무엇인가요?

웹 서버와 웹 서버 + WAS를 사용하는 경우는 각각 장단점이 있습니다. 여기서는 가장 일반적인 케이스에 대한 장단점을 다루겠습니다.

웹 서버만 사용하는 경우:

장점:

  1. 간단함: 웹 서버만 사용하는 경우, 시스템 구성이 단순하고 관리가 비교적 쉽습니다.
  2. 빠른 응답 시간: 웹 서버는 정적 콘텐츠를 빠르게 제공할 수 있습니다. 이는 웹 서버가 이미 생성된 콘텐츠를 곧바로 클라이언트에게 전송하기 때문입니다.
  3. 리소스 효율: 웹 서버는 동적 콘텐츠 처리에 필요한 CPU나 메모리 등의 리소스를 적게 사용합니다.

단점:

  1. 동적 콘텐츠 처리 불가: 웹 서버는 동적인 콘텐츠를 처리하는 데 제한이 있습니다. 즉, 사용자의 입력에 따라 변하는 콘텐츠를 웹 서버만으로 처리하기 어렵습니다.
  2. 비즈니스 로직 처리 불가: 웹 서버는 복잡한 비즈니스 로직을 처리하는 데 한계가 있습니다. 이를 처리하려면 추가적인 프로그래밍이 필요합니다.

웹 서버 + WAS를 사용하는 경우:

장점:

  1. 동적 콘텐츠 처리: WAS는 사용자의 요청에 따라 동적으로 웹 페이지를 생성하고, 웹 서비스에 필요한 다양한 기능을 수행할 수 있습니다.
  2. 비즈니스 로직 처리: WAS는 복잡한 비즈니스 로직을 처리하며, 데이터베이스와의 연동, 트랜잭션 관리 등을 할 수 있습니다.
  3. 세션 관리: WAS는 사용자별 세션 정보를 유지하고 관리할 수 있어 사용자에게 맞춤화된 서비스를 제공할 수 있습니다.

단점:

  1. 복잡함: 서버와 WAS 결합하여 사용하는 경우, 시스템 구성이 복잡하고, 관리와 유지보수가 어려울 있습니다.
  2. 성능 이슈: WAS 동적인 콘텐츠를 처리하면서 많은 리소스를 사용할 있습니다. 이에 따라 대량의 동적 콘텐츠 처리 성능 저하가 일어날 있습니다. 이를 위해 최적화가 필요합니다.
  3. 리소스사용량: WAS 애플리케이션 로직을 처리하는데 필요한 많은 컴퓨팅 리소스를 사용합니다. 따라서 높은 수준의 리소스 관리가 필요하며, 이는 하드웨어 비용 증가로 이어질 있습니다.

8. 정적 컨텐츠와 동적 컨텐츠의 차이점에 대해 설명해 주세요.

정적 컨텐츠(Static Content)

: 서버에 미리 저장되어 있는 파일로, 사용자의 요청에 따라 변경되지 않는 컨텐츠입니다. 예를 들어, HTML 파일, CSS 파일, 이미지 파일, JavaScript 파일 등이 정적 컨텐츠에 해당합니다. 이러한 파일들은 웹 서버에 저장되어 있고, 사용자가 웹 페이지를 요청하면 웹 서버는 해당 파일들을 그대로 반환합니다. 사용자마다 다르게 변화하지 않으며, 서버의 로직에 의해 변화하지도 않습니다.

동적 컨텐츠(Dynamic Content) 

: 사용자의 요청, 입력, 세션, 서버의 로직 등에 따라 실시간으로 변화하는 컨텐츠를 말합니다. 예를 들어, 사용자의 로그인 상태에 따라 보이는 화면이 달라지거나, 사용자가 입력한 정보에 따라 생성되는 결과 페이지, 서버의 처리 로직에 따라 생성되는 HTML 등이 동적 컨텐츠에 해당합니다. 이러한 컨텐츠는 웹 애플리케이션 서버(WAS)와 같은 서버 사이드 로직에 의해 처리되며, 데이터베이스와의 상호작용을 필요로 할 수도 있습니다.

따라서, 정적 컨텐츠는 페이지의 고정된 부분(레이아웃, 스타일 ) 담당하고, 동적 컨텐츠는 페이지의 변화하는 부분(사용자 정보, 실시간 데이터 ) 담당하는 것으로 있습니다. 둘을 적절히 조합함으로써 사용자에게 원활하고 맞춤화된 서비스를 제공할 있습니다.

 

9. 웹 서버와 WAS에서 보안은 어떻게 관리되나요?

웹 서버와 웹 애플리케이션 서버(WAS)에서의 보안 관리는 매우 중요한 이슈입니다. 다양한 보안 위협으로부터 서버와 사용자의 정보를 보호해야 하기 때문입니다. 웹 서버와 WAS에서의 보안 관리는 아래와 같은 방법들이 존재합니다:

  1. 인증 권한 관리: 사용자 인증과 권한 관리는 WAS 주요 보안 기능 하나입니다. WAS 로그인 메커니즘을 제공하여 사용자를 식별하고, 해당 사용자가 접근할 있는 자원과 기능을 제한합니다.
  2. 데이터 암호화: 서버와 WAS 데이터를 암호화하여 네트워크를 통한 정보 유출을 방지합니다. 이는 특히 민감한 정보(: 패스워드, 신용카드 정보 ) 전송할 중요합니다. 가장 대표적인 방법은 HTTPS 사용하는 것으로, 이는 SSL/TLS 프로토콜을 통해 암호화된 연결을 제공합니다.
  3. 방화벽 설정: 서버는 보안을 강화하기 위해 특정 IP 주소, 포트, 도메인 등으로부터의 접근을 제한하는 방화벽 설정을 있습니다.
  4. 입력 데이터 검증: WAS 사용자로부터의 입력을 검증하여 SQL Injection, Cross-site Scripting(XSS) 등의 공격을 방지합니다.
  5. 세션 관리: WAS 사용자의 세션 정보를 안전하게 관리하며, 이를 통해 사용자의 요청을 식별하고 접근 권한을 제어합니다. 이를 통해 세션 하이재킹 공격을 방지할 있습니다.
  6. 서버 보안 패치 업데이트: 서버와 WAS 지속적으로 발견되는 새로운 보안 취약점에 대응하기 위해 최신 상태로 유지되어야 합니다. 이를 위해 제공되는 보안 패치와 업데이트를 정기적으로 적용하는 것이 중요합니다.
  7. 오류 예외 처리: 잘못된 요청이나 예상치 못한 오류에 대한 적절한 처리도 중요한 보안 이슈입니다. 특히 에러 메시지가 너무 많은 정보를 제공하면 이를 이용한 공격의 기회를 제공할 있습니다.

10. 복잡한 웹 애플리케이션에서의 웹 서버와 WAS의 역할에 대해 어떻게 이해하고 있나요?

웹 서버의 주요 역할은 다음과 같습니다:

  1. HTTP 프로토콜 지원: 웹 서버는 HTTP 요청을 받아들이고 적절한 HTTP 응답을 반환하는 역할을 합니다. 이 과정에서 요청을 분석하고, 적절한 리소스를 찾아 응답을 구성하며, 필요에 따라 클라이언트로부터의 추가 정보를 요청하는 등의 작업을 수행합니다.
  2. 정적 컨텐츠 제공: 웹 서버는 HTML, CSS, JavaScript, 이미지 등의 정적 파일을 클라이언트에게 제공합니다. 이러한 파일은 서버에 미리 저장되어 있으며, 서버는 요청에 따라 이를 그대로 반환합니다.
  3. 로드 밸런싱: 여러 대의 WAS가 동작하는 환경에서 웹 서버는 로드 밸런서의 역할을 하여 트래픽을 균등하게 분산시킵니다. 이를 통해 서버 부하를 관리하고 전체 시스템의 성능을 최적화합니다.

**웹 애플리케이션 서버(WAS)**의 주요 역할은 다음과 같습니다:

  1. 동적 컨텐츠 제공: WAS는 사용자의 요청, 입력, 세션, 서버의 로직 등에 따라 실시간으로 변화하는 동적 컨텐츠를 제공합니다. WAS는 웹 애플리케이션의 로직을 처리하며, 이를 통해 동적으로 웹 페이지를 생성하거나 데이터를 처리합니다.
  2. 비즈니스 로직 처리: WAS는 웹 애플리케이션의 복잡한 비즈니스 로직을 처리하는 역할을 합니다. 데이터베이스와의 연동, 트랜잭션 관리, 세션 관리 등의 기능을 수행합니다.
  3. 보안 기능: WAS는 사용자 인증, 권한 관리, 데이터 암호화 등의 보안 기능을 제공합니다.

복잡한 웹 애플리케이션에서는 웹 서버와 WAS가 협력하여 사용자에게 원활하고 풍부한 웹 서비스를 제공합니다. 웹 서버는 사용자로부터의 요청을 받아들이고 기본적인 처리를 수행하며, WAS는 복잡한 웹 애플리케이션 로직과 안정적인 보안 기능을 처리하여 사용자에게 최종 결과를 반환하는 역할을 수행합니다.

웹 서버와 WAS가 협력하는 구체적인 과정은 다음과 같습니다:

  1. 사용자는 웹 브라우저를 통해 특정 URL에 접속 요청을 합니다.
  2. 웹 서버는 이 요청을 받아 분석합니다. 만약 요청이 정적 파일에 대한 것이라면, 웹 서버는 해당 파일을 찾아 바로 반환합니다.
  3. 하지만 요청이 동적 컨텐츠, 즉 서버 로직의 처리가 필요한 경우, 웹 서버는 이 요청을 WAS에게 전달합니다.
  4. WAS는 요청을 분석하고 필요한 비즈니스 로직을 처리합니다. 이 과정에서 데이터베이스와의 상호작용이 필요할 수도 있습니다.
  5. WAS는 처리 결과를 바탕으로 동적으로 웹 페이지를 생성하거나 데이터를 반환하고, 이를 웹 서버에게 전달합니다.
  6. 웹 서버는 WAS로부터 받은 응답을 사용자에게 전달합니다.

이러한 방식으로 웹 서버와 WAS는 각자의 역할을 수행하면서 웹 애플리케이션의 요구사항을 충족시키고, 사용자에게 원활하고 안전한 웹 서비스를 제공합니다.

 

11. 로드 밸런싱과 스케일링에 대해 알고 있나요? 웹 서버와 WAS에서 어떻게 적용되나요?

로드 밸런싱은 여러 대의 서버가 트래픽을 공유하도록 분산하는 기술입니다. 이는 서버에 가해지는 부하를 고르게 분산시킴으로써 시스템의 안정성을 유지하고 성능을 향상시키는 역할을 합니다. 웹 서버는 자주 로드 밸런서로서의 역할을 수행하며, 들어오는 요청을 여러 WAS에 고르게 분배합니다. 이를 통해 단일 WAS에 과도한 부하가 집중되는 것을 방지하고, 전체 시스템의 효율을 최적화합니다.

스케일링은 시스템의 처리 능력을 증가시키는 방법을 말하며, 크게 수평 스케일링(Horizontal Scaling, Scale Out)과 수직 스케일링(Vertical Scaling, Scale Up)으로 구분할 수 있습니다.

  1. 수평 스케일링: 시스템의 처리 능력을 증가시키기 위해 동일한 구성의 서버를 추가로 배치하는 방법입니다. 예를 들어, 웹 서버나 WAS를 추가하여 시스템을 확장할 수 있습니다. 이는 로드 밸런싱과 밀접한 관련이 있습니다. 추가된 서버 간의 트래픽 분산이 필요하기 때문에, 이때 로드 밸런서가 중요한 역할을 합니다.
  2. 수직 스케일링: 시스템의 처리 능력을 증가시키기 위해 기존 서버의 하드웨어 성능(예: CPU, RAM 등)을 향상시키는 방법입니다. 이는 간단하게 시스템의 처리 능력을 향상시킬 수 있지만, 하드웨어의 향상에는 한계가 있으며, 비용이 많이 들 수도 있습니다.

웹 서버와 WAS에서는 이러한 스케일링 방법을 적절히 조합하여 사용합니다. 예를 들어, 일정 수준까지는 수직 스케일링을 통해 서버의 성능을 향상시킬 수 있지만, 이후에는 수평 스케일링을 통해 여러 서버에 트래픽을 분산시키는 방법을 선택할 수 있습니다. 이를 통해 시스템의 안정성을 유지하면서도 효율적으로 처리 능력을 확장할수 있습니다.

특히, 클라우드 환경에서는 이러한 스케일링과 로드 밸런싱이 더욱 중요합니다. 클라우드 서비스는 일반적으로 자원을 유연하게 할당하고 조정할 수 있어, 시스템의 부하에 따라 동적으로 서버를 추가하거나 제거하는 오토 스케일링 기능을 제공합니다. 또한, 클라우드 서비스 제공자는 고급 로드 밸런싱 기능을 제공하여, 복잡한 분산 환경에서도 트래픽을 효과적으로 관리할 수 있게 합니다.

한편, 이러한 로드 밸런싱과 스케일링 기술을 적용할 때는 세션 관리, 데이터 일관성, 서버 간의 상태 동기화 등의 추가적인 고려사항이 생길 수 있습니다. 예를 들어, 여러 WAS가 동시에 동작하는 환경에서는 세션 정보를 공유하거나 동기화해야 하는 경우가 있을 수 있습니다. 이를 위해 세션 클러스터링, 스티키 세션, 세션 스토어 등의 기술을 사용할 수 있습니다.

결과적으로, 웹 서버와 WAS에서 로드 밸런싱과 스케일링은 시스템의 성능, 안정성, 확장성을 보장하는 핵심적인 역할을 수행합니다. 이를 통해 웹 애플리케이션은 다양한 환경과 요구 사항에 유연하게 대응하고, 사용자에게 안정적이고 빠른 서비스를 제공할 수 있습니다.

 

12. Nginx나 Apache 같은 웹 서버 소프트웨어에 대해 알고 있나요? 이들의 특징은 무엇인가요?

Nginx와 Apache는 가장 널리 사용되는 웹 서버 소프트웨어입니다.

Apache HTTP Server (이하 Apache)는 세계에서 가장 널리 사용되는 웹 서버 소프트웨어 중 하나로, Apache 소프트웨어 재단에서 개발하고 관리하고 있습니다. 아파치의 주요 특징은 다음과 같습니다:

  1. 확장성: Apache는 모듈화 된 설계를 가지고 있습니다. 이는 사용자가 필요에 따라 다양한 기능을 추가하거나 제거할 수 있음을 의미합니다. 예를 들어, PHP, Perl, Python 등 다양한 프로그래밍 언어를 지원하기 위한 모듈을 설치할 수 있습니다.
  2. 풍부한 기능: Apache는 매우 풍부한 기능을 제공합니다. 가상 호스팅, URL 리라이팅, 액세스 제어, 인증 등 다양한 기능을 지원합니다.
  3. 포트 이동성: Apache는 거의 모든 운영체제에서 실행될 수 있습니다. Windows, Linux, macOS 등 다양한 환경에서 Apache를 사용할 수 있습니다.

Nginx는 또 다른 인기 있는 웹 서버 소프트웨어로, 고성능, 높은 동시성, 낮은 메모리 사용량 등을 목표로 설계되었습니다. Nginx의 주요 특징은 다음과 같습니다:

  1. 성능: Nginx는 이벤트 기반 모델을 사용하여 동시에 많은 수의 연결을 처리할 수 있습니다. 이는 Nginx가 고프로 성능의 웹 서버와 리버스 프록시로서 뛰어난 선택이 될 수 있게 합니다.
  2. 리버스 프록시 및 로드 밸런싱: Nginx는 강력한 리버스 프록시 및 로드 밸런서로서의 기능을 제공합니다. 이를 통해 Nginx는 웹 애플리케이션 서버의 앞단에서 트래픽을 분산하고, 캐싱, SSL 종료 등의 기능을 수행할 수 있습니다.
  3. 정적 컨텐츠 처리: Nginx는 정적 컨텐츠를 효과적으로 제공할 수 있습니다. 이는 Nginx가 정적 파일의 서비스에 있어서 매우 빠른 성능을 보일 수 있게 합니다.
  4. 다양한 프로토콜 지원: Nginx는 HTTP, HTTPS, SMTP, POP3, IMAP 등의 다양한 프로토콜을 지원합니다.

그럼에도 불구하고, Apache와 Nginx에는 각각의 장단점이 있으므로, 사용 사례에 따라 적절한 선택을 해야합니다.

Apache는 다양한 모듈을 통해 유연하게 구성할 수 있으며, .htaccess 파일을 사용한 세부적인 설정 제어, 뛰어난 문서 지원 등이 가능하다는 이점이 있습니다. 하지만 동시 연결 수가 많아질수록 메모리 사용량이 증가하는 문제가 있을 수 있습니다.

반면에, Nginx는 이벤트 기반 모델 덕분에 많은 수의 동시 연결을 효과적으로 처리할 수 있습니다. 이는 고성능이 요구되는 사이트나 정적 컨텐츠가 많은 사이트에서 효과적입니다. 또한, Nginx는 로드 밸런서나 리버스 프록시로서의 역할도 잘 수행할 수 있습니다. 하지만 Apache에 비해 모듈 지원이 상대적으로 떨어지며, .htaccess와 같은 세부적인 디렉토리 단위의 설정이 제한적입니다.

최근에는 Apache와 Nginx를 함께 사용하는 방식도 자주 볼 수 있습니다. 예를 들어, Nginx를 리버스 프록시 및 정적 파일 서버로 사용하고, Apache를 동적 컨텐츠를 처리하는 서버로 사용하는 방식입니다. 이렇게 하면 각각의 장점을 취하면서 전체 시스템의 성능과 효율성을 향상시킬 수 있습니다.

 

'Spring' 카테고리의 다른 글

디버깅 모드  (0) 2025.01.19
FeignClient  (1) 2025.01.19
멀티 모듈 (Multi-Module)  (0) 2025.01.17
API(application programming interface), RestAPI  (0) 2023.05.22
SOLID 원칙  (0) 2023.04.07