[Java/SpringBoot] gRPC 연동 방법

2024. 10. 3. 16:36· Server
목차
  1. [gRPC 사용 계기]
  2. [연동 방법 진행 순서]
  3. 1. 각 build.gradle에 의존성 추가
  4. 2. 각 application.yml에 설정 추가
  5. 3. proto 파일 작성
  6. 4. 자원서버의 gRPC 통신 구현
  7. 5. 인증서버의 gRPC 통신 구현
  8. 6. postman으로 통신 테스트

[gRPC 사용 계기]

MSA(Microservices Architecture)의 관점에서 서버를 분리하여 개발하는 방법을 찾던 중, gRPC는 비교적 러닝 커브가 낮고 개인 개발에서도 실용적인 통신 방식이라 판단하여 이를 사용해보기로 했습니다.

인증 서버는 회원 기능만 담당하고, 그 외 비즈니스 로직은 자원 서버에서 처리하는 구조로 설계하였습니다. 자원 서버로 들어오는 모든 API 요청에 대해 인증 서버로 토큰 검증 요청을 보내고, 그 결과를 바탕으로 인증하는 방식으로 구현하고자 합니다.

 

이 내용은 인증 서버에 회원 기능이 구현되었다는 전제 하에 작성되었습니다.

 

[연동 방법 진행 순서]

  1. 각 build.gradle에 의존성 추가
  2. 각 application.yml에 설정 추가
  3. proto 파일 작성
  4. 자원서버의 gRPC 통신 구현
  5. 인증서버의 gRPC 통신 구현
  6. postman으로 통신 테스트

💡 개발 환경 Java 17, Spring 3.3.X, Gradle 8.8, MySQL

1. 각 build.gradle에 의존성 추가

인증서버

> build.gradle

plugins { ​​​​id 'java' ​​​​id 'org.springframework.boot' version '3.3.3' ​​​​id 'io.spring.dependency-management' version '1.1.6' ​​​​// gRPC통신 시에 사용되는 protobuf 플러그인 설정 ​​​​id 'com.google.protobuf' version '0.9.4' } ... dependencies { ‌... 그 외 의존성 ​​​​ ​​​​// gRPC ​​​​implementation 'io.grpc:grpc-netty-shaded:1.66.0' ​​​​implementation 'io.grpc:grpc-protobuf:1.66.0' ​​​​implementation 'io.grpc:grpc-stub:1.66.0' ​​​​implementation 'com.google.protobuf:protobuf-java:4.27.4' ​​​​implementation 'com.google.protobuf:protobuf-java-util:4.27.4' ​​​​implementation 'net.devh:grpc-spring-boot-starter:2.15.0.RELEASE' ​​​​ ​​​​// ProtoBuf ​​​​compileOnly 'javax.annotation:javax.annotation-api:1.3.2' } // gRPC protobuf { ​​​​protoc { ​​​​​​​​artifact = "com.google.protobuf:protoc:4.27.4" ​​​​} ​​​​plugins { ​​​​​​​​grpc { ​​​​​​​​​​​​artifact = "io.grpc:protoc-gen-grpc-java:1.66.0" ​​​​​​​​} ​​​​} ​​​​generateProtoTasks { ​​​​​​​​all().each { task -> ​​​​​​​​​​​​task.plugins { ​​​​​​​​​​​​​​​​grpc {} ​​​​​​​​​​​​} ​​​​​​​​} ​​​​} } // .proto 파일의 위치를 src/main/proto로 지정 sourceSets { ​​​​main { ​​​​​​​​proto { ​​​​​​​​​​​​srcDir 'src/main/proto' ​​​​​​​​} ​​​​} } compileJava { ​​​​dependsOn 'generateProto' } tasks.processResources { ​​​​duplicatesStrategy = DuplicatesStrategy.EXCLUDE } tasks.named('test') { ​​​​useJUnitPlatform() }

 

dependencies 블록 설명

더보기
  • grpc-netty-shaded : gRPC의 서버 및 클라이언트에서 사용되는 Netty 전송 채널 라이브러리
  • grpc-protobuf: gRPC와 protobuf를 연결해주는 라이브러리. Protobuf를 gRPC 서비스에서 사용할 수 있게 함.
  • grpc-stub: gRPC의 Stub을 사용하여 클라이언트와 서버 간의 원격 호출을 처리.
  • protobuf-java: Protobuf 파일에서 생성된 Java 클래스들을 사용하기 위한 라이브러리.
  • protobuf-java-util: Protobuf 파일의 JSON 변환을 도와주는 유틸리티 라이브러리.
  • grpc-spring-boot-starter: Spring Boot와 gRPC를 쉽게 통합할 수 있도록 도와주는 라이브러리.
  • javax.annotation-api: 주석(annotation)을 위한 라이브러리로, 컴파일할 때만 필요하기 때문에 compileOnly로 설정.

자원서버

> build.gradle

plugins { ‌id 'java' ‌id 'org.springframework.boot' version '3.3.3' ‌id 'io.spring.dependency-management' version '1.1.6' ‌​​​​// gRPC통신 시에 사용되는 protobuf 플러그인 설정 ​​​​​​​​id 'com.google.protobuf' version '0.9.4' } ... dependencies { ‌... 그 외 의존성 ​​​​ ‌// gRPC ‌implementation 'io.grpc:grpc-netty-shaded:1.66.0' ‌implementation 'io.grpc:grpc-protobuf:1.66.0' ‌implementation 'io.grpc:grpc-stub:1.66.0' ‌implementation "com.google.protobuf:protobuf-java:4.27.4" ‌implementation "com.google.protobuf:protobuf-java-util:4.27.4" ‌// gRPC Client ‌implementation 'net.devh:grpc-client-spring-boot-starter:3.1.0.RELEASE' ‌// ProtoBuf ‌compileOnly 'javax.annotation:javax.annotation-api:1.3.2' } // gRPC 및 Protobuf 설정 protobuf { ‌protoc { ‌‌artifact = "com.google.protobuf:protoc:4.27.4" ‌} ‌plugins { ‌‌grpc { ‌‌‌artifact = "io.grpc:protoc-gen-grpc-java:1.66.0" ‌‌} ‌} ‌generateProtoTasks { ‌‌all().each { task -> ‌‌‌task.plugins { ‌‌‌‌grpc {} ‌‌‌} ‌‌} ‌} } // 프로토콜 버퍼 파일 경로 설정 sourceSets { ‌main { ‌‌proto { ‌‌‌srcDir 'src/main/proto' ‌‌} ‌‌java { ‌‌‌// 프로토콜 파일로부터 생성된 코드 경로를 포함 ‌‌‌srcDirs += 'build/generated/source/proto/main/java' ‌‌‌srcDirs += 'build/generated/source/proto/main/grpc' ‌‌} ‌} } // 컴파일 태스크가 Protobuf 파일 생성을 포함하도록 의존성 설정 compileJava { ​​​​dependsOn 'generateProto' } // Protobuf 관련 경로 정리 clean { ‌delete 'build/generated' }

 

dependencies 블록 설명

더보기
  • grpc-netty-shaded : gRPC의 서버 및 클라이언트에서 사용되는 Netty 전송 채널 라이브러리
  • grpc-protobuf: gRPC와 protobuf를 연결해주는 라이브러리. Protobuf를 gRPC 서비스에서 사용할 수 있게 함.
  • grpc-stub: gRPC의 Stub을 사용하여 클라이언트와 서버 간의 원격 호출을 처리.
  • protobuf-java: Protobuf 파일에서 생성된 Java 클래스들을 사용하기 위한 라이브러리.
  • protobuf-java-util: Protobuf 파일의 JSON 변환을 도와주는 유틸리티 라이브러리.
  • grpc-client-spring-boot-starter: gRPC 클라이언트를 쉽게 설정하고 Spring Boot에서 사용할 수 있게 해주는 라이브러리
  • javax.annotation-api: 주석(annotation)을 위한 라이브러리로, 컴파일할 때만 필요하기 때문에 compileOnly로 설정.

sourceSets 블록 설명

  • proto.srcDir 'src/main/proto': Protobuf 파일의 위치를 src/main/proto로 설정.
  • java.srcDirs: Protobuf로부터 생성된 Java 코드의 위치를 추가. build/generated/source/proto/main/java는 기본 Protobuf 관련 Java 클래스들이, build/generated/source/proto/main/grpc는 gRPC Stub 코드들이 생성되는 디렉터리.

위와 같이 각각 build.gradle을 작성하고 .proto 파일을 src/main/proto 디렉토리에 두면 별도의 환경 변수 설정 없이도 Gradle 빌드 시 gRPC 관련 코드를 생성하고 컴파일이 진행됨


2. 각 application.yml에 설정 추가

> 인증서버 application.yml

파일의 최상단에 아래와 같이 코드를 입력한다. (local ver.)

# gRPC 인증 서버 포트 설정 grpc: ​​server: ​​​​port: ${GRPC_PORT} ​​​​security: ​​​​​​enabled: false

> 자원서버 application.yml

파일의 최상단에 아래와 같이 코드를 입력한다. (local ver.)

# gRPC 자원 서버 포트 설정 grpc: ​​server: ​​​​port: ${GRPC_RESOURCE_SERVER_PORT} ​​client: ​​​​auth: ​​​​​​address: ${GRPC_HOST}:${GRPC_AUTH_SERVER_PORT} ​​​​​​negotiation-type: plaintext
  • GRPC_RESOURCE_SERVER_PORT : gRPC의 자원 서버 포트 (실제 백엔드 개발 시에는 활용되지 않는 포트)
  • GRPC_AUTH_SERVER_PORT : gRPC의 인증 서버 포트 (인증서버와 통신 시에는 해당 주소로 통신한다.)
  • grpc.client.auth : "auth" 클라이언트에 해당하는 서버의 주소 및 통신 방식 등 설정을 지정

3. proto 파일 작성

proto 파일 (proto파일은 인증서버와 자원서버 모두 작성해주어야 함!)

syntax = "proto3"; option java_package = "com.smile.fridaymarket_auth.grpc"; option java_outer_classname = "AuthTokenProto"; service AuthTokenService { ​​rpc VerifyToken(AuthTokenRequest) returns (AuthTokenResponse); } // 요청 객체 message AuthTokenRequest { ​​string accessToken = 1; } // 응답 객체 message AuthTokenResponse { ​​bool success =1; ​​string userId = 2; ​​string username = 3; }

 

상세 설명은 아래 더 보기 버튼을 클릭해주세요.

더보기
syntax = "proto3"; option java_package = "com.smile.fridaymarket_auth.grpc"; option java_outer_classname = "AuthTokenProto";
  • 문법 버전: proto3는 Protocol Buffers의 세 번째 버전을 사용함을 나타냄
  • Java 패키지 설정: java_package는 생성된 Java 클래스가 포함될 패키지를 지정하며, com.smile.fridaymarket_auth.grpc로 설정됨
  • 클래스 이름 설정: java_outer_classname은 생성될 Java 클래스의 이름을 정의하며, AuthTokenProto로 설정되어 모든 메시지와 서비스를 포함하는 외부 클래스를 생성함
service AuthTokenService { ​​rpc VerifyToken(AuthTokenRequest) returns (AuthTokenResponse); }
  • gRPC 서비스 정의: AuthTokenService라는 gRPC 서비스를 정의
  • RPC 메서드: VerifyToken 메서드는 AuthTokenRequest를 입력으로 받고, AuthTokenResponse를 반환하는 RPC 호출을 정의함
// 요청 객체 message AuthTokenRequest { ‌string accessToken = 1; }
  • 요청 메시지: AuthTokenRequest 메시지는 인증을 위한 요청 정보를 포함
  • 필드: accessToken은 클라이언트가 인증 서버에 전달하는 액세스 토큰을 나타내며, 필드 번호는 1임
// 응답 객체 message AuthTokenResponse { ​​bool success = 1; ​​string userId = 2; ​​string username = 3; }
  • 응답 메시지: AuthTokenResponse 메시지는 인증 결과를 포함.
  • 필드:
    • success: 인증 성공 여부를 나타내는 boolean 값, 필드 번호 1
    • userId: 인증된 사용자의 ID를 포함하는 문자열, 필드 번호 2
    • username: 인증된 사용자의 이름을 포함하는 문자열, 필드 번호 3

4. 자원서버의 gRPC 통신 구현

자원서버의 gRPC 통신 서비스 클래스

> GrpcAuthClientService.java

@Slf4j @Service public class GrpcAuthClientService { ​​​​@GrpcClient("auth") ​​​​private AuthTokenServiceGrpc.AuthTokenServiceBlockingStub authStub; ​​​​public UserResponse authToken(String accessToken) { ​​​​​​​​try { ​​​​​​​​​​​​// 인터셉터를 추가한 Stub 생성 (주입된 authStub을 사용) ​​​​​​​​​​​​AuthTokenServiceGrpc.AuthTokenServiceBlockingStub interceptedStub = ​​​​​​​​​​​​​​​​​​​​authStub.withInterceptors(new JwtClientInterceptor(accessToken)); ​​​​​​​​​​​​AuthTokenProto.AuthTokenResponse authTokenResponse = interceptedStub.verifyToken( ​​​​​​​​​​​​​​​​​​​​AuthTokenProto.AuthTokenRequest.newBuilder() ​​​​​​​​​​​​​​​​​​​​​​​​​​​​.setAccessToken(accessToken) ​​​​​​​​​​​​​​​​​​​​​​​​​​​​.build() ​​​​​​​​​​​​); ​​​​​​​​​​​​log.info("gRPC 통신 응답 username: {}", authTokenResponse.getUsername()); ​​​​​​​​​​​​return new UserResponse(true, authTokenResponse.getUserId(), authTokenResponse.getUsername()); ​​​​​​​​} ​​​​​​​​catch (StatusRuntimeException e) { ​​​​​​​​​​​​log.info("gRPC 호출 실패 : {}", e.getStatus().getCode().name()); ​​​​​​​​​​​​return new UserResponse(false, "Unknown", "Unknown"); ​​​​​​​​} ​​​​} }

 

  • @GrpcClient("auth")
    • gRPC 클라이언트 애노테이션: Spring 애플리케이션에서 gRPC 클라이언트를 의존성 주입할 때 사용하는 애노테이션
    • 클라이언트 이름: "auth"로 설정되며, application.yml의 grpc.client.auth 설정과 일치해야 함
    • 연결 정보: Spring이 gRPC 클라이언트의 연결 정보를 주입하는 역할을 수행
  • gRPC Stub: authStub은 인증 서버로 요청을 보낼 때 사용하는 gRPC Stub으로, 토큰 검증 요청을 수행하는 데 사용됨

 

> JwtClientInterceptor.java

@Slf4j public class JwtClientInterceptor implements ClientInterceptor { ​​​​private static final Metadata.Key<String> AUTHORIZATION_HEADER = Metadata.Key.of("Authorization", Metadata.ASCII_STRING_MARSHALLER); ​​​​private final String accessToken; ​​​​public JwtClientInterceptor(String accessToken) { ​​​​​​​​this.accessToken = accessToken; ​​​​} ​​​​@Override ​​​​public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> methodDescriptor, ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​CallOptions callOptions, Channel channel) { ​​​​​​​​return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(channel.newCall(methodDescriptor, callOptions)) { ​​​​​​​​​​​​@Override ​​​​​​​​​​​​public void start(Listener<RespT> responseListener, Metadata headers) { ​​​​​​​​​​​​​​​​headers.put(AUTHORIZATION_HEADER, "Bearer " + accessToken); ​​​​​​​​​​​​​​​​super.start(responseListener, headers); ​​​​​​​​​​​​} ​​​​​​​​}; ​​​​} }

 

  • gRPC 요청을 가로채서 헤더에 JWT 토큰을 추가하는 인터셉터
  • Authorization 헤더에 Bearer {토큰} 형식으로 액세스 토큰을 담아 인증 서버로 전달

 

> GrpcAuthController.java

@RestController @RequiredArgsConstructor @RequestMapping("/api/auth") public class GrpcAuthController { // gRPC 통신 테스트를 위한 클래스 ​​​​@RequestMapping(value = "", method = RequestMethod.POST) ​​​​public UserResponse authToken(HttpServletRequest request) { ‌ ‌​​​​UserResponse user = (UserResponse) request.getAttribute("user"); ​​​​​​​​if (user == null || !user.success()) { ​​​​​​​​​​​​throw new CustomException(ErrorCode.TOKEN_NOT_VALID); ​​​​​​​​} ​​​​​​​​return user; // 이미 검증된 사용자 정보 반환 ​​​​} }

 

  • 자원 서버로 API 호출을 보냈을 때 gRPC 통신이 정상적으로 작동하는지 테스트하기 위해 해당 컨트롤러를 생성하였습니다.
  • 요청에서 이미 검증된 사용자 정보를 확인한 후, 그 정보를 반환합니다.
  • 만약 인증 정보가 유효하지 않다면 CustomException을 발생시켜 토큰 검증 오류를 처리합니다.

 


5. 인증서버의 gRPC 통신 구현

> JwtServerInterceptor.java

@RequiredArgsConstructor @GrpcGlobalServerInterceptor public class JwtServerInterceptor implements ServerInterceptor { ​​​​private final JwtTokenProvider jwtTokenProvider; ​​​​// Authorization 헤더 키 생성 (Metadata.Key) ​​​​private static final Metadata.Key<String> AUTHORIZATION_KEY = ​​​​​​​​​​​​Metadata.Key.of("Authorization", Metadata.ASCII_STRING_MARSHALLER); ​​​​@Override ​​​​public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall( ​​​​​​​​​​​​ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) { ​​​​​​​​// Authorization 헤더에서 토큰을 가져옴 ​​​​​​​​String token = headers.get(AUTHORIZATION_KEY); ​​​​​​​​if (token == null || token.isEmpty()) { ​​​​​​​​​​​​throw new CustomException(ErrorCode.ILLEGAL_ACCESS_TOKEN_NOT_VALID); ​​​​​​​​} ​​​​​​​​// 'Bearer ' 접두사 제거 ​​​​​​​​if (token.startsWith("Bearer ")) { ​​​​​​​​​​​​token = token.substring(7); // "Bearer " 뒤의 부분만 남김 ​​​​​​​​} ​​​​​​​​try { ​​​​​​​​​​​​// 토큰 유효성 검증 ​​​​​​​​​​​​Optional<DecodedJWT> decodedJWT = jwtTokenProvider.isValidToken(token); ​​​​​​​​​​​​if (decodedJWT.isEmpty()) { ​​​​​​​​​​​​​​​​return closeCallWithError(call, headers, Status.UNAUTHENTICATED, "유효하지 않은 토큰입니다."); ​​​​​​​​​​​​} ​​​​​​​​} catch (CustomJwtException e) { ​​​​​​​​​​​​return closeCallWithError(call, headers, Status.UNAUTHENTICATED, e.getMessage()); ​​​​​​​​} ​​​​​​​​// 검증 성공 시, 다음 핸들러 호출 ​​​​​​​​return next.startCall(call, headers); ​​​​} ​​​​/** * 인증 실패 시 gRPC 호출을 종료하고 에러 메시지를 반환합니다. * * @param call ServerCall 객체 ​​​​​* @param headers gRPC 헤더 ​​​​​* @param status 반환할 gRPC 상태 코드 ​​​​​* @param errorDesc 에러 설명 ​​​​​* @return 빈 ServerCall.Listener 객체 ​​​​​*/ ​​​​private <ReqT, RespT> ServerCall.Listener<ReqT> closeCallWithError(ServerCall<ReqT, RespT> call, Metadata headers, Status status, String errorDesc) { ​​​​​​​​log.warn("gRPC 호출 실패: {}", errorDesc); ​​​​​​​​ErrorResponse errorResponse = new ErrorResponse(false, errorDesc, "BAD_REQUEST"); ​​​​​​​​Metadata trailers = new Metadata(); ​​​​​​​​trailers.put(Key.of("error-details", Metadata.ASCII_STRING_MARSHALLER), toJson(errorResponse)); ​​​​​​​​call.close(status.withDescription(errorDesc), trailers); ​​​​​​​​return new ServerCall.Listener<>() { ​​​​​​​​}; // 빈 리스너 반환 ​​​​} ​​​​/** * ErrorResponse를 JSON 형식으로 변환합니다. * * @param errorResponse 에러 응답 객체 ​​​​​* @return JSON 형식의 문자열 ​​​​​*/ ​​​​private String toJson(ErrorResponse errorResponse) { ​​​​​​​​try { ​​​​​​​​​​​​return new ObjectMapper().writeValueAsString(errorResponse); ​​​​​​​​} catch (IOException e) { ​​​​​​​​​​​​log.error("JSON 변환 오류: {}", e.getMessage()); ​​​​​​​​​​​​return "{\"success\":false,\"message\":\"서버 오류\",\"httpStatus\":\"INTERNAL_SERVER_ERROR\"}"; ​​​​​​​​} ​​​​} }

 

  • 자원 서버로부터 받은 토큰 값을 gRPC 요청의 헤더에서 꺼내어 검증하는 클래스
  • gRPC는 HTTP 통신이 아니며 기본적으로 JSON 형태의 응답을 반환하지 않기 때문에, 예외 발생 시 에러 형태를 통일하기 위해 toJson() 메서드를 생성

 

> GrpcAuthServerService.java

@Slf4j @GrpcService @RequiredArgsConstructor public class GrpcAuthServerService extends AuthTokenServiceGrpc.AuthTokenServiceImplBase { ​​​​private final JwtTokenProvider jwtTokenProvider; ​​​​private final UserReader userReader; ​​​​@Override ​​​​public void verifyToken(AuthTokenProto.AuthTokenRequest request, StreamObserver<AuthTokenProto.AuthTokenResponse> responseObserver) { ​​​​​​​​String accessToken = request.getAccessToken(); ​​​​​​​​AuthTokenProto.AuthTokenResponse.Builder responseBuilder = AuthTokenProto.AuthTokenResponse.newBuilder(); ​​​​​​​​String username = jwtTokenProvider.getUsernameFromToken(accessToken).replace("\"", ""); ​​​​​​​​try { ​​​​​​​​​​​​User user = userReader.getUserByUsername(username); ​​​​​​​​​​​​UUID userId = user.getId(); ​​​​​​​​​​​​responseBuilder ​​​​​​​​​​​​​​​​​​​​.setUserId(String.valueOf(userId)) ​​​​​​​​​​​​​​​​​​​​.setUsername(username); ​​​​​​​​​​​​responseObserver.onNext(responseBuilder.build()); ​​​​​​​​} catch (CustomException e) { ​​​​​​​​​​​​log.error("사용자 조회 중 예외 발생: {}", e.getMessage()); ​​​​​​​​​​​​responseBuilder.setSuccess(false); ​​​​​​​​​​​​responseObserver.onNext(responseBuilder.build()); ​​​​​​​​} ​​​​​​​​responseObserver.onCompleted(); ​​​​} }
  • 유효한 액세스 토큰에 대한 인증을 수행하는 서비스 클래스.
  • 인증 처리: 클라이언트로부터 액세스 토큰을 받아 해당 토큰의 사용자 정보를 조회하여 응답 빌더 객체에 담아 반환
  • 응답 처리: 조회된 사용자 정보를 포함한 응답 객체를 생성하고, 사용자 정보를 반환
  • 예외 처리: 사용자 조회 중 예외가 발생할 경우, 응답 객체의 success 필드를 false로 설정하여 오류 정보를 클라이언트에 반환

6. postman으로 통신 테스트

Postman을 사용하여 인증 서버와 자원 서버 간의 gRPC 호출을 테스트합니다. 

 

자원서버로 gRPC가 잘 동작하는 지 postman 테스트를 실시합니다.

헤더에 Authorization의 이름으로 Bearer 형태의 토큰을 담아 요청을 보냅니다.

통신이 잘 되는 모습!!

 

토큰을 헤더에 담기 위해 interceptor 를 추가하였는데 해당 내용은 다음 포스트에서 좀 더 자세히 작성해보겠습니다!!

이 문서가 gRPC를 사용하여 인증 서버와 자원 서버를 연결하는 데 도움이 되길 바랍니다. (미래의 나에게도 ㅎ..) 추가 질문이나 필요하신 내용이 있다면 언제든지 말씀해 주세요 :)

'Server' 카테고리의 다른 글

HTTPS 설정하기  (0) 2022.04.28
  1. [gRPC 사용 계기]
  2. [연동 방법 진행 순서]
  3. 1. 각 build.gradle에 의존성 추가
  4. 2. 각 application.yml에 설정 추가
  5. 3. proto 파일 작성
  6. 4. 자원서버의 gRPC 통신 구현
  7. 5. 인증서버의 gRPC 통신 구현
  8. 6. postman으로 통신 테스트
'Server' 카테고리의 다른 글
  • HTTPS 설정하기
예령 : )
예령 : )
개발 공부를 하며 기록하고 있는 일기장입니다. 꾸준히 기록할 예정이니 많은 관심 부탁드립니다! :)
예령 : )
예령's 개발기록
예령 : )
전체
오늘
어제
  • 분류 전체보기 (98)
    • Github (2)
    • Java (1)
    • Spring & SpringBoot (10)
    • Server (8)
      • docker (6)
    • 개발 (6)
      • 자료구조 (2)
    • 스파르타코딩클럽 (66)
      • 웹개발의 봄, Spring (1)
      • 프로그래머스_Java_알고리즘 기초 (18)
      • 항해99 (39)
    • TIL (4)
    • Tech Conference (1)
    • AWS (0)

인기 글

최근 글

hELLO · Designed By 정상우.v4.2.0
예령 : )
[Java/SpringBoot] gRPC 연동 방법
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.