Avatar
๐Ÿ˜‰

Organizations

  • Spring์„ ํฌํ•จํ•œ Java ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ **VO(Value Object)**์™€ **DTO(Data Transfer Object)**๋Š” ๊ฐœ๋…์ ์œผ๋กœ ๋น„์Šทํ•ด ๋ณด์ผ ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ทธ ๋ชฉ์ ๊ณผ ์‚ฌ์šฉํ•˜๋Š” ๋งฅ๋ฝ์—์„œ ์ฐจ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์— ๊ฐ๊ฐ์„ ์„ค๋ช…ํ•˜๊ณ  ์ฐจ์ด๋ฅผ ์ •๋ฆฌํ• ๊ฒŒ์š”.


    1. VO (Value Object)

    • ์˜๋ฏธ: ๊ฐ’ ์ž์ฒด๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๊ฐ์ฒด. ๊ฐ’์˜ ๋™๋“ฑ์„ฑ์„ ๋น„๊ตํ•  ๋•Œ, ๊ฐ์ฒด์˜ ์ฐธ์กฐ๊ฐ€ ์•„๋‹ˆ๋ผ ๊ฐ’์ด ๊ฐ™์€์ง€๋กœ ํŒ๋‹จํ•ฉ๋‹ˆ๋‹ค.
    • ํŠน์ง•:
      • **๋ถˆ๋ณ€(Immutable)**ํ•˜๊ฒŒ ์„ค๊ณ„ํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค.
      • equals(), hashCode()๋ฅผ ์žฌ์ •์˜ํ•ด์„œ ๊ฐ’์ด ๊ฐ™์œผ๋ฉด ๋™์ผํ•œ ๊ฐ์ฒด๋กœ ๊ฐ„์ฃผํ•ฉ๋‹ˆ๋‹ค.
      • ์ฃผ๋กœ ๋„๋ฉ”์ธ ๋ชจ๋ธ์—์„œ ์‚ฌ์šฉ๋˜๋ฉฐ, ํŠน์ • ๊ฐœ๋…(์˜ˆ: ์ฃผ์†Œ, ๋ˆ, ์ด๋ฆ„ ๋“ฑ)์„ ์บก์Аํ™”ํ•ฉ๋‹ˆ๋‹ค.
    public class Address {
        private final String city;
        private final String street;
    
        public Address(String city, String street) {
            this.city = city;
            this.street = street;
        }
    
        // equals, hashCode ๋ฐ˜๋“œ์‹œ ์žฌ์ •์˜
    }
    

    2. DTO (Data Transfer Object)

    • ์˜๋ฏธ: ๊ณ„์ธต ๊ฐ„ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ์„ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๊ฐ์ฒด (์˜ˆ: Controller โ†’ Service โ†’ Repository)
    • ํŠน์ง•:
      • ๋ถˆ๋ณ€์ผ ํ•„์š” ์—†์Œ, Getter/Setter ์žˆ์Œ
      • ๋‹จ์ˆœํžˆ ๋ฐ์ดํ„ฐ๋ฅผ ์˜ฎ๊ธฐ๋Š” ๋ชฉ์  (๋กœ์ง์ด ์—†์–ด์•ผ ํ•จ)
      • ๋ณดํ†ต ์ž…๋ ฅ(Request), **์ถœ๋ ฅ(Response)**์šฉ์œผ๋กœ ๋งŽ์ด ์“ฐ์ž„
    public class UserResponseDto {
        private String name;
        private String email;
    
        // ๊ธฐ๋ณธ ์ƒ์„ฑ์ž, getter/setter
    }
    

    ์ •๋ฆฌ: VO vs DTO

    ํ•ญ๋ชฉ VO (Value Object) DTO (Data Transfer Object)
    ๋ชฉ์  ๊ฐ’ ์ž์ฒด๋ฅผ ํ‘œํ˜„ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ
    ๋ถˆ๋ณ€์„ฑ ๋ณดํ†ต ๋ถˆ๋ณ€ ๋ณดํ†ต ๊ฐ€๋ณ€
    ์‚ฌ์šฉ ์œ„์น˜ ๋„๋ฉ”์ธ ๋ชจ๋ธ ๊ณ„์ธต ๊ฐ„ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ
    equals/hashCode ๊ฐ’ ๊ธฐ์ค€์œผ๋กœ ์žฌ์ •์˜ ์ผ๋ฐ˜์ ์œผ๋กœ ์žฌ์ •์˜ํ•˜์ง€ ์•Š์Œ
    ๋กœ์ง ํฌํ•จ ๊ฐ€๋Šฅ ์—†์Œ (์ˆœ์ˆ˜ ๋ฐ์ดํ„ฐ๋งŒ)

    ์‚ฌ์šฉ ์˜ˆ์‹œ

    ๊ฐ„๋‹จํ•œ Spring ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌ์กฐ์—์„œ VO์™€ DTO์˜ ์ฐจ์ด๋ฅผ ์‹ค์ œ ์˜ˆ์ œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. ์˜ˆ์‹œ๋Š” โ€œ์‚ฌ์šฉ์ž(User) ์ •๋ณด ์ฒ˜๋ฆฌโ€๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

    Created Sun, 30 Mar 2025 17:14:05 +0900
  • JPA์ฟผ๋ฆฌ๋ฅผ ๋กœ๊ทธ๋กœ ์ถœ๋ ฅํ•˜๊ธฐ ์œ„ํ•œ yml ์„ค์ •

    Spring Boot์—์„œ JPA ์ฟผ๋ฆฌ๋ฅผ ๋กœ๊ทธ๋กœ ์ถœ๋ ฅํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด application.yml ํŒŒ์ผ์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์„ค์ •์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค:

    spring:
      jpa:
        show-sql: true # SQL ์ฟผ๋ฆฌ๋ฅผ ์ฝ˜์†”์— ์ถœ๋ ฅ
        properties:
          hibernate:
            format_sql: true # SQL ์ฟผ๋ฆฌ๋ฅผ ๋ณด๊ธฐ ์ข‹๊ฒŒ ํฌ๋งท
      logging:
        level:
          org.hibernate.SQL: debug         # ์‹คํ–‰๋˜๋Š” SQL ๋กœ๊ทธ
          org.hibernate.type.descriptor.sql.BasicBinder: trace # ๋ฐ”์ธ๋”ฉ๋˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’ ๋กœ๊ทธ
    

    ์„ค๋ช…:

    • show-sql: Hibernate๊ฐ€ ์‹คํ–‰ํ•˜๋Š” SQL์„ ํ‘œ์ค€ ์ถœ๋ ฅ์œผ๋กœ ๋ณด์—ฌ์คŒ (๊ฐ„๋‹จํ•œ ๋กœ๊ทธ).
    • format_sql: SQL ์ฟผ๋ฆฌ๋ฅผ ์ฝ๊ธฐ ์‰ฝ๊ฒŒ ์ค„๋ฐ”๊ฟˆ ๋ฐ ๋“ค์—ฌ์“ฐ๊ธฐ.
    • logging.level.org.hibernate.SQL: ๋” ์ƒ์„ธํ•œ SQL ๋กœ๊ทธ (๋กœ๊น… ํ”„๋ ˆ์ž„์›Œํฌ ํ†ตํ•ด ์ถœ๋ ฅ).
    • logging.level.org.hibernate.type.descriptor.sql.BasicBinder: SQL์— ๋ฐ”์ธ๋”ฉ๋˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๊นŒ์ง€ ์ถœ๋ ฅํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉ.

    ๐Ÿ’ก ํŒŒ๋ผ๋ฏธํ„ฐ ๋กœ๊ทธ๋Š” ๋ฏผ๊ฐ ์ •๋ณด๊ฐ€ ๋…ธ์ถœ๋  ์ˆ˜ ์žˆ์œผ๋‹ˆ ์šด์˜ ํ™˜๊ฒฝ์—์„œ๋Š” ์ฃผ์˜ํ•ด์„œ ์‚ฌ์šฉํ•˜์„ธ์š”.

    Created Fri, 28 Mar 2025 13:25:03 +0900
  • Spring Cloud Gateway์—์„œ globalcors ์„ค์ •

    • ํŠน์ • URI ํŒจํ„ด์— ๋Œ€ํ•ด์„œ๋งŒ CORS๋ฅผ ํ—ˆ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ์„ค์ •ํ•œ cors-configurations ํ‚ค์˜ ํŒจํ„ด์„ ์„ธ๋ถ„ํ™”ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
    • ํ˜„์žฌ๋Š” ‘/**‘๋กœ ๋ชจ๋“  ๊ฒฝ๋กœ์— ๋Œ€ํ•ด ํ—ˆ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ, ์ด๋ฅผ ์ œํ•œํ•˜๋ ค๋ฉด ์˜ˆ๋ฅผ ๋“ค์–ด /api/public/** ์ฒ˜๋Ÿผ ํŠน์ • ๊ฒฝ๋กœ๋กœ ์ขํ˜€์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

    Spring Cloud Gateway์—์„œ globalcors ์„ค์ •์„ ์‚ฌ์šฉํ•  ๋•Œ ํŠน์ • URI ํŒจํ„ด์— ๋Œ€ํ•ด์„œ๋งŒ CORS๋ฅผ ํ—ˆ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ์„ค์ •ํ•œ cors-configurations ํ‚ค์˜ ํŒจํ„ด์„ ์„ธ๋ถ„ํ™”ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ๋Š” '/\*\*'๋กœ ๋ชจ๋“  ๊ฒฝ๋กœ์— ๋Œ€ํ•ด ํ—ˆ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ, ์ด๋ฅผ ์ œํ•œํ•˜๋ ค๋ฉด ์˜ˆ๋ฅผ ๋“ค์–ด /api/public/** ์ฒ˜๋Ÿผ ํŠน์ • ๊ฒฝ๋กœ๋กœ ์ขํ˜€์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

    Created Fri, 28 Mar 2025 11:41:41 +0900
  • jwt ๊ด€๋ จ Tip

    Q. access token ์ด ๋งŒ๋ฃŒ๋˜๋ฉด, refresh token์„ ํ†ตํ•ด ์žฌ๋ฐœํ–‰ ํ•œ๋‹ค. refresh token์€ ๋งŒ๋ฃŒ ๊ธฐ๊ฐ„์ด ์—†์„๊นŒ?

    A. Refresh Token๋„ ๋ฐ˜๋“œ์‹œ ๋งŒ๋ฃŒ ๊ธฐ๊ฐ„์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    • ์ผ๋ฐ˜์ ์œผ๋กœ๋Š” Access Token๋ณด๋‹ค ํ›จ์”ฌ ๊ธด ๋งŒ๋ฃŒ ๊ธฐ๊ฐ„์„ ์„ค์ •ํ•  ๋ฟ์ด์—์š”.

    1. ์ผ๋ฐ˜์ ์ธ ๋งŒ๋ฃŒ ์‹œ๊ฐ„ ์„ค์ •

    • Access Token: ๋ณดํ†ต 15๋ถ„ ~ 1์‹œ๊ฐ„
    • Refresh Token: ๋ณดํ†ต 7์ผ ~ 30์ผ ๋˜๋Š” 90์ผ

    2. ์™œ Refresh Token๋„ ๋งŒ๋ฃŒ ๊ธฐ๊ฐ„์ด ํ•„์š”ํ•œ๊ฐ€?

    • Refresh Token์ด ์œ ์ถœ๋˜์—ˆ์„ ๊ฒฝ์šฐ, ๋ฌด์ œํ•œ์œผ๋กœ Access Token์„ ์žฌ๋ฐœ๊ธ‰๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋ณด์•ˆ์— ์น˜๋ช…์ ์ž…๋‹ˆ๋‹ค.
    • ์ผ์ • ๊ธฐ๊ฐ„์ด ์ง€๋‚˜๋ฉด ๋กœ๊ทธ์ธ ์„ธ์…˜์„ ์žฌํ™•์ธํ•˜๊ฑฐ๋‚˜ ์žฌ๋กœ๊ทธ์ธ์„ ์œ ๋„ํ•˜๋Š” ๊ฒƒ์ด ๋ณด์•ˆ์ƒ ๋” ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

    3. ์ €์žฅ ์œ„์น˜๋Š”?

    • Refresh Token์€ ๋ณดํ†ต ์„œ๋ฒ„ ์ €์žฅ ๋ฐฉ์‹ (e.g., Redis)์— ์ €์žฅํ•˜๊ณ , ์‚ฌ์šฉ์ž์—๊ฒŒ๋Š” ์‹๋ณ„์ž๋งŒ ์ „๋‹ฌํ•˜๊ฑฐ๋‚˜ ํด๋ผ์ด์–ธํŠธ์— ์ €์žฅํ•˜๋˜ ๋ณด์•ˆ์ ์œผ๋กœ ์•ˆ์ „ํ•œ ์ €์žฅ์†Œ (e.g., Secure Cookie, LocalStorage X) ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค.

    Q. Spring Boot์—์„œ์˜ ์˜ˆ์‹œ

    A. Spring Boot์—์„œ JWT ๊ธฐ๋ฐ˜์œผ๋กœ Access Token๊ณผ Refresh Token์„ ๋ฐœ๊ธ‰ ๋ฐ ์žฌ๋ฐœ๊ธ‰ํ•˜๋Š” ๊ธฐ๋ณธ์ ์ธ ๊ตฌ์กฐ๋ฅผ ์˜ˆ์‹œ


    1. ํ† ํฐ ์ƒ์„ฑ ํด๋ž˜์Šค (JwtProvider)

    @Component
    public class JwtProvider {
    
        private final String secretKey = "yourSecretKey"; // ์ ์ ˆํžˆ ์•”ํ˜ธํ™” ํ•„์š”
        private final long accessTokenValidity = 1000L * 60 * 15;  // 15๋ถ„
        private final long refreshTokenValidity = 1000L * 60 * 60 * 24 * 14; // 14์ผ
    
        public String createAccessToken(String userId) {
            return createToken(userId, accessTokenValidity);
        }
    
        public String createRefreshToken(String userId) {
            return createToken(userId, refreshTokenValidity);
        }
    
        private String createToken(String userId, long validity) {
            Claims claims = Jwts.claims().setSubject(userId);
            Date now = new Date();
            Date expiry = new Date(now.getTime() + validity);
    
            return Jwts.builder()
                    .setClaims(claims)
                    .setIssuedAt(now)
                    .setExpiration(expiry)
                    .signWith(SignatureAlgorithm.HS256, secretKey)
                    .compact();
        }
    
        public String getUserIdFromToken(String token) {
            return Jwts.parser().setSigningKey(secretKey)
                    .parseClaimsJws(token).getBody().getSubject();
        }
    
        public boolean validateToken(String token) {
            try {
                Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token);
                return true;
            } catch (ExpiredJwtException e) {
                return false;
            }
        }
    }
    

    2. ๋กœ๊ทธ์ธ ์‹œ ํ† ํฐ ๋ฐœ๊ธ‰

    @PostMapping("/login")
    public ResponseEntity<TokenResponse> login(@RequestBody LoginRequest request) {
        // ์ธ์ฆ ์ฒ˜๋ฆฌ (์ƒ๋žต)
        String userId = "user-id";
    
        String accessToken = jwtProvider.createAccessToken(userId);
        String refreshToken = jwtProvider.createRefreshToken(userId);
    
        // Refresh Token์„ DB๋‚˜ Redis์— ์ €์žฅ
        refreshTokenService.save(userId, refreshToken);
    
        return ResponseEntity.ok(new TokenResponse(accessToken, refreshToken));
    }
    

    3. Access Token ๋งŒ๋ฃŒ ์‹œ Refresh Token์œผ๋กœ ์žฌ๋ฐœ๊ธ‰

    @PostMapping("/token/refresh")
    public ResponseEntity<TokenResponse> refreshToken(@RequestBody TokenRequest request) {
        String refreshToken = request.getRefreshToken();
    
        if (!jwtProvider.validateToken(refreshToken)) {
            throw new RuntimeException("Invalid refresh token");
        }
    
        String userId = jwtProvider.getUserIdFromToken(refreshToken);
    
        // ์ €์žฅ๋œ refresh token๊ณผ ๋น„๊ต
        String stored = refreshTokenService.get(userId);
        if (!stored.equals(refreshToken)) {
            throw new RuntimeException("Token mismatch");
        }
    
        String newAccessToken = jwtProvider.createAccessToken(userId);
        return ResponseEntity.ok(new TokenResponse(newAccessToken, refreshToken));
    }
    

    4. Refresh Token ์ €์žฅ ์˜ˆ์‹œ (Redis ๊ธฐ๋ฐ˜)

    @Service
    public class RefreshTokenService {
    
        private final RedisTemplate<String, String> redisTemplate;
    
        public RefreshTokenService(RedisTemplate<String, String> redisTemplate) {
            this.redisTemplate = redisTemplate;
        }
    
        public void save(String userId, String token) {
            redisTemplate.opsForValue().set(userId, token, 14, TimeUnit.DAYS); // ์œ ํšจ ๊ธฐ๊ฐ„ ์„ค์ •
        }
    
        public String get(String userId) {
            return redisTemplate.opsForValue().get(userId);
        }
    }
    

    Q. ์—์‹œ์—์„œ RefreshToken ์—์„œ refresh save์ „์— ๊ธฐ์กด๊บผ๋Š” ์•ˆ์ง€์›Œ๋„ ๋ ๊นŒ?

    A. ์ผ๋ฐ˜์ ์œผ๋กœ๋Š” ๊ธฐ์กด Refresh Token์„ ์‚ญ์ œํ•˜๊ฑฐ๋‚˜ ๋ฎ์–ด์จ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    ์™œ๋ƒ๋ฉด:

    Created Thu, 27 Mar 2025 11:36:45 +0900
  • Spring Boot์—์„œ Kafka๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์˜ค๋ฅ˜๋ฅผ ์ฝ”๋“œ๋กœ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ด๋ณผ๊ฒŒ์š”.
    Kafka ํ”„๋กœ๋“€์„œ์™€ ์ปจ์Šˆ๋จธ์—์„œ Fallback ๋ฉ”์†Œ๋“œ, ์žฌ์‹œ๋„ (Retry), ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋“ฑ์„ ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ด…๋‹ˆ๋‹ค.


    1. Kafka ํ”„๋กœ๋“€์„œ์—์„œ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ (Fallback, Retry)

    Kafka ํ”„๋กœ๋“€์„œ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋ธŒ๋กœ์ปค๋กœ ๋ณด๋‚ด๋Š” ๊ณผ์ •์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    ์˜ˆ๋ฅผ ๋“ค์–ด, ๋„คํŠธ์›Œํฌ ๋ฌธ์ œ, ๋ธŒ๋กœ์ปค ๋‹ค์šด, ๋ฉ”์‹œ์ง€ ํฌ๊ธฐ ์ดˆ๊ณผ ๋“ฑ์˜ ๋ฌธ์ œ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๋Š”๋ฐ์š”, ์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

    โœ… (1) Fallback ๋ฉ”์†Œ๋“œ ์ ์šฉ (Resilience4j ์‚ฌ์šฉ)

    Resilience4j์˜ @Retry์™€ @Recover๋ฅผ ํ™œ์šฉํ•˜๋ฉด
    Kafka ์ „์†ก์ด ์‹คํŒจํ–ˆ์„ ๋•Œ ์ž๋™์œผ๋กœ ์žฌ์‹œ๋„๋ฅผ ํ•˜๊ณ , ์ตœ์ข…์ ์œผ๋กœ ์‹คํŒจํ•˜๋ฉด ๋Œ€์ฒด ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    Created Wed, 26 Mar 2025 13:38:03 +0900
  • Apache Kafka ์‚ฌ์šฉ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์ฃผ์š” ์˜ค๋ฅ˜ ์œ ํ˜•๊ณผ ๊ทธ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ •๋ฆฌํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


    1. ๋„คํŠธ์›Œํฌ ๋ฐ ์—ฐ๊ฒฐ ์˜ค๋ฅ˜

    โŒ ์˜ค๋ฅ˜: Connection to broker <broker_id> failed

    ๐Ÿ“Œ ์›์ธ: ๋ธŒ๋กœ์ปค์™€์˜ ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ ๋ฌธ์ œ, ๋ธŒ๋กœ์ปค ๋‹ค์šด, ๋ฐฉํ™”๋ฒฝ ๋ฌธ์ œ ๋“ฑ
    โœ… ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•:

    • zookeeper์™€ broker๊ฐ€ ์‹คํ–‰ ์ค‘์ธ์ง€ ํ™•์ธ (ps aux | grep kafka)
    • listeners ๋ฐ advertised.listeners ์„ค์ • ํ™•์ธ (server.properties)
    • ๋ฐฉํ™”๋ฒฝ ์„ค์ • (iptables -L, firewalld)์„ ์ ๊ฒ€ํ•˜์—ฌ ํฌํŠธ๊ฐ€ ์—ด๋ ค ์žˆ๋Š”์ง€ ํ™•์ธ

    2. ๋ธŒ๋กœ์ปค ๋ฐ ํ† ํ”ฝ ๊ด€๋ จ ์˜ค๋ฅ˜

    โŒ ์˜ค๋ฅ˜: Leader not available for partition <partition_id>

    ๐Ÿ“Œ ์›์ธ:

    Created Wed, 26 Mar 2025 13:30:03 +0900