이 글은 Java의 접근 제어자(public, private), static, 그리고 Annotation에 대해서 정리한 글입니다.
알고리즘을 풀 때에는 잘 몰랐는데, 막상 백엔드를 공부해보려고 Spring Boot를 시작하니 Java 문법에 대해서 제대로 모르고 있다는 생각이 들었다
알고리즘을 풀 때는 무지성으로 public static을 붙이거나, main 함수 안에서만 구현해도 됐었는데, 실제 객체지향 프로그래밍과 프레임워크 환경 안에서는 이러한 키워드 하나하나가 시스템의 보안과 메모리 효율을 결정하는 중요한 요소였다.
이번 기회에 Spring Boot를 공부하면서 알게 된 개념들을 다시 한 번 정리해보고자 한다.
접근 제어자 (Access Modifier)
알고리즘 문제를 풀 때에는 보통 하나의 클래스(Main) 안에서 모든 로직을 처리하기 때문에 접근 제어자를 크게 신경 쓸 필요가 없었고, 귀찮으면 그냥 public으로 열어버려도 상관없었다.
하지만 실제 애플리케이션은 수많은 클래스가 서로 상호작용하는 거대한 시스템이기 때문에 캡슐화(Encapsulation)가 중요하다.
Public vs Private
가장 많이 사용하는 접근 제어자는 public과 private이 있다.
public- 외부(다른 클래스, 패키지)에서 누구나 접근하고 호출할 수 있다.
- 주로 Controller의 메서드나 DTO의 Getter / Setter처럼 외부와 소통해야 하는 창구에 사용한다.
private- 외부에서는 절대로 접근할 수 없고, 자기 자신(클래스 내부)에서만 접근이 가능하다.
- 객체의 중요한 데이터(필드)는 무조건
private으로 숨기는 것이 원칙이다.
왜 변수는 private이어야 하는가?
// [Bad Case] 변수를 public으로 열어둔 경우
public class User {
public int age;
}
// 외부에서 이상한 짓이 가능함
User user = new User();
user.age = -500; // 나이가 -500살? 막을 방법이 없음.
위 코드에서 만약 변수 age가 public이라면 외부에서 누구나 이 값을 바꿔버릴 수 있다. 이를 방지하기 위해서 변수는 private으로 잠그고, 데이터를 변경하는 메서드(Setter)를 public으로 열어두어 통제해야 한다.
// [Good Case] 변수는 숨기고, 메서드로 통제한다
public class User {
private int age; // 외부 접근 불가 🚫
// 데이터를 넣을 때는 이 문(Method)을 통해서만 가능
public void setAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("나이는 0보다 작을 수 없습니다.");
}
this.age = age;
}
}
Spring Boot에서 Entity나 DTO를 만들 때 습관적으로 필드를 private으로 선언하는 이유가 바로 이 데이터 무결성을 지키기 위함이다.
데이터 무결성?
데이터 부결성은 데이터베이스(DB)에 엉뚱한 데이터가 들어가지 못하도록 막는 규칙을 의미한다. 즉, 데이터의 정확성, 일관성, 그리고 유효성을 유지하는 것을 의미하며, 데이터가 삭제될 때까지 변경되거나 훼손되지 않고 원래 의도된 상태 그대로 정확하게 남아있도록 보장하는 것이다. 크게 객체 무결성, 참조 무결성, 도메인 무결성이 있다.
Static
static의 핵심은 "공유"와 "객체 생성 없이 사용 가능"이다.
Non-static vs Static
- 인스턴스 변수 (Non-static)
- 객체를 생성(
new)해야만 존재한다. - A라는 객체와 B라는 객체는 서로 다르며, A 객체를 수정해도 B 객체는 변하지 않는다. (개별성)
- 객체를 생성(
- 클래스 변수 (
static)- 객체가 몇개든 단 하나만 존재한다.
- 누군가 객체를 변경하면, 모든 객체가 수정된다. (공유성)
메모리 구조에서의 차이
- 일반 객체:
new를 할 때마다 Heap Area에 계속 생성된다. static객체: 프로그램이 시작될 때 Method Area(Static Area)에 딱 한 번 올라가고, 프로그램이 종료될 때까지 살아있다.
실제 코드에서의 차이
class Counter {
int count = 0; // 인스턴스 변수 (손목시계)
static int total = 0; // 클래스 변수 (벽시계)
public Counter() {
count++;
total++;
}
}
public class Main {
public static void main(String[] args) {
Counter c1 = new Counter();
Counter c2 = new Counter();
// c1의 count는? 1 (자기 자신만 셈)
// total은? 2 (c1이 생성될 때 +1, c2가 생성될 때 +1 되어서 누적됨)
}
}
Spring Boot 개발 시에는 대부분 Spring Bean(싱글톤)이 관리해주기 때문에 개발자가 직접 static을 남발할 일은 많지 않다. 오히려 static을 잘못 쓰면 멀티스레드 환경인 웹 서버에서 모든 사용자가 데이터를 공유해버리는 심각한 버그가 터질 수 있어서 주의가 필요하다.
어노테이션(Annotation)
Spring Boot 코드를 보면 @ 기호를 쉽게 찾아볼 수 있다. 골뱅이의 정식 명칭은 어노테이션(Annotation)으로, 알고리즘 문제를 풀 때에는 전혀 볼 일이 없는 문법이다.
주석(Comment)와의 차이
주석( //, /* */ )은 사람을 위한 메모라면, 어노테이션(@)은 컴파일러나 프레임워크를 위한 메모이다.
즉, Sping Boot는 클래스의 내용을 모르더라도 어노테이션만 보고 특정 메모리 영역에 넣어야겠다고 판단하고 처리한다.
대표적인 어노테이션
@RestController- 의미: 이 클래스는 뷰(HTML)를 그리는 게 아니라, 데이터(JSON)를 반환하는 역할을 한다.
- Spring의 행동: 이 어노테이션이 붙은 클래스의 메서드가 무언가를 리턴하면, 자동으로 JSON 형식으로 바꿔서 응답을 보낸다.
@GetMapping("/hello")- 의미: HTTP 메서드가
GET이고, 주소가/hello인 요청이 오면 이 함수를 실행하세요. - Spring의 행동: 해당 주소로 요청이 들어왔을 때, 어노테이션을 보고 정확히 이 메서드로 안내한다.
- 의미: HTTP 메서드가
Lombok과 JSON (Getter / Setter)
API를 만들 때 핵심은 Getter와 Setter 메서드이다.
JSON 변환의 핵심인 Getter
Spring Boot가 자바 객체를 JSON으로 바꿀 때 사용하는 라이브러리는 Jackson이다. 이 라이브러리는 private으로 잠긴 변수를 함부로 훔쳐보지 않는다. 대신 공개된 접근 메서드(Getter)를 찾아서 데이터를 가져온다.
만약, Getter 메서드가 없다면, Jackson이 데이터를 가져오지 못해서 빈 객체( { } )만 리턴한다. 따라서 값을 가져오기 위해서는 반드시 변수마다 해당하는 Getter 메서드가 필요하다.
Lombok
변수가 20개, 30개씩 늘어난다면, Getter와 Setter 메서드 역시 각각 20개, 30개씩 늘어나야 한다. 이러한 귀찮음을 없애주는 구세주가 바로 Lombok이다.
// [Before] Lombok 없이 짠 코드 (매우 김)
public class UserInfo {
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
// ... 변수마다 반복 ...
}
// [After] Lombok 사용 (@Data 또는 @Getter)
@Getter
@Setter
public class UserInfo {
private String name;
// 끝! 컴파일 할 때 Lombok이 알아서 메서드를 생성해줌.
}
@Getter 어노테이션 하나만 붙이면 코드를 짤 때에는 없었던 Getter 메서드가 생성되어 동작한다. 덕분에 코드는 깔끔하게 유지할 수 있고, Jackson은 생성된 Getter를 통해 JSON 객체를 만들어 낼 수 있다.
'🖥️ Dev > Backend' 카테고리의 다른 글
| [Backend][Spring Boot] 회원정보 데이터베이스를 API로 만들어보자! (1) | 2026.01.27 |
|---|---|
| [Backend][Spring Boot] JPA(Java Persistence API)와 회원정보 데이터베이스 (0) | 2026.01.27 |
since 2025.01.27. ~ 개발자를 향해....🔥