* 이전내용 : https://lts0606.tistory.com/654
gRPC를 활용하여 파일을 주고받는 방법도 어렵지 않습니다.
proto 파일의 내용에서 파일 형식의 응답객체와, 해당 객체를 사용하는 메서드를 추가하여 줍니다.
* proto 파일 내용
syntax = "proto3";
option java_multiple_files = true;
option java_package = "kr.com.rts.proto";
option java_outer_classname = "HelloPrt";
package protocc;
service MyProtoService {
rpc giveMeData1(RequestMessage) returns (ResponseMessageStyle1); //송신 및 수신용 메소드1
rpc giveMeData2(RequestMessage) returns (ResponseMessageStyle2); //송신 및 수신용 메소드2
rpc giveMeData3(RequestMessage) returns (stream ResponseMessageStyle3); //stream 제어가 붙은 파일용 메소드
}
message RequestMessage { //요청하는 객체
string id = 1;
string name = 2;
float price = 3;
}
message ResponseMessageStyle1 { //결과받는 객체1
string result = 1;
string status = 2;
}
message ResponseMessageStyle2 { //결과받는 객체2
string result = 1;
string status = 2;
float statusCode = 3;
RequestMessage yourRequest = 4;
}
message ResponseMessageStyle3 { //파일용 바이트 객체
bytes file = 3;
}
기존의 proto 파일에서(새로 만들어도 됩니다) 파일과 관련된 항목을 추가 하였습니다.
bytes 자료형을 추가하면 해당 데이터는 파일을 주고받기 위한 바이트 데이터로 사용 할 수 있으며,
해당 파일을 통해 사용하는 메서드에 stream이라는 제어자를 붙여주면 스트림 객체로 데이터를 가져올 수 있습니다.
maven update 또는 maven generate-source를 통해서 신규 또는 변경된 내용을 적용받도록 해 준 다음에, 해당 내용을 서비스 클래스에 추가하여 봅니다.
* 사용하는 서비스
import io.grpc.stub.StreamObserver;
import kr.com.rts.proto.*;
import kr.com.rts.proto.RequestMessage;
import kr.com.rts.proto.ResponseMessageStyle1;
import kr.com.rts.proto.ResponseMessageStyle2;
import kr.com.rts.proto.ResponseMessageStyle3;
public class TestService extends MyProtoServiceGrpc.MyProtoServiceImplBase {
//생략..
@Override
public void giveMeData3(RequestMessage request, StreamObserver<ResponseMessageStyle3> responseObserver) {
File filePath = new File("보낼파일위치");
try (FileInputStream fis = new FileInputStream(filePath); BufferedInputStream bis = new BufferedInputStream(fis)) {
int bufferSize = 256 * 1024;// 256k
byte[] buffer = new byte[bufferSize];
int length;
while ((length = bis.read(buffer, 0, bufferSize)) != -1) { //스트림에 byte가 남아있지 않을 때 까지
responseObserver.onNext(ResponseMessageStyle3.newBuilder().setFile(ByteString.copyFrom(buffer, 0, length)).build()); //파일내용을 추가합니다.
}
responseObserver.onCompleted();
} catch (IOException e) {
e.printStackTrace();
}
}
}
원하는 파일을 위 코드 예제처럼 stream으로 가져와서 proto 타입에서 정의한 file 이름으로 추가하여 줍니다.
아래 처럼 file이름으로 주었기 때 문에 setFile 메서드를 통해 데이터를 넣어주면 됩니다.
이제 사용자의 요청 뒤에 파일을 전달해 주는 테스트 코드만 남았습니다.
기존 테스트 코드에서 아래 내용을 추가하였습니다.
* 테스트용 클래스
import static org.assertj.core.api.Assertions.assertThat;
import java.io.File;
import java.util.Iterator;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import com.google.common.io.ByteSink;
import com.google.common.io.FileWriteMode;
import com.google.common.io.Files;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import kr.com.rts.proto.MyProtoServiceGrpc;
import kr.com.rts.proto.RequestMessage;
import kr.com.rts.proto.ResponseMessageStyle1;
import kr.com.rts.proto.ResponseMessageStyle2;
import kr.com.rts.proto.ResponseMessageStyle3;
@SpringBootTest
class GRpcJavaApplicationTests {
@Test
void contextLoads() {
String url = "127.0.0.1:10777";
try {
ManagedChannel channel = ManagedChannelBuilder.forTarget(url).usePlaintext().build();
RequestMessage req2 = RequestMessage.newBuilder().setId("두번째 메시지").setName("두번째 메시지2").setPrice(554f)
.build();
MyProtoServiceGrpc.MyProtoServiceBlockingStub stub = MyProtoServiceGrpc.newBlockingStub(channel);
// 파일 요청 및 받기
ByteSink byteSink = Files.asByteSink(new File("저장할위치와이름"), FileWriteMode.APPEND);
Iterator<ResponseMessageStyle3> response3 = stub.giveMeData3(req2);
while (response3.hasNext()) { //데이터가 존재 할 때 까지
byteSink.write(response3.next().getFile().toByteArray());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
데이터를 가져오는 기능을 Files 클래스를 통해서 쉽게 구현하였습니다. * ByteSink는 Java 14부터 지원합니다.
코드 자체가 거의 직관적이라 그리 어렵지는 않았습니다.
아래 깃허브 주소는 위 내용에 사용된 소스코드를 올려놓은 주소 입니다.
https://github.com/TaeSeungRyu/sample/tree/main/gRPC샘플코드
SpringBoot gRPC 체험 후기를 작성 해 보았습니다.
아직까지 이것저것 해 보는 중이라 내용이 다소 틀릴 수 있습니다.
틀린 부분 또는 다른 의견은 언제든 환영 입니다! 👻
'Spring framework > Spring boot' 카테고리의 다른 글
[Springboot] Mongotemplate 에서 _class 제거 (0) | 2023.04.25 |
---|---|
[SpringBoot] Spring Security jwt 연동 하기 - 2023 (2) | 2023.04.07 |
SpringBoot gRPC 체험 후기 - 1 (0) | 2023.03.08 |
메이븐(maven) 환경에서 Q클래스 생성 (0) | 2022.11.22 |
스프링부트에서 모바일에 따른 뷰 페이지(Springboot mobile view) (2) | 2022.10.12 |
댓글