enum을 처음 보면 제일 헷갈리는 포인트가 많다.
결론부터 말하면,
- enum은 미리 만들어진 객체(인스턴스) 목록이다.
- GET과 POST는 단순한 글자가 아니라 HttpMethod 타입의 객체다.
- this == POST는 “현재 이 객체가 POST 객체냐?”를 묻는 비교다.
`enum`을 쓰는 이유: 문자열 `POST`로도 되는데 왜 굳이?
문자열은 아무 값이나 들어올 수 있고, `enum`은 정해진 값만 들어올 수 있다.
그래서 `enum`은 실수를 “런타임 버그”가 아니라 “컴파일/초기 처리 단계”에서 잡게 해준다.
1) 오타가 “조용히 통과”하는 문제를 막는다 (가장 큼)
문자열 방식:
String method = request.getMethod(); // "GET" 또는 "POST" 같은 문자열이라고 가정
if (method.equals("POST")) { ... }
여기서 `POTS` 같은 오타가 들어가면?
- 컴파일은 된다.
- 실행도 된다.
- 다만 조건이 영원히 false가 되어 로직이 이상해진다.
- 이런 버그는 찾기 어렵다.
`enum`방식:
HttpMethod method = request.getMethod(); // GET 또는 POST
if (method == HttpMethod.POST) { ... }
여기서 `HttpMethod.POTS` 같은 건 애초에 존재하지 않으니 컴파일 에러가 난다.
즉, 실수를 “아예 못 쓰게” 막는다.
2) 가능한 값의 범위를 강제로 제한한다 (불필요한 경우의 수 제거)
문자열은 사실상 무한이다.
- "GET", "POST" 말고도
- "DELETE", "ABC", "", "get" 등 뭐든 들어올 수 있다.
그러면 코드 곳곳에 이런 방어 로직이 필요해진다.
HttpMethod method = request.getMethod(); // GET 또는 POST
if (method == HttpMethod.POST) { ... }
enum은 값이 딱 정해져 있으니 이런 불확실성이 사라진다.
- HttpMethod는 GET 아니면 POST다.
- 그 외는 들어올 수 없다(들어오려면 변환 단계에서 걸러짐).
3) 비교가 안전하고 단순해진다 (==로 끝)
문자열 비교는 실수 포인트가 많다.
- ==로 비교하면 안 된다(참조 비교라서)
- .equals()를 써야 한다
- null이면 NullPointerException 터진다
반면 enum은 비교가 이렇게 끝난다.
if (method == HttpMethod.POST) { ... }
- 의도 명확
- 실수 확률 낮음
- 비용도 적음(참조 비교)
4) IDE 자동완성/리팩토링이 된다 (유지보수 체감 큼)
문자열 `POST`는 IDE 입장에서 그냥 글자다.
- 오타를 자동으로 잡아주기 어렵고
- `POST`를 다른 이름으로 바꾸는 리팩토링도 약하다
`enum`은 “타입”이니까 IDE가 강하게 도와준다.
- `HttpMethod.` 치면 `GET`, `POST` 자동완성
- 이름 바꾸면 사용처를 일괄로 안전하게 변경
프로젝트 규모 커질수록 이게 진짜 크다.
5) 확장/정책 추가가 깔끔해진다 (로직을 한 곳에 모을 수 있음)
나중에 메서드가 늘어나면 문자열은 조건식이 늘어난다.
if (method.equals("POST") || method.equals("PUT") || method.equals("PATCH")) {
...
}
enum은 이런 정책을 “값 자체”에 붙여둘 수 있다.
public enum HttpMethod {
GET, POST, PUT, DELETE, PATCH;
public boolean hasRequestBody() {
return this == POST || this == PUT || this == PATCH;
}
}
이제 사용처는 이렇게 읽힌다.
if (method.hasRequestBody()) { ... }
- 조건식이 흩어지지 않는다
- 정책 변경도 한 군데만 고치면 된다.
6) 실제로는 “변환 단계”에서 더 안전해진다 (String → enum)
현실 세계에서 요청은 결국 문자열로 들어온다. ("GET", "POST")
중요한 건 그 문자열을 초기에 enum으로 변환해서 이후 로직이 안전하게 돌아가게 만드는 것이다.
예를 들면:
public static HttpMethod from(String raw) {
return HttpMethod.valueOf(raw); // 잘못된 값이면 예외로 바로 걸림
}
이렇게 하면 "GTE" 같은 값이 들어오는 순간 초기에 터져서(=잘못된 입력)
아래 로직까지 “잘못된 상태”가 흘러가지 않는다.
일단 코드부터 보자
package http;
public enum HttpMethod {
GET,
POST;
public boolean isPost() {
return this == POST;
}
}
여기서 핵심은 `GET, POST`가 변수 선언이 아니라 "이 `enum`이 가질 수 있는 값(정확히는 인스턴스) 목록”이라는 점이다.
enum은 “값 목록”이 아니라 “객체 목록”이다
`enum HttpMethod { GET, POST }`를 선언하면 JVM은 내부적으로 이런 걸 만들어 둔다고 생각하면 된다.
- HttpMethod.GET → HttpMethod 타입 객체 1개
- HttpMethod.POST → HttpMethod 타입 객체 1개
즉, GET이랑 POST는 그냥 문자열이 아니라 이미 만들어져 있는 객체다.
그래서 이런 코드가 가능한 거다.
HttpMethod m = HttpMethod.GET; // m은 GET 객체를 가리킴
여기서 “값을 설정한다”는 말은 사실 이렇게 말하는 게 더 정확하다.
- m이라는 변수에 GET 객체의 참조(주소)를 넣는다.
그럼 POST는 “그냥 상수” 맞나?
맞다. POST는 상수다.
다만 문자열 상수가 아니라,
- HttpMethod 타입의 상수(= 미리 만들어진 객체)다.
즉,
- "POST" 는 String 값(문자열)
- HttpMethod.POST 는 HttpMethod 객체(열거형 인스턴스)
이 차이가 엄청 크다.
isPost()에서 this는 정확히 뭘 가리키나
이제 가장 중요한 부분.
public boolean isPost() {
return this == POST;
}
여기서 `this`는 이 메서드를 호출한 그 객체다.
즉, `isPost()`를 누가 호출했냐에 따라 `this`가 달라진다.
예를 들어:
HttpMethod a = HttpMethod.GET;
HttpMethod b = HttpMethod.POST;
a.isPost(); // 이때 this는 GET
b.isPost(); // 이때 this는 POST
- a.isPost() 호출 시 this는 GET
- b.isPost() 호출 시 this는 POST
그래서 내부 비교가 이렇게 된다.
- GET == POST → false
- POST == POST → true
즉 isPost()는 한 문장으로 이 뜻이다.
“지금 내(this)가 POST냐?”
request.getMethod().isPost() 흐름을 “진짜로” 한 줄씩 풀어보기
네가 제일 헷갈린 부분이 여기다.
예시 상황
HttpMethod method = request.getMethod();
여기서 `request.getMethod()`는 `HttpMethod`를 리턴한다.
그 리턴값은 둘 중 하나다.
- HttpMethod.GET
- HttpMethod.POST
이제 이 코드를 보자.
request.getMethod().isPost()
이걸 사람이 이해하기 쉽게 풀면 이렇게 된다.
- request.getMethod() 실행
→ 결과가 예를 들어 HttpMethod.POST가 나왔다고 치자 - 그 결과(= HttpMethod.POST)에 대해 .isPost() 호출
→ 결국 이거랑 똑같다.
HttpMethod.POST.isPost()
3. 그럼 isPost() 안의 this는 누구냐?
→ “호출 주체”가 HttpMethod.POST니까 this는 POST다.
4. return 문 실행
return this == POST; // this가 POST니까 true
끝.
그래서
- HttpMethod.POST == request.getMethod()
- request.getMethod().isPost()
이 둘은 결국 같은 비교를 다른 문장으로 쓴 것이다.
그럼 왜 굳이 isPost()를 만들었나
기능적으로는 이 두 개가 완전히 같다.
if (request.getMethod() == HttpMethod.POST) { ... }
if (request.getMethod().isPost()) { ... }
차이는 “기술”이 아니라 “표현”이다.
isPost()가 주는 장점
의도가 바로 읽힌다
`== HttpMethod.POST`는 “비교”라는 구현이 보이고,
`.isPost()`는 “질문”처럼 읽힌다.
- `method == POST` → “POST랑 같냐?” (구현 중심)
- `method.isPost()` → “POST냐?” (의도 중심)
반복을 줄인다
코드 곳곳에 `== HttpMethod.POST`가 흩어지면 지저분해진다.
한 번 감싸두면 통일된다.
확장에 유리하다
나중에 `isGet()`, `isWriteMethod()` 같은 식으로 늘리기 쉽다.
예:
public boolean isReadMethod() {
return this == GET;
}
또는
public boolean hasRequestBody() {
return this == POST; // 단순 예시
}
(실제로는 PUT, PATCH도 바디를 가질 수 있으니 확장 가능)
'Java' 카테고리의 다른 글
| 왜 new Integer()를 사용하면 안 될까? (0) | 2026.02.13 |
|---|---|
| static (0) | 2026.02.05 |
| 쓰레드란? (0) | 2026.01.29 |