자바의 Jackson에 대해 설명하는 글을 작성하겠습니다. Jackson은 자바에서 JSON 데이터를 처리하기 위해 널리 사용되는 라이브러리로, 객체와 JSON 간의 직렬화(Serialization) 및 역직렬화(Deserialization)를 쉽게 수행할 수 있게 해줍니다. 특히, Jackson의 어노테이션은 이러한 변환 과정을 세밀하게 제어할 수 있도록 도와줍니다. 아래에서는 Jackson의 주요 어노테이션을 표로 정리한 뒤, 각 어노테이션에 대한 상세 설명과 예시를 제공하겠습니다.

---

### Jackson 주요 어노테이션 표

| 어노테이션                  | 설명                                                                                     |
|----------------------------|------------------------------------------------------------------------------------------|
| `@JsonProperty`           | JSON 키와 자바 필드/메서드 이름을 매핑하거나, 직렬화/역직렬화 시 속성 이름을 지정          |
| `@JsonIgnore`             | 직렬화 및 역직렬화 시 특정 필드를 무시                                                     |
| `@JsonIgnoreProperties`   | 클래스 레벨에서 직렬화/역직렬화 시 무시할 속성(들)을 지정                                  |
| `@JsonInclude`            | 직렬화 시 특정 조건(예: null 값 제외)에 따라 필드를 포함하거나 제외                       |
| `@JsonCreator`            | 역직렬화 시 사용할 생성자나 팩토리 메서드를 지정                                          |
| `@JsonSetter`             | 역직렬화 시 특정 Setter 메서드를 JSON 속성과 매핑                                         |
| `@JsonGetter`             | 직렬화 시 특정 Getter 메서드를 JSON 속성으로 사용                                         |
| `@JsonAnySetter`          | 정의되지 않은 JSON 속성을 Map 형태로 처리                                                |
| `@JsonAnyGetter`          | Map의 내용을 추가적인 JSON 속성으로 직렬화                                               |
| `@JsonManagedReference`   | 객체 간 순환 참조에서 부모 객체를 직렬화                                                  |
| `@JsonBackReference`      | 객체 간 순환 참조에서 자식 객체를 직렬화에서 제외                                        |
| `@JsonIdentityInfo`       | 순환 참조 문제를 해결하기 위해 객체의 고유 식별자를 사용                                   |
| `@JsonTypeInfo`           | 다형성 타입 정보를 JSON에 포함시켜 직렬화/역직렬화 시 올바른 타입으로 처리                |
| `@JsonSubTypes`           | `@JsonTypeInfo`와 함께 사용되며, 하위 타입을 명시                                        |
| `@JsonView`               | 특정 뷰(View)에 따라 직렬화/역직렬화 대상을 제한                                          |
| `@JacksonInject`          | JSON 데이터 대신 외부에서 주입된 값을 필드에 설정                                         |

---

### 각 어노테이션 상세 설명 및 예시

#### 1. `@JsonProperty`
- **설명**: JSON 속성 이름과 자바 필드/메서드 이름을 매핑하거나, 이름을 강제로 지정합니다.
- **예시**:
```java
import com.fasterxml.jackson.annotation.JsonProperty;

public class Person {
    @JsonProperty("fullName")
    private String name;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        Person person = new Person();
        person.setName("홍길동");
        String json = mapper.writeValueAsString(person);
        System.out.println(json); // {"fullName":"홍길동"}
    }
}
```

#### 2. `@JsonIgnore`
- **설명**: 직렬화 및 역직렬화 시 특정 필드를 제외합니다.
- **예시**:
```java
import com.fasterxml.jackson.annotation.JsonIgnore;

public class Person {
    private String name;
    @JsonIgnore
    private int age;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
}

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        Person person = new Person();
        person.setName("김영희"); person.setAge(25);
        String json = mapper.writeValueAsString(person);
        System.out.println(json); // {"name":"김영희"}
    }
}
```

#### 3. `@JsonIgnoreProperties`
- **설명**: 클래스 레벨에서 무시할 속성을 지정하거나, 알 수 없는 속성을 무시하도록 설정합니다.
- **예시**:
```java
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties({"age", "ignoreUnknown = true"})
public class Person {
    private String name;
    private int age;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
}

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        String json = "{\"name\":\"이철수\",\"age\":30,\"extra\":\"data\"}";
        Person person = mapper.readValue(json, Person.class);
        System.out.println(person.getName()); // "이철수"
    }
}
```

#### 4. `@JsonInclude`
- **설명**: 직렬화 시 null 값이나 빈 값 등을 제외하는 조건을 설정합니다.
- **예시**:
```java
import com.fasterxml.jackson.annotation.JsonInclude;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Person {
    private String name;
    private String address;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getAddress() { return address; }
    public void setAddress(String address) { this.address = address; }
}

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        Person person = new Person();
        person.setName("박민수");
        String json = mapper.writeValueAsString(person);
        System.out.println(json); // {"name":"박민수"}
    }
}
```

#### 5. `@JsonCreator`
- **설명**: 역직렬화 시 사용할 생성자나 팩토리 메서드를 지정합니다.
- **예시**:
```java
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class Person {
    private final String name;

    @JsonCreator
    public Person(@JsonProperty("name") String name) {
        this.name = name;
    }

    public String getName() { return name; }
}

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        String json = "{\"name\":\"최수진\"}";
        Person person = mapper.readValue(json, Person.class);
        System.out.println(person.getName()); // "최수진"
    }
}
```

#### 6. `@JsonSetter`
- **설명**: 역직렬화 시 Setter 메서드를 특정 JSON 속성과 매핑합니다.
- **예시**:
```java
import com.fasterxml.jackson.annotation.JsonSetter;

public class Person {
    private String name;

    @JsonSetter("fullName")
    public void setName(String name) { this.name = name; }

    public String getName() { return name; }
}

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        String json = "{\"fullName\":\"김지영\"}";
        Person person = mapper.readValue(json, Person.class);
        System.out.println(person.getName()); // "김지영"
    }
}
```

#### 7. `@JsonGetter`
- **설명**: 직렬화 시 Getter 메서드를 JSON 속성으로 사용합니다.
- **예시**:
```java
import com.fasterxml.jackson.annotation.JsonGetter;

public class Person {
    private String name;

    @JsonGetter("fullName")
    public String getName() { return name; }

    public void setName(String name) { this.name = name; }
}

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        Person person = new Person();
        person.setName("윤서진");
        String json = mapper.writeValueAsString(person);
        System.out.println(json); // {"fullName":"윤서진"}
    }
}
```

#### 8. `@JsonAnySetter`
- **설명**: 정의되지 않은 JSON 속성을 Map으로 처리합니다.
- **예시**:
```java
import com.fasterxml.jackson.annotation.JsonAnySetter;
import java.util.HashMap;
import java.util.Map;

public class Person {
    private Map<String, Object> properties = new HashMap<>();

    @JsonAnySetter
    public void setProperty(String key, Object value) {
        properties.put(key, value);
    }

    public Map<String, Object> getProperties() { return properties; }
}

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        String json = "{\"name\":\"이정훈\",\"age\":29}";
        Person person = mapper.readValue(json, Person.class);
        System.out.println(person.getProperties()); // {name=이정훈, age=29}
    }
}
```

#### 9. `@JsonAnyGetter`
- **설명**: Map의 내용을 추가적인 JSON 속성으로 직렬화합니다.
- **예시**:
```java
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import java.util.HashMap;
import java.util.Map;

public class Person {
    private Map<String, Object> properties = new HashMap<>();

    @JsonAnyGetter
    public Map<String, Object> getProperties() { return properties; }

    public void setProperty(String key, Object value) { properties.put(key, value); }
}

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        Person person = new Person();
        person.setProperty("name", "최영미");
        person.setProperty("age", 35);
        String json = mapper.writeValueAsString(person);
        System.out.println(json); // {"name":"최영미","age":35}
    }
}
```

#### 10. `@JsonManagedReference`와 `@JsonBackReference`
- **설명**: 순환 참조 문제를 해결하기 위해 부모-자식 관계를 정의합니다.
- **예시**:
```java
import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.fasterxml.jackson.annotation.JsonBackReference;

public class Parent {
    @JsonManagedReference
    public Child child;

    public void setChild(Child child) { this.child = child; }
}

public class Child {
    @JsonBackReference
    public Parent parent;

    public void setParent(Parent parent) { this.parent = parent; }
}

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        Parent parent = new Parent();
        Child child = new Child();
        parent.setChild(child);
        child.setParent(parent);
        String json = mapper.writeValueAsString(parent);
        System.out.println(json); // {"child":{}}
    }
}
```

#### 11. `@JsonIdentityInfo`
- **설명**: 순환 참조를 객체 ID로 해결합니다.
- **예시**:
```java
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class Person {
    private int id;
    private String name;
    private Person friend;

    public Person(int id, String name) { this.id = id; this.name = name; }
    public void setFriend(Person friend) { this.friend = friend; }
    public String getName() { return name; }
}

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        Person p1 = new Person(1, "김태양");
        Person p2 = new Person(2, "이수진");
        p1.setFriend(p2);
        p2.setFriend(p1);
        String json = mapper.writeValueAsString(p1);
        System.out.println(json); // {"id":1,"name":"김태양","friend":{"id":2,"name":"이수진","friend":1}}
    }
}
```

#### 12. `@JsonTypeInfo`와 `@JsonSubTypes`
- **설명**: 다형성을 처리하기 위해 타입 정보를 JSON에 포함합니다.
- **예시**:
```java
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
    @Type(value = Dog.class, name = "dog"),
    @Type(value = Cat.class, name = "cat")
})
public abstract class Animal {
    public String name;
}

public class Dog extends Animal {}
public class Cat extends Animal {}

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        Dog dog = new Dog(); dog.name = "멍멍이";
        String json = mapper.writeValueAsString(dog);
        System.out.println(json); // {"type":"dog","name":"멍멍이"}
    }
}
```

#### 13. `@JsonView`
- **설명**: 특정 뷰에 따라 직렬화 대상을 제한합니다.
- **예시**:
```java
import com.fasterxml.jackson.annotation.JsonView;

public class Person {
    public interface PublicView {}
    public interface PrivateView extends PublicView {}

    @JsonView(PublicView.class)
    private String name;

    @JsonView(PrivateView.class)
    private int age;

    public Person(String name, int age) { this.name = name; this.age = age; }
    public String getName() { return name; }
    public int getAge() { return age; }
}

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        Person person = new Person("박준영", 27);
        String json = mapper.writerWithView(Person.PublicView.class).writeValueAsString(person);
        System.out.println(json); // {"name":"박준영"}
    }
}
```

#### 14. `@JacksonInject`
- **설명**: JSON 데이터가 아닌 외부에서 주입된 값을 사용합니다.
- **예시**:
```java
import com.fasterxml.jackson.annotation.JacksonInject;

public class Person {
    @JacksonInject
    private String source;
    private String name;

    public Person(String name) { this.name = name; }
    public String getSource() { return source; }
    public String getName() { return name; }
}

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        InjectableValues inject = new InjectableValues.Std().addValue(String.class, "외부 소스");
        Person person = mapper.reader(inject).forType(Person.class)
                .readValue("{\"name\":\"최민수\"}");
        System.out.println(person.getSource()); // "외부 소스"
    }
}
```

---

### 결론
Jackson은 강력한 JSON 처리 기능을 제공하며, 위의 어노테이션들은 이를 세밀하게 제어할 수 있게 해줍니다. 다형성 처리, 순환 참조 해결, 속성 이름 매핑 등 다양한 기능을 통해 개발자는 유연하고 효율적인 JSON 처리를 구현할 수 있습니다. 프로젝트에서 Jackson을 사용할 때는 팀원 모두가 관련 어노테이션을 이해하고, 적절한 설정(예: 의존성 추가, IDE 플러그인 설치)을 통해 효율적으로 활용하는 것이 중요합니다.

궁금한 점이 있다면 언제든 물어보세요!