Springboot를 이용한 토이프로젝트 프로필 이미지처리를 위해 처음 Firebase Strorage를 사용해보았다.
springboot : 3.3.3
java : 17
firebase : firebase-admin:9.2.0
firebase strorage 이용을 위해 가입 이후에는 무료버전인 Spark 요금제인데 firebase strorage를 이용하기 위해서는 종량제 버전인 Blaze 요금제에 가입해야한다. 그러면 strorage에 1GB를 무료로 사용가능하며 이후는 사용량에 따라 요금이 부과되는 형식이다. (사실 무료치고 굉장히 적긴하다..)
새로운 프로젝트를 생성한다.
생성이후 프로젝트 설정 - 서비스 계정에서 언어에 맞는 Admin SDK 구성 스니펫코드와 키를 생성할 수 있다. 해당 코드는 이후 프로젝트에서 config 코드에 사용 예정이다. (Springboot java 사용으로 자바 코드를 복사하였다.)
이제부터 이곳에 이미지를 등록하고 가져와서 사용하게 된다.
이제 프로젝트로 돌아가서 firebase 설정을 마져 해보자.
firebase 사용을 위해 최신버전 gradle을 받아준다.
implementation("com.google.firebase:firebase-admin:9.2.0") // 최신 버전 확인
프로젝트 내부 resouces 아래에 포함하였다.
(git사용 시 키파일이 올라가지않도록 필수로 꼭 gitignore파일에 등록해주기)
프로젝트 실행 시 자동으로 firebase 정보를 받아올수 있도록 config로 설정해준다.
bucket()
FirebaseConfig.java
@Bean
public FirebaseApp firebaseApp() throws IOException{
List<FirebaseApp> firebaseApps = FirebaseApp.getApps();
if (!firebaseApps.isEmpty()) {
// 이미 초기화된 FirebaseApp이 있다면 첫 번째 FirebaseApp 반환
return firebaseApps.get(0);
}
FirebaseOptions options = FirebaseOptions.builder()
.setCredentials(
GoogleCredentials.fromStream(
new ClassPathResource("키파일 내부 위치").getInputStream()))
.setStorageBucket("firebasestorage 버킷명")
.build();
FirebaseApp app = FirebaseApp.initializeApp(options);
return app;
}
@Bean
public Bucket bucket() throws IOException{
return StorageClient.getInstance(firebaseApp()).bucket();
}
여기까지 Springboot에 firebase 설정을 마쳤다.
그럼 이제 실제 내부로직을 추가해 이미지 업로드, 이미지 가져오는 기능을 추가해보자.
이미지 업로드 화면 구성과 스크립트를 작성한다.
Mypage.html
<table>
<tr>
<td colspan="2">
// 프로필 이미지 노출
<img id ="myImage" src="업로드 이후 url" style="width: 200px;height: 200px;">
</td>
</tr>
<tr>
<td colspan="2">
<form id="uploadForm">
<label for="file">사진</label>
<input type="file" id="file" name="file" accept="image/*" required />
<button type="submit">업로드</button>
</form>
</td>
</tr>
</table>
// 이미지 업로드 해당 스크립트
$('#uploadForm').on('submit', function(event) {
var formData = new FormData();
formData.append('file', $('#file')[0].files[0]);
$.ajax({
url: '/uploadImg',
type: 'POST',
async: false,
data: formData,
contentType: false,
processData: false,
success: function(response) {
alert(response);
location.href = "/newMyPage";
},
error: function(xhr, status, error) {
alert(response);
}
});
});
ImageController.java
@PostMapping("/uploadImg")
public ResponseEntity<String> fileUpload(@RequestParam("file") MultipartFile multipartFile, HttpServletRequest request) throws IOException {
HttpSession session = request.getSession();
SessionVO sessionInfo = (SessionVO) session.getAttribute(SessionConst.SESSION_INFO);
if (!multipartFile.isEmpty()) {
imageService.saveImg(multipartFile, sessionInfo.getId());
return ResponseEntity.ok("파일 업로드 성공");
}else{
return ResponseEntity.status(500).body("파일 업로드 실패");
}
}
ImageSeviceImpl.java
@Transactional
@Override
public int saveImg(MultipartFile multipartFile, String loginId) throws IOException {
String fileName = loginId;
InputStream content = new ByteArrayInputStream(multipartFile.getBytes());
try{
bucket.create(fileName, content, multipartFile.getContentType());
}catch (Exception e){
e.getMessage();
return 0;
}
return 1;
}
ImageSeviceImpl.java
@Override
public String getImgUrl(String loginId) {
String encodedURL = "";
try{
if(bucket.get(loginId) == null){
// 이미지 없는 경우 디폴트 이미지로 노출
return "https://firebasestorage.googleapis.com/v0/b/firebase Storage 버킷명/o/default.png?alt=media";
}
String imagePath = loginId; // 이미지 파일 경로
String encodedImgPath = URLEncoder.encode(imagePath, "UTF-8");
encodedURL = "https://firebasestorage.googleapis.com/v0/b/firebase Storage 버킷명/o/"+ encodedImgPath + "?alt=media";
}catch (Exception e){
e.getMessage();
}
return encodedURL;
}
이렇게 구성하면 이미지를 로그인아이디로 가져오고 업로드 할 수 있게 된다. 하지만 1GB까지만 무료이기 때문에 현재 테스트만으로도 67KB를 사용해버렸다.
다음에는 같은 로직을 google cloud를 이용하는 방법으로 변경해볼까 한다.
https://popawaw.tistory.com/264
https://bellgod.tistory.com/107