클라이언트가 게이트웨이로 요청을하면 게이트웨이에서 요청에맞는 서버를 찾아서 라우팅합니다.


게이트웨이로 요청을보내면
api-gateway 에서 요청을받아
eureka-server 로 전송하고 eureka-server 에서
msa-sb-user 를 찾아 데이터 저장 합니다.

이 클래스는 API Gateway의 보안 설정(Security Config)을 정의하는 역할을 합니다.
Spring WebFlux 기반에서 JWT 인증, 예외 처리, CORS, CSRF 설정, 보안 필터 등록 등을 수행합니다.
handler 패키지는 Spring Security에서 발생하는 예외(401, 403)를 처리하는 역할을 합니다.
즉, 사용자가 인증되지 않았거나(401), 권한이 없을 때(403) 적절한 HTTP 응답을 반환하도록 설정합니다.
CustomAccessDeniedHandler → 403 Forbidden (권한 없음)
@Override
public Mono<Void> handle(ServerWebExchange exchange, AccessDeniedException denied) {
return Mono.fromRunnable(() -> {
exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
});
}
✔ 권한이 없는 사용자가 관리자 페이지 등 접근 시 403 응답 반환
✔ 예: 일반 유저가 /admin 페이지 접근 시 발생
CustomAuthenticationEntryPoint → 401 Unauthorized (인증 실패)
@Override
public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException ex) {
return Mono.fromRunnable(() -> {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
});
}
✔ JWT 토큰 없이 보호된 API에 접근하면 401 응답 반환
✔ 예: 로그인하지 않은 사용자가 /users/me 요청 시 발생
jwt 패키지는 JWT(Json Web Token)를 이용한 인증 및 보안 관련 기능을 담당합니다.
JwtTokenProvider → JWT 생성 및 검증
public String createToken(String email){
Claims claims = Jwts.claims().setSubject(email);
claims.put("email", email); // 추가 정보 저장 가능
Date now = new Date();
Date expiryDate = new Date(now.getTime() + expiration);
return Jwts.builder()
.setClaims(claims)
.setIssuedAt(now)
.setExpiration(expiryDate)
.signWith(this.secretKey, SignatureAlgorithm.HS256)
.compact();
}
✔ 사용자의 이메일을 기반으로 JWT 토큰을 생성
✔ 토큰에 생성 시간(setIssuedAt), 만료 시간(setExpiration), 키정보(signWith)를 포함
JwtFilter → API 요청 필터링 및 JWT 인증
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
System.out.println("요청 헤더에서 토큰 획득 : " + token);
if (token != null) {
try {
String email = jwtTokenProvider.getEmailFromToken(token); // JWT에서 이메일 추출
System.out.println("토큰에서 email 추출: " + email);
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
new User(email, "", new ArrayList<>()), null, null
);
return chain.filter(exchange.mutate()
.request(exchange.getRequest().mutate()
.header("X-Authencated-User", email)
.build())
.build())
.contextWrite(ReactiveSecurityContextHolder.withAuthentication(auth));
} catch (ExpiredJwtException e) {
System.out.println("토큰이 만료되었습니다.");
} catch (Exception e) {
throw new RuntimeException("잘못된 토큰");
}
}
return chain.filter(exchange);
}
✔ 요청에서 JWT 토큰을 읽고(Authorization 헤더 확인), 유효성 검증 후 인증 정보를 설정
✔ 유효한 경우, 사용자 이메일을 X-Authencated-User 헤더에 추가하여 하위 서비스로 전달
✔ 토큰이 없거나 만료된 경우, 예외 처리 후 요청을 차단 가능
redis 패키지는 Redis를 이용한 데이터 캐싱 및 세션 관리를 담당합니다.
API Gateway에서 JWT 토큰 저장, 세션 관리, 인증 정보 캐싱 등을 위해 사용됩니다.
RedisConnectionFactory → Redis 연결 관리
@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(); // Redis 연결 설정
}
✔ LettuceConnectionFactory를 사용하여 Redis와의 연결을 생성
✔ Jedis 대신 Lettuce 사용 ( 성능 최적화 ,lecttuce는 jedis보다 기능은 적지만 저장 공간이큼 )
RedisTemplate → Redis 데이터 저장 및 조회
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory()); // Redis 연결
template.setKeySerializer(new StringRedisSerializer()); // 키를 문자열로 직렬화
template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); // JSON 형태로 값 저장
return template;
}
✔ RedisTemplate를 이용해 Redis에 데이터를 저장 & 조회 가능
✔ 키(StringRedisSerializer)와 값(GenericJackson2JsonRedisSerializer)을 JSON 직렬화 방식으로 저장( 여기서 직렬화는 외부시스템을 바이트코드로 저장하는 것입니다 , 바이트코드로 저장하는 이유는 , 외부객체를 json파일로 변환하기 위해서 입니다.)
✔ JWT 토큰, 사용자 세션 정보 등을 저장하는 데 활용 가능
이 클래스는 Spring Cloud Gateway를 사용하여 API Gateway 역할을 수행하는 엔트리포인트(시작점)입니다.
마이크로서비스(MSA) 환경에서 클라이언트 요청을 적절한 마이크로서비스로 라우팅(전달)하는 역할을 합니다.
@EnableDiscoveryClient → Eureka Server와 연동
@EnableDiscoveryClient
✔ API Gateway가 Eureka Server에 클라이언트로 등록됨
✔ Eureka Server에서 실행 중인 마이크로서비스들의 위치(IP, 포트)를 조회 가능
✔ 라우팅 시 lb://서비스이름을 사용하여 로드 밸런싱 가능
RouteLocator → API 라우팅 설정
@Bean
public RouteLocator ecomRouteLocator(RouteLocatorBuilder builder) {
System.out.println("게이트웨이에서 개별 서비스 URL 등록");
return builder.routes()
.route("msa-sb-user",
r -> r.path("/auth/**").uri("lb://msa-sb-user"))
.route("msa-sb-user",
r -> r.path("/user/**").uri("lb://msa-sb-user"))
.build();
}
✔ RouteLocator를 사용하여 API Gateway에서 요청을 적절한 마이크로서비스로 전달
✔ "lb://msa-sb-user" → Eureka Server에서 msa-sb-user의 위치를 조회하여 로드 밸런싱 후 요청 전달
✔ /auth/ 및 /user/ 요청은 msa-sb-user 마이크로서비스로 전달
이 설정 파일은 API Gateway의 환경 설정을 정의하며, 주요 기능은 다음과 같습니다.
✅ API Gateway의 서비스 이름 및 포트 설정 (api-gateway, 8080)
✅ Eureka Server와 연동하여 서비스 등록 및 헬스 체크 설정
✅ JWT 토큰 설정 (비밀키, 만료시간)
✅ Redis 연결 설정 (세션 및 캐싱 관리)
API Gateway의 Eureka Server 연동
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
instance:
lease-renewal-interval-in-seconds: 15
lease-expiration-duration-in-seconds: 20
✔ Eureka Server(localhost:8761/eureka)에 API Gateway를 서비스로 등록
✔ 15초마다 헬스 체크를 수행하고, 20초 동안 응답이 없으면 서비스에서 제거
JWT 인증 설정
jwt:
token:
raw_secret_key: **********************************************
expiration: 10
✔ JWT 토큰의 비밀키(raw_secret_key) 설정
✔ 토큰 만료시간(expiration)을 10초로 짧게 설정 (테스트용, 실제 환경에서는 조정 필요)

이 클래스는 Eureka Server를 실행하는 엔트리포인트이며, MSA 환경에서 서비스 디스커버리(서비스 등록 및 검색) 역할을 수행합니다.
✅ Eureka Server를 활성화하여 마이크로서비스의 위치(IP, 포트) 관리
✅ 마이크로서비스들이 Eureka Server에 등록하고, API Gateway가 이를 조회하여 요청을 라우팅
✅ MSA에서 동적인 서비스 등록/제거를 자동으로 처리
Eureka Server 활성화
@EnableEurekaServer
✔ 현재 애플리케이션을 Eureka Server로 동작하도록 설정
✔ 각 마이크로서비스( API Gateway 포함 )가 자신을 등록할 수 있음
이 설정 파일은 Eureka Server의 환경 설정을 정의하며, 주요 기능은 다음과 같습니다.
✅ Eureka Server의 서비스 이름(eureka-server) 및 포트 설정 (8761)
✅ Eureka Server 자체는 다른 Eureka Server에 등록하지 않도록 설정
✅ 서비스 등록 보존 기능(self-preservation) 비활성화
Eureka Server 포트 설정
server:
port: 8761
✔ Eureka Server가 8761 포트에서 실행됨
✔ 클라이언트(API Gateway, 마이크로서비스)는
http://localhost:8761/eureka로 서비스 등록
Eureka Server 자체 등록 및 레지스트리 가져오기 비활성화
eureka:
client:
register-with-eureka: false
fetch-registry: false
✔ 간단한 실습이므로 standalone환경으로 진행 (Stand-alone은 1개의 프로세스에서 동작하는 에플리케이션을 뜻함)
✔ Eureka Server 자체는 다른 Eureka Server에 등록하지 않음
✔ 서비스 레지스트리를 가져오지 않도록 설정 (Stand - alone 모드에서 사용 )
Self-Preservation 모드 비활성화
eureka:
server:
enable-self-preservation: false
✔ Self-Preservation 모드 비활성화 → 서비스 갱신이 없으면 자동으로 제거
✔ 테스트 환경에서는 false로 설정 가능하지만, 운영 환경에서는 true 권장

✅ CSRF 보호 비활성화
✅ 모든 요청을 허용 (permitAll())
✅ 로그인 화면(Form Login) 비활성화
모든 요청 허용 설정
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll())
✅ 회원 관련 API 제공 (회원가입, 정보 수정 등)
✅ 게이트웨이를 통해 /user 경로로 접근 가능
✅ 회원가입 요청을 UserService를 통해 처리
회원가입 API
@PostMapping("/signup")
public ResponseEntity<String> signup(@RequestBody UserDto userDto) {
userService.createUser(userDto);
return ResponseEntity.ok("회원가입 성공");
}
✔ 클라이언트에서 회원가입 요청(JSON) → UserService에서 회원 생성 → 응답 반환
✅ 회원가입 요청 데이터를 담는 DTO(Data Transfer Object)
✅ JSON 데이터를 객체로 변환하여 저장
✅ 기본적으로 ROLE_USER 권한을 설정
회원가입 데이터 구조
private String email;
private String userName;
private String password;
private String role = "ROLE_USER";
✔ 회원가입 시 이메일, 사용자명, 비밀번호 저장
✔ 기본 권한(ROLE_USER)을 자동 할당
✅ 회원 정보를 데이터베이스(members 테이블)에 저장
✅ Spring Security의 UserDetails 구현하여 인증 객체로 활용
✅ 이메일(email)을 기본 키(PK)로 사용하며, roles 필드를 통해 역할(Role) 관리
JPA 엔티티 필드 구성
@Id
private String email;
@Column(name="username")
private String userName;
private String password;
private String hp;
private String address;
private String roles;
private boolean enable;
✔ 회원 정보(email, userName, password, hp, address) 저장
✔ roles를 통해 사용자의 권한(예: ROLE_USER, ROLE_ADMIN) 설정 가능
✔ enable 필드를 사용하여 이메일 인증 여부 체크
✅ Lettuce를 사용하여 Redis 연결 (RedisConnectionFactory)
✅ RedisTemplate을 빈으로 등록하여 Redis 데이터를 저장 및 조회 가능
✅ 키 ,값을 직렬화 설정
Redis 연결 설정
@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
✔ Lettuce를 사용하여 Redis와 연결
✔ 환경 설정을 기반으로 Redis 연결 객체를 생성
RedisTemplate 설정
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory());
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}
✔ Redis에서 데이터를 저장하고 조회하는 RedisTemplate을 설정
✔ 문자열 키(StringRedisSerializer), JSON 직렬화된 값(GenericJackson2JsonRedisSerializer) 사용
✅ JPA를 사용하여 UserEntity의 CRUD(생성, 조회, 수정, 삭제) 기능 제공
✅ 이메일(email)을 기준으로 회원을 조회하는 메서드(findByEmail) 추가
✅ Spring Data JPA를 사용하여 자동으로 구현됨 (메서드 선언만 하면 JPA가 SQL을 생성하여 실행)
✅ 회원가입 처리 (createUser)
✅ 비밀번호 암호화 (BCryptPasswordEncoder)
✅ 이메일 인증 요청 처리 (sendVaildEmail)
✅ Redis를 활용한 이메일 인증 토큰 저장
회원가입 처리
public void createUser(UserDto userDto) {
if (userRepository.findByEmail(userDto.getEmail()).isPresent()) {
throw new IllegalArgumentException("Email already exists");
}
UserEntity userEntity = UserEntity.builder()
.email(userDto.getEmail())
.userName(userDto.getUserName())
.password(passwordEncoder.encode(userDto.getPassword()))
.roles("ROLE_USER")
.enable(false)
.build();
userRepository.save(userEntity);
sendVaildEmail(userEntity);
}
✔ 이메일 중복 체크 후 새로운 회원을 저장
✔ 비밀번호를 암호화하여 저장 (passwordEncoder.encode())
✔ 회원가입 후 이메일 인증 요청 (sendVaildEmail)
이메일 인증 요청 & Redis 저장
private void sendVaildEmail(UserEntity userEntity) {
String token = UUID.randomUUID().toString();
redisTemplate.opsForValue().set(token, userEntity.getEmail(), 6, TimeUnit.HOURS);
String url = "http://localhost:8080/user/vaild?token=" + token;
sendMail(userEntity.getEmail(), "Email 인증", "링크를 눌러서 인증: " + url);
}
✔ UUID 기반의 랜덤 토큰 생성 후 Redis에 저장 (6시간 만료)
✔ 인증 URL을 포함한 이메일 전송 (sendMail)
✅ 서비스 이름 및 포트 설정 (msa-sb-user, 8081)
✅ Eureka Server와 연동하여 서비스 등록 및 헬스 체크 설정
✅ MySQL과 연결하여 사용자 데이터 관리
✅ Redis 연결 설정 (세션 및 캐싱 관리)
✅ JWT 토큰 설정 (비밀키, 만료시간)
✅ 이메일 인증을 위한 SMTP 설정
Eureka Server 연동
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
instance:
lease-renewal-interval-in-seconds: 15
lease-expiration-duration-in-seconds: 20
✔ Eureka Server(localhost:8761/eureka)에 MSA-SB-USER 서비스를 등록
✔ 15초마다 헬스 체크를 수행하고, 20초 동안 응답이 없으면 서비스에서 제거
MySQL 데이터베이스 설정
spring.datasource.url=jdbc:mysql://localhost:3306/msa_sb_user
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=p1234
✔ MySQL(localhost:3306)에 연결하여 msa_sb_user 데이터베이스 사용
✔ JPA와 Hibernate를 사용하여 데이터 저장 및 조회
Redis 설정
spring.data.redis.host=localhost
spring.data.redis.port=6379
spring.data.redis.repositories.enabled=false
✔ Redis(localhost:6379)를 활용하여 세션 및 인증 캐싱 처리
✔ 이메일 인증 시 토큰 저장에 사용
JWT 인증 설정
jwt.token.raw_secret_key=****************
jwt.access-token-expiration=3600000
jwt.refresh-token-expiration=604800000
✔ JWT 토큰의 비밀키(raw_secret_key) 설정
✔ Access Token 유효시간 1시간(3600000ms), Refresh Token 유효시간 7일(604800000ms) 설정
이메일 인증 설정 (Gmail SMTP)
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=******@gmail.com
spring.mail.password=**** **** **** ****
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.timeout=5000
spring.mail.properties.mail.smtp.starttls.enable=true
✔ 회원가입 후 이메일 인증을 위한 SMTP 설정
✔ Google SMTP(smtp.gmail.com:587) 사용하여 이메일 전송










