Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/main/java/com/likelion/picklbe/domain/brand/Brand.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,14 @@ public String filename() {
return filename;
}

public String displayName() { // getter
public String displayName() {
return displayName;
}

public static Brand fromStoreName(String name) {
if (name == null || name.isBlank()) {
return DEFAULT;
}
// μš°μ„ μˆœμœ„: μ—λΈŒλ¦¬λ°μ΄ β†’ 이마트 λ“± (μ„ μ–Έ μˆœμ„œ μœ μ§€)
for (Brand b : values()) {
if (b == DEFAULT) {
continue;
Expand All @@ -110,4 +109,17 @@ public static Brand fromStoreName(String name) {
}
return DEFAULT;
}

public static Brand fromCodeSafe(String code) {
if (code == null || code.isBlank()) {
return DEFAULT;
}
for (Brand b : values()) {
if (b.code.equalsIgnoreCase(code)) {
return b;
}
}
return DEFAULT;
}
}

118 changes: 105 additions & 13 deletions src/main/java/com/likelion/picklbe/domain/brand/BrandImageResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,151 @@

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

@Component
public class BrandImageResolver {

// ex) https://picklocal.s3.ap-northeast-2.amazonaws.com
@Value("${app.cdn.base-url:https://picklocal.s3.ap-northeast-2.amazonaws.com}")
private String baseUrl;

@Value("${app.cdn.brand-path:brands}")
@Value("${app.cdn.brand-path:images/brand}")
private String brandPath;

@Value("${app.cdn.default-file:mart_default.png}")
private String defaultFile;

/** 원문(지점λͺ…/μƒν˜Έλͺ…/λΈŒλžœλ“œλͺ… 포함 κ°€λŠ₯)μ—μ„œ Brand enum을 μΆ”μ • */
/**
* 원문(지점λͺ…/μƒν˜Έλͺ…/λΈŒλžœλ“œλͺ… 포함 κ°€λŠ₯)μ—μ„œ Brand enum을 μΆ”μ •
*/
public Brand resolveBrand(String raw) {
if (raw == null || raw.isBlank()) {
if (!StringUtils.hasText(raw)) {
return Brand.DEFAULT;
}
return Brand.fromStoreName(raw);
}

/** Brand μ½”λ“œλ§Œ ν•„μš”ν•  λ•Œ */
/**
* explicitBrand(컬럼) μš°μ„ , μ—†μœΌλ©΄ name(지점λͺ…)으둜 μΆ”μ •
*/
public Brand resolveBrand(String explicitBrand, String name) {
if (StringUtils.hasText(explicitBrand)) {
// fromStoreName κ°€ λΈŒλžœλ“œλͺ…도 νŒŒμ‹±ν•œλ‹€λŠ” μ „μ œ
return resolveBrand(explicitBrand);
}
return resolveBrand(name);
}

/**
* Brand μ½”λ“œλ§Œ ν•„μš”ν•  λ•Œ
*/
public String resolveBrandCode(String raw) {
return resolveBrand(raw).code();
}

/** μ›λ¬Έμ—μ„œ λ°”λ‘œ λŒ€ν‘œ 이미지 URL */
/**
* Brand μ½”λ“œλ§Œ 이미 μžˆλŠ” 경우(예: DB 쑰회)
*/
public String resolveBrandCodeFromCode(String brandCode) {
Brand b = Brand.fromCodeSafe(brandCode); // μ—†μœΌλ©΄ DEFAULT λ°˜ν™˜ν•˜λ„λ‘ enum에 κ΅¬ν˜„λ˜μ–΄ μžˆμ–΄μ•Ό 함
return b.code();
}

/**
* μ›λ¬Έμ—μ„œ λ°”λ‘œ λŒ€ν‘œ 이미지 URL
*/
public String resolveImageUrl(String raw) {
return imageUrlFor(resolveBrand(raw));
}

/** Brandκ°€ 이미 μžˆλŠ” 경우 이미지 URL */
/**
* explicitBrand + name λ™μ‹œ κ³ λ €
*/
public String resolveImageUrl(String explicitBrand, String name) {
return imageUrlFor(resolveBrand(explicitBrand, name));
}

/**
* Brandκ°€ 이미 μžˆλŠ” 경우 이미지 URL
*/
public String imageUrlFor(Brand brand) {
// 1) brandκ°€ null/DEFAULT μ΄κ±°λ‚˜ 파일λͺ…이 λΉ„μ–΄μžˆμœΌλ©΄ κΈ°λ³Έ 이미지
String filename =
(brand == null || brand == Brand.DEFAULT || brand.filename() == null)
(brand == null || brand == Brand.DEFAULT || !StringUtils.hasText(brand.filename()))
? defaultFile
: brand.filename();
return String.format("%s/%s/%s", rtrim(baseUrl), rtrim(brandPath), filename);

// 2) filename μžμ²΄κ°€ μ ˆλŒ€ URL이면 κ·ΈλŒ€λ‘œ λ°˜ν™˜ (운영 쀑 전체 URL을 enum에 넣은 경우 λŒ€μ‘)
if (isAbsoluteUrl(filename)) {
return filename;
}

// 3) baseUrl/brandPath μ•ˆμ „ μ‘°ν•©
return joinUrl(rtrimSlashes(baseUrl), rtrimSlashes(brandPath), filename);
}

/** μ›λ¬Έμ—μ„œ Brand와 이미지 URL을 ν•œ λ²ˆμ— */
/**
* Brand μ½”λ“œλ‘œ λ°”λ‘œ 이미지 URL (μ½”λ“œλ§Œ λ‚΄λ €λ°›λŠ” API/쿼리 λŒ€μ‘)
*/
public String imageUrlForCode(String brandCode) {
Brand b = Brand.fromCodeSafe(brandCode);
return imageUrlFor(b);
}

/**
* μ›λ¬Έμ—μ„œ Brand와 이미지 URL/μ½”λ“œλ₯Ό ν•œ λ²ˆμ—
*/
public ResolvedBrand resolve(String raw) {
Brand b = resolveBrand(raw);
return new ResolvedBrand(b, imageUrlFor(b), b.code());
}

private String rtrim(String s) {
if (s == null || s.isBlank()) {
/**
* explicitBrand + name λ™μ‹œ μž…λ ₯ 버전
*/
public ResolvedBrand resolve(String explicitBrand, String name) {
Brand b = resolveBrand(explicitBrand, name);
return new ResolvedBrand(b, imageUrlFor(b), b.code());
}

// ---- helpers -------------------------------------------------------------

private static boolean isAbsoluteUrl(String s) {
if (!StringUtils.hasText(s)) {
return false;
}
String t = s.trim().toLowerCase();
return t.startsWith("http://") || t.startsWith("https://");
}

private static String rtrimSlashes(String s) {
if (!StringUtils.hasText(s)) {
return "";
}
return s.replaceAll("/+$", "");
}

/** 편의 λ°˜ν™˜ DTO */
public record ResolvedBrand(Brand brand, String imageUrl, String code) {}
private static String joinUrl(String... parts) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < parts.length; i++) {
String p = parts[i] == null ? "" : parts[i].trim();
if (p.isEmpty()) {
continue;
}
if (sb.length() > 0 && sb.charAt(sb.length() - 1) != '/') {
sb.append('/');
}
sb.append(p.replaceAll("^/+", "")); // μ•ž μŠ¬λž˜μ‹œ 제거
}
return sb.toString();
}

/**
* 편의 λ°˜ν™˜ DTO
*/
public record ResolvedBrand(Brand brand, String imageUrl, String code) {

}
}

11 changes: 7 additions & 4 deletions src/main/java/com/likelion/picklbe/global/config/S3Config.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package com.likelion.picklbe.global.config;

import jakarta.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import jakarta.annotation.PostConstruct;

import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Getter
@Configuration
Expand Down
Loading