SerialVersionUID๋ฅผ ์„ ์–ธํ•ด์•ผ ํ•˜๋Š” ์ด์œ 

2024. 11. 28. 04:26ยท๐Ÿ“‚ programming-language/java
JCF ์˜ HashMap ์ฝ”๋“œ๋ฅผ ๋ณด๋‹ค๊ฐ€ SerialVersionUID ๋ฅผ ๋ณด๊ณ  ํ˜ธ๊ธฐ์‹ฌ์— ํ•™์Šตํ•œ ๋‚ด์šฉ

 

 

 

1. ํด๋ž˜์Šค์˜ ๊ธฐ๋ณธ ํ•ด์‹œ๊ฐ’์„ ํ†ตํ•œ SerialVersionUID ์˜ ๋ฌธ์ œ

  1. ํด๋ž˜์Šค์˜ ๊ตฌ์กฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
    • ์˜ˆ์‹œ: ๋ฉค๋ฒ„ ๋ณ€์ˆ˜ ํƒ€์ž… ๋ณ€๊ฒฝ, ๋ฉค๋ฒ„ ๋ณ€์ˆ˜ ์‚ญ์ œ
  2. ํ”„๋ ˆ์ž„์›Œํฌ ๋˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์ œ๊ณตํ•˜๋Š” ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋„ ๋ฒ„์ „์—…์„ ํ†ตํ•ด SerialVersionUID๊ฐ€ ๋ณ€๊ฒฝ๋  ๊ฒฝ์šฐ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ์˜ˆ์ƒํ•˜์ง€ ๋ชปํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

 

2. SerialVersionUID??

  1. SUID ๋Š” ์ง๋ ฌํ™”์™€ ์—ญ์ง๋ ฌํ™” ๊ณผ์ •์—์„œ ๊ฐ’์ด ์„œ๋กœ ๋งž๋Š”์ง€ ํ™•์ธํ•œ ํ›„์— ์ฒ˜๋ฆฌํ•œ๋‹ค.(๋งž์ง€ ์•Š๋‹ค๋ฉด InvalidClassException ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.)
  2. ์ž๋ฐ”์˜ ์ง๋ ฌํ™” ์ŠคํŽ™ ์ •์˜๋ฅผ ์‚ดํŽด๋ณด๋ฉด SUID ๊ฐ’์€ ํ•„์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ฉฐ ์„ ์–ธ๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฉด ํด๋ž˜์Šค์˜ ๊ธฐ๋ณธ ํ•ด์‹œ๊ฐ’์„ ์‚ฌ์šฉํ•œ๋‹ค. (์ด ๊ฐ’๋“ค์€ ํด๋ž˜์Šค์˜ ์ด๋ฆ„, ์ƒ์„ฑ์ž ๋“ฑ๊ณผ ๊ฐ™์ด ํด๋ž˜์Šค์˜ ๊ตฌ์กฐ๋ฅผ ์ด์šฉํ•ด์„œ ์ƒ์„ฑ)

 

ํ•„๋“œ ์ถ”๊ฐ€ ํ›„ ์—ญ์ง๋ ฌํ™”๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•จ์„ ํ™•์ธํ•˜๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ

class DefaultSerialEntity implements Serializable {

    private String title;
    private String pressName;
    private String reporterName;

    // ์ƒˆ๋กœ์šด ํ•„๋“œ ์ถ”๊ฐ€
    private String phoneNumber;

    public DefaultSerialEntity(String title, String pressName, String reporterName) {
        this.title = title;
        this.pressName = pressName;
        this.reporterName = reporterName;
    }

    @Override
    public String toString() {
        return "Article{" +
                "title='" + title + '\'' +
                ", pressName='" + pressName + '\'' +
                ", reporterName='" + reporterName + '\'' +
                '}';
    }
}

// test code
class DefaultSerialEntityTest {
    
    @Test
    @DisplayName("DefaultSerialEntity ์— phoneNumber ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ๊ฒฝ์šฐ ๋‹ค๋ฅธ ์—ญ์ง๋ ฌํ™” ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜์—ฌ ์˜ˆ์™ธ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค")
    void defaultSerializeWhenAddField() throws IOException, ClassNotFoundException {
        //given, when
        // phoneNumber ํ•„๋“œ ์ถ”๊ฐ€ ์ด์ „ ์ง๋ ฌํ™” ๊ฐ’
        String serializedByteStrBeforeFieldAdd = "rO0ABXNyACtjb20uY29vcGVyLnNlcmlhbGl6YWJsZS5EZWZhdWx0U2VyaWFsRW50aX" +
                "R54Lm3/1et2ggCAANMAAlwcmVzc05hbWV0ABJMamF2YS9sYW5nL1N0cmluZztMAAxyZXBvcnRlck5hbWVxAH4AAUwABXRpdGxlc" +
                "QB+AAF4cHQAC3ByZXNzTmFtZTExdAAOcmVwb3J0ZXJOYW1lMTF0AAbsnbTrpoQ=";

        //then
        assertThatThrownBy(() -> SerializableUtil.<DefaultSerialEntity>deSerializeMethod(serializedByteStrBeforeFieldAdd))
                .isInstanceOf(InvalidClassException.class);
    }

}

 

 

ํ•„๋“œ ์ถ”๊ฐ€ ํ›„ ์ •์ƒ์ ์œผ๋กœ ์—ญ์ง๋ ฌํ™”๊ฐ€ ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•˜๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ

public class SerialUIDEntity implements Serializable {

    @Serial
    private static final long serialVersionUID = -7116771609929351855L;

    private String title;
    private String pressName;
    private String reporterName;

    // ์ƒˆ๋กœ์šด ํ•„๋“œ ์ถ”๊ฐ€
    private String phoneNumber;

    public SerialUIDEntity(String title, String pressName, String reporterName) {
        this.title = title;
        this.pressName = pressName;
        this.reporterName = reporterName;
    }

    @Override
    public String toString() {
        return "SerialUIDEntity{" +
                "title='" + title + '\'' +
                ", pressName='" + pressName + '\'' +
                ", reporterName='" + reporterName + '\'' +
                ", phoneNumber='" + phoneNumber + '\'' +
                '}';
    }

}

// test code
class SerialUIDEntityTest {

    @Test
    @DisplayName("serialVersionUID ์„ ์„ ์–ธํ•˜๋ฉด ํด๋ž˜์Šค ์ •๋ณด ๊ด€๊ณ„์—†์ด serialVersionUID ๊ธฐ์ค€์œผ๋กœ ์ง๋ ฌํ™”๋œ๋‹ค.")
    void SerialVersionUID() throws IOException, ClassNotFoundException {
        //given, when
        // phoneNumber ํ•„๋“œ ์ถ”๊ฐ€ ์ด์ „ ์ง๋ ฌํ™” ๊ฐ’ : new SerialUIDEntity("title222", "pressName222", "reporter222");
        String serializedByteStrBeforeFieldAdd = "rO0ABXNyACdjb20uY29vcGVyLnNlcmlhbGl6YWJsZS5TZXJpYWxVSURFbnRpdHmdPCX" +
                "tUpN9UQIAA0wACXByZXNzTmFtZXQAEkxqYXZhL2xhbmcvU3RyaW5nO0wADHJlcG9ydGVyTmFtZXEAfgABTAAFdGl0bGVxAH4AAXh" +
                "wdAAMcHJlc3NOYW1lMjIydAALcmVwb3J0ZXIyMjJ0AAh0aXRsZTIyMg==";

        //then
        Assertions.assertThat(SerializableUtil.<SerialUIDEntity>deSerializeMethod(serializedByteStrBeforeFieldAdd))
                .isInstanceOf(SerialUIDEntity.class);
    }

}

 

3. ํด๋ž˜์Šค์˜ ๊ธฐ๋ณธ ํ•ด์‹œ๊ฐ’์„ ํ†ตํ•œ SerialVersionUID ์˜ ๋ฌธ์ œ

  1. ํด๋ž˜์Šค์˜ ๊ตฌ์กฐ๊ฐ€ ๋ณ€๊ฒฝ ๋˜์—ˆ์„ ๋•Œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
    • ์˜ˆ์‹œ: ๋ฉค๋ฒ„ ๋ณ€์ˆ˜ ํƒ€์ž… ๋ณ€๊ฒฝ, ๋ฉค๋ฒ„ ๋ณ€์ˆ˜ ์‚ญ์ œ
  2. ํด๋ž˜์Šค์˜ ๊ธฐ๋ณธ ํ•ด์‹œ๊ฐ’์„ ํ†ตํ•œ SerialVersionUID ์˜ ๋ฌธ์ œ
    • ํ”„๋ ˆ์ž„์›Œํฌ ๋˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์ œ๊ณตํ•˜๋Š” ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋„ ๋ฒ„์ „์—…์„ ํ†ตํ•ด SerialVersionUID ๊ฐ€ ๋ณ€๊ฒฝ๋  ๊ฒฝ์šฐ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ์˜ˆ์ƒํ•˜์ง€ ๋ชปํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

 

4. ๐Ÿšจ SerialVersionUID ๋Š” ๋˜๋„๋ก์ด๋ฉด ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๊ด€๋ฆฌํ•˜์ž!!

  • intellij ์—์„œ๋Š” serialVersionUID ์ž๋™ ์ƒ์„ฑ์„ ์ œ๊ณตํ•˜๋Š” ์˜ต์…˜์„ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ผญ ์˜ต์…˜์„ ์ถ”๊ฐ€ํ•˜๋„๋ก ํ•˜์ž!! (์ด์™•์ด๋ฉด ๊ฒฝ๊ณ ๊นŒ์ง€ ๋„์šฐ๋„๋ก ํ•˜์ž!)
  • (File > Settings > Serializable class without ‘serialVersionUID’)

 

 

 

5. Serialazable ์˜ ๊ถŒ์žฅํ•˜์ง€ ์•Š์ง€๋งŒ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์ฃผ์˜ํ•ด์„œ ์‚ฌ์šฉํ•˜์ž.

  1. ์•…์˜์ ์ธ ๊ณต๊ฒฉ ์š”์†Œ๊ฐ€ ๋งŽ๋‹ค.
    • readObject : ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋Š” ํด๋ž˜์Šค ํŒจ์Šค์— ์žˆ๊ณ  Serializable interface ๋ฅผ ๊ตฌํ˜„ํ•œ ๋ชจ๋“  ํƒ€์ž…์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
    • ์—ญ์ง๋ ฌํ™” ํ•„ํ„ฐ๋ง ์„ ์‚ฌ์šฉํ•ด ์•ˆ์ „ํ•˜๋‹ค๊ณ  ํŒ๋‹จ๋˜๋Š” ํด๋ž˜์Šค ํ™”์ดํŠธ ๋ฆฌ์ŠคํŠธ ์™€ ๊ฐ™์€ ๋ชฉ๋ก์„ ์—ญ์ง๋ ฌํ™”๋ฅผ ํ•˜๋Š”๋ฐ ์ œ๊ณตํ•ด์•ผ ํ•œ๋‹ค.

 

6. References

  • https://madplay.github.io/post/java-serialization-advanced
  • https://madplay.github.io/post/why-java-serialization-is-bad
  • https://androowl.tistory.com/50

'๐Ÿ“‚ programming-language > java' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

์ž๋ฐ”์—์„œ ๋™์‹œ์„ฑ์€ ์™œ ๋ฐœ์ƒํ• ๊นŒ?  (4) 2025.03.23
Java Local Cache ๋น„๊ตํ•˜๊ธฐ  (0) 2025.03.09
์ž๋ฐ” ๋น„๋™๊ธฐ๋กœ ์นดํŽ˜ ์ฝ˜์†” ์˜ˆ์ œ ๋งŒ๋“ค๊ธฐ  (0) 2024.11.26
์–ด๋Œ‘ํ„ฐ ํŒจํ„ด(adapter pattern)  (1) 2024.07.09
ํผ์‚ฌ๋“œ ํŒจํ„ด(Facade Pattern)  (0) 2024.07.08
'๐Ÿ“‚ programming-language/java' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
  • ์ž๋ฐ”์—์„œ ๋™์‹œ์„ฑ์€ ์™œ ๋ฐœ์ƒํ• ๊นŒ?
  • Java Local Cache ๋น„๊ตํ•˜๊ธฐ
  • ์ž๋ฐ” ๋น„๋™๊ธฐ๋กœ ์นดํŽ˜ ์ฝ˜์†” ์˜ˆ์ œ ๋งŒ๋“ค๊ธฐ
  • ์–ด๋Œ‘ํ„ฐ ํŒจํ„ด(adapter pattern)
cooper25
cooper25
  • cooper25
    dev cooper
    cooper25
  • ์ „์ฒด
    ์˜ค๋Š˜
    ์–ด์ œ
    • ๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ (84)
      • ๐Ÿ“‚ backend (34)
        • spring (19)
        • architecture (10)
        • test (5)
      • ๐Ÿ“‚ computer-science (5)
      • ๐Ÿ“‚ programming-language (12)
        • java (12)
      • ๐Ÿ“‚ infra (9)
        • mysql (4)
        • redis (2)
        • message-queue (3)
      • ๐Ÿ“‚ cloud (2)
        • aws (2)
      • ๐Ÿ“‚ frontend (1)
        • react (0)
      • ๐Ÿ“‚ education & lecture (16)
        • ์ธํ”„๋ผ ๊ณต๋ฐฉ (11)
        • ํ•ญํ”Œ ๋ฐฑ์—”๋“œ 7๊ธฐ (5)
      • ๐Ÿ“‚ ai (1)
        • claude (1)
      • ๐Ÿ“‚ etc (2)
        • ํšŒ๊ณ  (1)
        • ์ปจํผ๋Ÿฐ์Šค (1)
  • ๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

    • ํ™ˆ
    • ํƒœ๊ทธ
    • ๋ฐฉ๋ช…๋ก
  • ๋งํฌ

  • ๊ณต์ง€์‚ฌํ•ญ

  • ์ธ๊ธฐ ๊ธ€

  • ํƒœ๊ทธ

    JPA
    gof
    kafka
    spring-batch
    ๋ฐ์ดํ„ฐ ์ค‘์‹ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„ค๊ณ„
    ํ•ญํ•ดํ”Œ๋Ÿฌ์Šค
    ์Šคํ”„๋ง์บ ํ”„ ํ›„๊ธฐ
    ์ธํ”„๋ผ๊ณต๋ฐฉ
    nGrinder
    ํšŒ๊ณ 
    spring camp 2025
    mysql
    AWS
    react
    Redisson
    UUID
    ๊ฐ€์ƒ ๋ฉด์ ‘ ์‚ฌ๋ก€๋กœ ๋ฐฐ์šฐ๋Š” ๋Œ€๊ทœ๋ชจ ์„ค๊ณ„
    ๋™์‹œ์„ฑ
    spring AOP
    spring
  • ์ตœ๊ทผ ๋Œ“๊ธ€

  • ์ตœ๊ทผ ๊ธ€

  • hELLOยท Designed By์ •์ƒ์šฐ.v4.10.6
cooper25
SerialVersionUID๋ฅผ ์„ ์–ธํ•ด์•ผ ํ•˜๋Š” ์ด์œ 
์ƒ๋‹จ์œผ๋กœ

ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”