| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
- leetcode
- HTML
- 알고리즘문제풀이
- react
- lodash
- 자바스크립트 알고리즘 문제
- 자바스크립트 문제풀이
- 자바스크립트 문제 풀이
- stack문제
- 프로그래머스
- 자바스크립트
- Baekjoon
- 리액트
- Next.js13
- Next
- 프론트엔드
- next13
- 자바스크립트 문제
- 타입스크립트
- 자바스크립트 연결리스트
- 리액트쿼리
- NPM
- 제로베이스
- JavaScript
- CSS
- til
- JS
- 코딩테스트
- 자바스크립트 알고리즘
- leetcode문제풀이
- Today
- Total
코드노트
[Spring Boot] Spring Cloud OpenFeign 깊게 이해하기 본문
마이크로서비스 아키텍처 (MSA) 및 분산 시스템 환경에서 외부 API 통신을 단순화해주는 Spring Cloud OpenFeign에 대해서 정리 해보려고 한다.
우리가 사용하는 어노테이션들이 내부적으로 어떻게 동작하고 왜 이런 구조를 사용하는지 시스템적인 관점에서 분석해보자!
Spring Boot & Lombok 핵심 어노테이션 이해하기
스프링 프레임워크는 애노테이션(Annotation, @)을 통해 프로그램의 제어권과 설정을 관리한다.
Spring 프레임워크 핵심 제어 어노테이션
@SpringBootApplication (애플리케이션 시스템의 시작점)
- 이 어노테이션은 스프링 부트 성을 움직이는 '마스터키'이자 메인 제어 센터이다. 내부에는 세가지 핵심 애노테이션을 품고 있어, 프로그램이 켜지는 순간 다음과 같이 실행된다.
- @SpringBootConfiguration : 스프링 애플리케이션의 환경 설정을 총괄하고 필요한 Bean들을 정의, 관리하는 핵심 기지를 뜻한다.
- @ComponentScan : 스프링이 프로젝트 내부를 돌아다니면서 개발자가 만든 클래스들을 스캔한다. 그리고 @Service, @RestController같은 마크가 붙은 클래스들을 찾아 스프링의 관리 영역인 컨테이너(Bean)에 자동으로 등록해주는 탐지기 역할을 한다.
- @EnableAutoConfiguration : 스프링 부트의 가장 강력한 기능이다. 개발자가 데이터베이스나 웹서버 설정을 일일이 하지 않아도, 프로젝트에 포함된 라이브러리를 분석하여 최적의 환경을 자동으로 세팅해준다.
@RestController (외부 세상과 소통하는 문)
- 과거의 웹 서버 사용자에게 완성된 HTML화면(VIEW)를 그려 보내주었다. 하지만 현대의 앱이나 웹(React, Vue 등)은 화면이 아니라 순수한 데이터만 원한다.
- @RestController는 이 요청을 담당한다. 클라이언트가 문을 두드리면, 자바의 객체 데이터를 표준 데이터 규격인 JSON 포멧 문자열로 변환하여 응답 본문(Body)에 담아 직접 전달해 주는 통로 역할을 한다.
@RequestMapping("/api/example") (교통정리를 하는 이정표) (라우팅 레이어 설정)
- 웹사이트 주소창에 http://localhost:8080/api/example를 입력한다고 했을때 정확히 어떤 시능으로 연결되어야할지 알려주는 길잡이(Routing)역할을 한다. 클래스 맨 위에 선언하면 "이 클래스 안에 있는 모든 기능은 앞 주소에 '/api/example'를 달고 들어온다"라고 약속하는 공통 이정표가 된다.
- 정리하면 특정 HTTP요청 URL을 컨트롤러 클래스나 메서드에 매핑하는 역할은 한다. 클래스 레벨에 선언하면 네임스페이스 역할을 통해서 하위 메서드들의 중복 엔드포인트 경로를 묶어주고 가독성과 구조적으로 안정성까지 높일 수 있다.
@Service(진짜 핵심 비즈니스 로직을 수행하는 해결사) (비즈니스 도메인 레이어)
- 데이터베이스에서 데이터를 꺼내오고 그것을 가공하고 계산하는 진짜 서비스 핵심 로직 공간이다. 스프링에게 "여기는 중요한 비즈니스 규칙이 모여있는 곳이니 네가 안전하게 만들어서 관리해줘"라고 부탁하는 표식이다. 컴포넌트 스캔의 대상이 되어 싱글톤 객체로 스프링 컨테이너에 의해서 생명주기가 관리된다.
Lombok 어노테이션과 컴파일 시점의 코드 최적화(컴파일러가 대신 해줌)
Lombox은 런타임이 아닌 컴파일 시점에 자바의 AST(추상 구문 트리)를 수정하여 바이트코드(.class)에 직접 메서드를 주입하는 기술이다. 쉽게 말하면 자바 언어의 단점 중 하나는 데이터를 담는 개체를 만들 때 Getter, Setter, 생성자 같은 반복적인 보일러플레이트를 너무 많이 작성해야하는 점이 있다. 롬복은 이를 컴파일 시점에 대신 만들어주는 도구라 보면 된다.
@RequiredArgsConstructor (안전하고 깔끔한 부품 조립기)
- 클래스 내부에 선언된 변수 중 final 키워드가 붙거나 @NonNull이 지정된 필드만을 모아서 생성자를 자동으로 만들어준다.
- 이것이 왜 중요할까?
- 스프링 진영에서 권장하는 생성자 주입(Constructor Injection)을 유연하게 구현할 수 있게 해준다.
필드 주입(@Autowired)방식과 달리 객체가 생성되는 시점에 의존성이 완전히 채워지는 것을 보장(불변성 보장)하며 순환 참조 문제를 컴파일 시점에서 잡아낼 수 있는 안전한 시스템 구조를 만들어준다.
- 스프링 진영에서 권장하는 생성자 주입(Constructor Injection)을 유연하게 구현할 수 있게 해준다.
- 이것이 왜 중요할까?
@Getter / @Setter (캡슐화 지원)
- 객체지향의 핵심 원칙 중 하나인 데이터 캡슐화를 지키기 위해 필드는 privitte으로 가리고 외부 접근 통로인 Getter/Setter 메서드를 자동으로 컴파일러가 생성해준다. 데이터 전송 객체(DTO)에서 필수적으로 활용된다.
@Builder (안전한 객체 생성 매커니즘)
- 빌더 패턴을 자동으로 구현해준다. 생성자 인자가 많아질 때 발생할 수 있는 인자 순서 뒤바뀜 오류를 완전히 방지한다. 가독성을 높일 뿐만 아니라 필요한 필드만 선택적으로 세팅하여 객체를 생성할 수 있어 불변 객체를 설계할 때 매우 유용하다.
외부 서버 통신 기술 트랜드 및 OpenFeign 아키텍처
시스템이 커지면 하나의 서버가 모든 일을 처리할 수 없어 다른 서버(외부 API)와 통신해야한다. 스프링 생태계에서의 통신 기술 진화 과정 속에서 OpenFeign의 위치를 파악하는것이 중요하다.
네트워크 통신 기술 비교
| 기술명 | 특징 및 통신 방식 | 현재 위치 및 권장 환경 |
| RestTemplate | 동기(Blocking) 방식의 전통적인 HTTP 클라이언트 | 현재 기능 추가 없이 유지보수 모드 체제 (레거시 시스템 중심) |
| WebClient | 비동기/논블로킹(Non-Blocking) 기반 리액티브 통신 | 고성능, 대용량 트래픽 처리가 필요한 WebFlux 환경에 적합 |
| RestClient | Spring 6.1+에 도입된 현대적인 동기식 HTTP 클라이언트 | RestTemplate의 단점을 보완한 최신 스프링 표준 동기 클라이언트 |
| OpenFeign | 인터페이스 선언 기반의 선언형 HTTP 클라이언트 | MSA 및 REST API 연동 시 가독성과 생산성이 최우선일 때 강력 권장 |
OpenFeign의 핵심 작동 원리
OpenFeign이 혁신적인 이유는 개발자가 HTTP 커넥션을 열고 URL을 조합하고 스트림을 통해 데이터를 읽어오는 통신 코드를 단 한 줄도 작성하지 않는다는 점에 있습니다.
[클라이언트 서비스 로직]
│
▼
[Feign 인터페이스 호출]
│
▼
[스프링이 생성한 동적 프록시(Proxy) 동작]
│
▼
[HTTP 요청 자동 조립 및 발송]
1. @EnableFeignClients
- 스프링 애플리케이션이 구동될 때 프로젝트 내부의 @FeignClient 어노테이션이 붙은 인터페이스들을 전부 찾아내는 스위치 역할
2. 동적 프록시 (Dynamic Proxy)
- 개발자는 인터페이스만 선언했지만 스프링이 컴파일 및 런타임 시점에 이 인터페이스를 바탕으로 실제 HTTP 통신을 수행하는 구현 객체(프록시)를 메모리에 동적으로 만들어 준다.
3. 선언형 아키텍처
- @GetMapping{"/{id}")와 같은 Spring MVC 어노테이션 형식을 그대로 사용하여 외부 서버의 경로와 파라미터를 매핑하므로 개발자는 마치 우리 프로젝트 내부의 서비스를 호출하는 것과 같은 감각으로 외부 시스템과 유연하게 상호작용 할 수 있다.
분산 시스템 환경에서의 서비스 아키텍처 (MSA 구조)
현대의 백엔드 시스템은 하나의 거대한 서버가 모든 일을 처리하는 모놀리식(Monolithic) 구조에서 탈피하여 기능별로 서버를 쪼개어 통신하는 마이크로서비스 아키텍처(MSA) 혹은 분산 시스템 환경을 지향한다.
서비스 제공자 (API Provider)의 표준 역할
- 개념 : 시스템 아키텍처 상에서 데이터의 원천(Single Source of Truth)을 쥐고 있거나 핵심 비즈니스 연산을 직접 수행하는 종착지(Backend) 서버를 의미한다.
- 표준적 책무 : 외부의 호출을 받아 데이터베이스(DB)나 인메모리 저장소에 접근하여 실질적인 CRUD(생성·조회·수정·삭제) 가공 처리를 담당한다.
- 초기화 메커니즘 : 시스템 구동 시 필수적으로 메모리에 적재되어야 하는 공통 데이터나 기초 설정값들은 애플리케이션 컨텍스트의 생성 직후 단계(@PostConstruct 등)에서 안전하게 초기화(Initialization)하는 가동 표준을 따른다.
서비스 소비자 (API Consumer)의 표준 역할
- 개념 : 외부 최전방(사용자, 프론트엔드 앱)에서 들어오는 최초 요청을 맞이하는 진입점(Gateway 또는 클라이언트 포트) 서버 역할을 한다.
- 표준적 책무 : 표현 계층(Controller)에서 사용자의 인풋을 검증한 뒤 비즈니스 레이어(Service)로 비즈니스 흐름 제어권을 넘긴다.
핵심은 자신이 직접 데이터를 처리하지 않고 원격지에 있는 API Provider 서버에게 네트워크 호출을 통해 데이터 처리를 완전히 위임(Remote Call)한다는 점이다. - 아키텍처의 핵심 : 느슨한 결합(Loosely Coupled)과 설정의 외부화
- 대상 서버의 IP 주소나 도메인(URL)을 소스코드 내부에 하드코딩(Hard-coding)하는 것은 절대 하지말자.
코드와 설정을 철저히 분리하여 application.yaml 같은 외부 환경 설정 파일을 통해 관리해야 한다. - 이를 통해 소스코드를 단 한 줄도 수정하거나 다시 빌드하지 않고도 설정 파일의 속성값만 바꾸어 로컬 개발 환경(localhost), 테스트 환경(QA), 실제 운영 환경(Production)에 맞게 타깃 서버의 주소를 동적으로 전환 주입받을 수 있다.
- 대상 서버의 IP 주소나 도메인(URL)을 소스코드 내부에 하드코딩(Hard-coding)하는 것은 절대 하지말자.
