Firebase Storage 이용한 이미지 업로드 처리(with Springboot )

byteofprl·2025년 2월 2일
0
post-thumbnail

Springboot를 이용한 토이프로젝트 프로필 이미지처리를 위해 처음 Firebase Strorage를 사용해보았다.

  • 사용목적을 간단한 프로필 이미지 업로드 이후 마이페이지에서 노출하고 이미지를 변경하는 방법을 정리해보았다.

버전정보

springboot : 3.3.3
java : 17
firebase : firebase-admin:9.2.0

1. firebase 가입 후 Blaze 요금제 가입

https://firebase.google.com/

firebase strorage 이용을 위해 가입 이후에는 무료버전인 Spark 요금제인데 firebase strorage를 이용하기 위해서는 종량제 버전인 Blaze 요금제에 가입해야한다. 그러면 strorage에 1GB를 무료로 사용가능하며 이후는 사용량에 따라 요금이 부과되는 형식이다. (사실 무료치고 굉장히 적긴하다..)

2. firebase 프로젝트 생성 이후 설정

새로운 프로젝트를 생성한다.

생성이후 프로젝트 설정 - 서비스 계정에서 언어에 맞는 Admin SDK 구성 스니펫코드와 키를 생성할 수 있다. 해당 코드는 이후 프로젝트에서 config 코드에 사용 예정이다. (Springboot java 사용으로 자바 코드를 복사하였다.)

3. firebase Storage를 생성한다.

이제부터 이곳에 이미지를 등록하고 가져와서 사용하게 된다.

이제 프로젝트로 돌아가서 firebase 설정을 마져 해보자.

1. Springboot gradle 설정

firebase 사용을 위해 최신버전 gradle을 받아준다.

implementation("com.google.firebase:firebase-admin:9.2.0") // 최신 버전 확인

2. firebase 키파일 프로젝트에 등록

프로젝트 내부 resouces 아래에 포함하였다.
(git사용 시 키파일이 올라가지않도록 필수로 꼭 gitignore파일에 등록해주기)

3. firebase config 생성

프로젝트 실행 시 자동으로 firebase 정보를 받아올수 있도록 config로 설정해준다.

  • 파일경로는 copy path로 Path From source Root 경로 입력해준다.
  • firebasestorage 버킷명은 gs:// 제외한 뒤에 이름을 입력해준다.

bucket()

  • 이후 이미지정보를 가져오기 위해 bucket()도 config에 추가해준다.

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 설정을 마쳤다.

그럼 이제 실제 내부로직을 추가해 이미지 업로드, 이미지 가져오는 기능을 추가해보자.

1. 이미지 업로드 기능 구현

1. 화면 구성

이미지 업로드 화면 구성과 스크립트를 작성한다.

  • ajax 결과에서 이미지가 정상적으로 업로드 되었는지 노출한다.

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);
            }
        });
    });

2. 내부 로직기능 - 이미지 업로드

  • 사용목적이 프로필 이미지이므로 아이디 당 1개 이상일 필요가 없어서 파일명을 로그인아이디로 구성하고 업로드하는 로직으로 구현하였다. (아이디가 고유한 값이기 때문에)

ImageController.java

  • 해당 리턴으로 ajax alert창에 노출된다.
@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

  • 위와 같은 설명으로 bucket에 업로드 시 fileName에 loginId가 들어가게 된다.
@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;
    }

2. 내부 로직기능 - 이미지 가져오기

  • 프로필이 저장되어 있지 않은 경우에는 Storage에 저장해놓은 default.png를 불러오도록 하였다.
  • 마이페이지 접근 시 해당 메서드를 함께 호출하여 해당 url정보를 가져가도록 구성하고 html에서 img src로 노출하면 해당 이미지가 보이게 된다.

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를 이용하는 방법으로 변경해볼까 한다.

Firebase Storage 설정 참고 URL

https://popawaw.tistory.com/264
https://bellgod.tistory.com/107

0개의 댓글

관련 채용 정보