HTTP GET 메소드를 이용하여 지도 좌표값을 주소 정보(지번, 도로명, 법정동, 행정동)으로 반환 받는 API입니다.
좌표String Type 위도, 경도 -> 주소문자열
서비스 환경 등록
필요하다면 작성
API 요청을 허용할 host를 지정
4. 인증 키 발급
App 이름의 '인증 정보' 클릭
추후 네이버 지도 API로 요청시 Request Header에 담아야 함
Header 필드
x-ncp-apigw-api-key-id : 클라이언트 ID
x-ncp-apigw-api-key : Secret Key
이후 예제는 Geocoding, Directions 5 API에 대해 작성되었습니다. Geocoding과 Reverse Geocoding은 좌표<->주소간 변환하며 비슷한 면이 있습니다. Directions 5와 Directions 15는 최대 경유지 갯수의 차이와 API 요청방법에 대한 차이가 있습니다.
public class User {
private String name;
private int age;
// Getter for name
public String getName() {
return name;
}
// Setter for name
public void setName(String name) {
this.name = name;
}
// Getter for age
public int getAge() {
return age;
}
// Setter for age
public void setAge(int age) {
this.age = age;
}
}
클래스의 필드에 대해 getter / setter 메서드를 자동으로 생성
어노테이션 : @Getter, @Setter
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class User {
private String name;
private int age;
}
2. 생성자 자동 생성
@NoArgsConstructor, @AllArgsContructor, @RequiredArgsConstructor을 사용하지 않는다면,
public class User {
// 필드 정의
private String name;
private int age;
// 기본 생성자 (No-Args Constructor)
public User() {
}
// 모든 필드를 초기화하는 생성자 (All-Args Constructor)
public User(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Service {
private final String serviceName;
private final int serviceId;
private String description; // final이 아님
// RequiredArgsConstructor에 해당하는 생성자
public Service(String serviceName, int serviceId) {
this.serviceName = serviceName;
this.serviceId = serviceId;
}
}
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String name;
private int age;
}
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class Service {
private final String serviceName;
private final int serviceId;
private String description; // final이 아님, 생성자에 포함되지 않음
}
public class User {
private String name;
private int age;
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
객체의 문자열 표현을 자동 생성
어노테이션 : @ToString
import lombok.ToString;
@ToString
public class User {
private String name;
private int age;
}
public class User {
private String name;
private int age;
private User(Builder builder) {
this.name = builder.name;
this.age = builder.age;
}
public static class Builder {
private String name;
private int age;
public Builder name(String name) {
this.name = name;
return this;
}
public Builder age(int age) {
this.age = age;
return this;
}
public User build() {
return new User(this);
}
}
public static Builder builder() {
return new Builder();
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
// 빌더 패턴 사용 예제
User user = User.builder()
.name("John")
.age(30)
.build();
어노테이션 : @Builder
import lombok.Builder;
@Builder
public class User {
private String name;
private int age;
}
User user = User.builder()
.name("John")
.age(30)
.build();
6. 로그 로깅 지원
다양한 로깅 라이브러리에 대해 자동으로 로그 객체를 생성
@Slf4j, @Log, @Log4j2
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class User {
public void logExample() {
log.info("Logging with Lombok");
}
}
JPA(Java Persistence API)와 MyBatis는 둘 다 데이터베이스와 애플리케이션 간의 데이터 접근을 쉽게 하기 위한 프레임워크입니다. 하지만 그 작동 방식과 특징이 매우 다릅니다. 아래에서 JPA와 MyBatis의 주요 차이점, 장단점, 그리고 어떤 상황에서 사용하면 좋은지 정리하겠습니다.
1. JPA (Java Persistence API)
특징
ORM (Object-Relational Mapping) 기반
객체와 테이블을 매핑하여 SQL을 작성하지 않고도 데이터베이스와 상호작용 가능.
Hibernate, EclipseLink 등이 JPA 구현체로 사용됨.
JPQL (Java Persistence Query Language)
SQL과 유사한 언어로 엔티티 객체를 대상으로 쿼리 작성.
데이터베이스 독립성을 유지하면서 동작.
자동화된 데이터 관리
데이터 저장, 갱신, 삭제, 조회를 엔티티 객체로 처리.
변경 감지(Dirty Checking), 1차 캐시, 연관관계 매핑, 지연 로딩(Lazy Loading) 같은 기능 지원.
추상화
비즈니스 로직에서 SQL을 숨기고 객체 지향적 프로그래밍 가능.
장점
생산성: SQL을 작성하지 않아도 기본적인 CRUD 작업 가능.
추상화: 데이터베이스 독립성을 유지하며 객체 중심의 프로그래밍 가능.
자동화: 엔티티 상태 관리, 변경 감지, Lazy/Eager Loading 등 자동화된 기능 제공.
캐싱: 1차 캐시와 2차 캐시를 통해 성능 최적화.
단점
학습 곡선: 개념(엔티티 매핑, 연관 관계, 영속성 컨텍스트 등)을 이해하는 데 시간이 필요.
복잡한 쿼리 작성 어려움: JPQL과 Criteria API는 직관적이지 않을 수 있음.
자동화 오버헤드: 자동화된 기능이 성능 이슈를 야기할 가능성 있음(예: N+1 문제).
2. MyBatis
특징
SQL Mapper 기반
SQL을 직접 작성하고 XML 또는 어노테이션으로 매핑.
SQL의 자유도가 높아 복잡한 쿼리 처리에 유리.
설정 기반 매핑
XML 또는 어노테이션을 통해 Java 객체와 SQL 결과를 매핑.
직접적인 데이터베이스 제어
개발자가 SQL 작성에 완전한 제어권을 가짐.
복잡한 조인이나 고성능 쿼리를 직접 작성 가능.
결과 매핑:
쿼리 결과를 POJO(Plain Old Java Object)에 매핑하여 처리.
장점
SQL 제어: 복잡한 SQL 작성과 튜닝이 가능.
동적 SQL: 동적 쿼리 작성이 편리.
단순성: SQL Mapper로 구성되어 간단하고 직관적.
효율성: 개발자가 SQL 최적화와 성능 튜닝을 쉽게 제어.
단점
생산성 저하: 모든 SQL을 직접 작성해야 하므로 초기 개발 시간이 오래 걸릴 수 있음.
유지보수 어려움: SQL과 비즈니스 로직이 얽힐 가능성이 높음.
재사용성 제한: SQL 중심으로 설계되어 객체 지향적 설계와는 거리가 멀 수 있음.
3. JPA와 MyBatis 비교
특징
ORM(Object-Relational Mapping) 중심
SQL Mapper 중심
SQL 작성
JPQL 사용 (SQL 추상화)
SQL을 직접 작성
개발 속도
자동화된 데이터 관리로 빠른 개발 가능
직접 SQL 작성으로 초기 개발 속도 느림
복잡한 쿼리
복잡한 쿼리는 JPQL로 작성하거나 Native Query 사용
복잡한 쿼리 작성에 적합
데이터베이스 종속성
낮음 (JPQL 및 엔티티 중심)
높음 (SQL에 의존)
성능 최적화
자동화된 매핑과 캐시로 적절한 성능 제공
개발자가 SQL 튜닝으로 성능 최적화 가능
학습 곡선
높음 (ORM과 JPA의 동작 원리 이해 필요)
낮음 (SQL과 매핑 규칙만 알면 됨)
동적 쿼리 처리
어렵거나 불편할 수 있음 (Criteria API 사용)
동적 SQL 작성이 쉬움 (XML <if>, <choose> 지원)
유지 보수
코드에서 비즈니스 로직과 SQL 분리 가능
SQL과 비즈니스 로직이 얽힐 수 있음
캐시 지원
1차 캐시(엔티티 매니저) 및 2차 캐시(Hibernate 등 지원 가능)
직접 구현해야 함 (예: Redis와 연동)
플랫폼 의존성
낮음 (다양한 DB와 쉽게 호환)
DB 벤더에 종속될 가능성 있음
4. 어떤 상황에서 선택해야 하나?
JPA가 적합한 경우
객체 지향 설계를 선호하고 데이터베이스의 데이터와 객체 간 매핑이 중요한 경우.
데이터 중심보다 도메인 중심의 설계를 원할 때.
표준화된 방식(JPA/ORM)을 통해 프로젝트 확장성과 유지보수성을 고려할 때.
DB 독립성을 중시하며 다양한 DB를 지원할 가능성이 있을 때.
MyBatis가 적합한 경우
SQL 성능 최적화가 중요한 경우(복잡한 쿼리, 대용량 데이터 처리).
동적 쿼리와 복잡한 JOIN 쿼리를 자주 사용해야 할 때.
데이터베이스 설계가 복잡하고 JPA 매핑이 어렵거나 비효율적인 경우.
레거시 시스템과 통합이 필요한 경우.
5. 결론
JPA는 생산성을 높이고 유지보수를 쉽게 하기 위한 ORM 기반 도구로 적합하며 비즈니스 로직이 복잡하거나 객체 지향 설계가 중요한 프로젝트에서 강점.
MyBatis는 SQL 작성의 자유도와 데이터베이스 성능 최적화가 중요한 프로젝트에서 강점.
두 프레임워크는 상황에 따라 병행해서 사용하는 것도 가능합니다. 예를 들어, JPA를 기본으로 사용하되 복잡한 쿼리가 필요한 부분은 MyBatis로 처리하는 식으로 하이브리드 접근을 고려할 수도 있습니다.