enginner_s2eojeong

Jackson ๋งคํ•‘ ์˜ค๋ฅ˜: JSON ํ•„๋“œ์™€ Java ํ•„๋“œ ๋ถˆ์ผ์น˜ ๋ฌธ์ œ ํ•ด๊ฒฐํ•˜๊ธฐ (feat. ๋ชจ๋ธ api ์—ฐ๊ฒฐ) ๋ณธ๋ฌธ

Backend/SpringBoot

Jackson ๋งคํ•‘ ์˜ค๋ฅ˜: JSON ํ•„๋“œ์™€ Java ํ•„๋“œ ๋ถˆ์ผ์น˜ ๋ฌธ์ œ ํ•ด๊ฒฐํ•˜๊ธฐ (feat. ๋ชจ๋ธ api ์—ฐ๊ฒฐ)

_danchu 2025. 2. 21. 02:23

Recipe-Recommender Model

๋”๋ณด๊ธฐ

๐Ÿ’กGoal : ์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ€์ž… ์‹œ ๋“ฑ๋กํ•œ ์•Œ๋ ˆ๋ฅด๊ธฐ ์ •๋ณด์™€ ์„ ํ˜ธ๋„๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ '์˜ค๋Š˜์˜ ์ถ”์ฒœ ๋ ˆ์‹œํ”ผ'๋ฅผ ์ œ๊ณต

JSON ์š”์ฒญ: user_id

JSON ์‘๋‹ต: recipe_id

 

๋ฌธ์ œ

๋ฐ์ดํ„ฐ/ai ํŒ€์—์„œ ์ „๋‹ฌ๋ฐ›์€ input, output ๊ฐ’์„ ๋ฐ”ํƒ•์œผ๋กœ ๋ชจ๋ธ api์— user_id๋ฅผ ๋„˜๊ธฐ๊ณ , recipe_id๋ฅผ ๋ฐ›์•„์˜ค๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์˜€๋‹ค.

๊ทผ๋ฐ Postman์œผ๋กœ GET localhost:8080/api/recipes/recommend ์š”์ฒญ์„ ๋ณด๋ƒˆ๋”๋‹ˆ json ํ•„๋“œ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค.

 

RestTemplate์€ ๊ธฐ๋ณธ์ ์œผ๋กœ Jackson์„ ์‚ฌ์šฉํ•ดMap<String, Object>๋ฅผ JSON์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— {"user_id": "146"} ๊ฐ™์€ JSON ํ˜•ํƒœ๋กœ ๋ชจ๋ธ API์— ์ „์†ก๋œ๋‹ค.

์‘๋‹ต ๋ฐ์ดํ„ฐ ๋˜ํ•œ Map<String, Object> ํ˜•ํƒœ๋กœ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋ธ API๊ฐ€ JSON ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด, response.getBody()๊ฐ€ ์ด๋ฅผ {"recipe_id": 112}์™€ ๊ฐ™์€ JSON ํ˜•์‹์œผ๋กœ ์ „๋‹ฌ๋œ๋‹ค.

 

๋ฐ์ดํ„ฐ/ai ํŒ€์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ•„๋“œ๋ช…์„ ๋ฐ”ํƒ•์œผ๋กœ ์„ค๊ณ„๋ฅผ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— Java ๊ฐ์ฒด์™€ ํ•„๋“œ๋ช…์ด ๋‹ค๋ฅด๋‹ค๋Š”๊ฑธ ์—ผ๋‘์— ๋‘๊ณ  ๊ฐ’์„ ์ „๋‹ฌํ•  ๋•Œ์™€ ๋ฐ›์„ ๋•Œ ๋ชจ๋‘ ์ž˜ ๋งคํ•‘์„ ํ•ด๋†จ๋Š”๋ฐ๋„ ์ž๊พธ ๋งคํ•‘๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์—๋Ÿฌ๊ฐ€ ๋– ์„œ ๋กœ๊ทธ๋ฅผ ์ฐ์–ด๋ณด์•˜๋‹ค.

Map<String, Object> requestPayload = Map.of("user_id", userId);

try {
    ResponseEntity<Map<String, Object>> response = restTemplate.exchange(
            recipeRecommendApiUrl,
            HttpMethod.POST,
            new HttpEntity<>(requestPayload),
            new ParameterizedTypeReference<>() {
            }
    );

    log.info("Calling AI model with userId: {}", userId);

    Map<String, Object> responseBody = response.getBody();
    if (!responseBody.containsKey("recipe_id")) {
        log.error("AI ๋ชจ๋ธ ์‘๋‹ต์— recipeId๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.");
        return new RecipeRecommendResponseDTO(null, null, null);
    }

    .
    .
    .
    
    // ์ถ”์ฒœ ๋ ˆ์‹œํ”ผ ๋ฐ˜ํ™˜
    return new RecipeRecommendResponseDTO(
                                recipe.getId(),
                                recipe.getImagePath(),
                                recipe.getRecipeName());

    } catch (HttpClientErrorException e){
        log.error("AI ๋ชจ๋ธ API ํ˜ธ์ถœ ์‹คํŒจ: {}", e.getStatusCode());
        return new RecipeRecommendResponseDTO(null, null, null);
    }

 

์ผ๋‹จ ๋กœ๊ทธ๋ฅผ ํ†ตํ•ด userId๋Š” ๋ชจ๋ธ์— ์ž˜ ์ „๋‹ฌ๋˜๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ๋‹ค. 

Calling AI model with userId: 146

 

recipe_id๊ฐ€ ๋„๊ฐ’์ด์—ˆ๋‹ค๋ฉด ์ถœ๋ ฅ๋˜์–ด์•ผ ํ•  "AI ๋ชจ๋ธ ์‘๋‹ต์— recipeId๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค."๋Š” ์ถœ๋ ฅ๋˜์ง€ ์•Š์€๊ฑธ ๋ณด์•„ recipe_id ๊ฐ’์€ ์žˆ์ง€๋งŒ ์ œ๋Œ€๋กœ ๋งคํ•‘์ด ๋˜์ง€์•Š์•˜์Œ์„ ์•Œ ์ˆ˜ ์žˆ์—ˆ๋‹ค. ๋‹ค์Œ์œผ๋กœ ์˜์‹ฌํ•ด๋ณธ๊ฑด ๊ทธ ์•„๋ž˜์— ์œ„์น˜ํ•œ ์ตœ์ข… ์‘๋‹ต๊ฐ’์ธ RecipeRecommendResponseDTO์˜€๋‹ค.

 

๊ฐ’์„ ๋‹ด์•„ ๋ฐ˜ํ™˜ํ•˜๋Š” RecipeRecommendResponseDTO์—์„œ๋Š” ์—ฌ์ „ํžˆ ํ•„๋“œ๋ช…์„ recipeId๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์–ด์„œ ๋ฐœ์ƒํ•œ ๋ฌธ์ œ์˜€๋‹ค..!

์ด ๋•Œ๋ฌธ์— JSON ํ•„๋“œ๋ช…(recipe_id)๊ณผ DTO ํ•„๋“œ๋ช…(recipeId)์ด ์ผ์น˜ํ•˜์ง€ ์•Š์•„์„œ Jackson์ด ์ž๋™์œผ๋กœ ๋งคํ•‘ํ•˜์ง€ ๋ชปํ•œ ๊ฒƒ์ด๋‹ค.

 

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

@JsonProperty๋ฅผ ์‚ฌ์šฉํ•ด์„œ JSON ํ•„๋“œ๋ช…์„ Java ํ•„๋“œ์— ๋ช…์‹œ์ ์œผ๋กœ ๋งคํ•‘ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

 

์งœ์ž” ์ด์   ์˜ค๋Š˜์˜ ์ถ”์ฒœ ๋ ˆ์‹œํ”ผ๊ฐ€ ์ž˜ ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค :)