βπ[Backend Development] CommentPath ν΄λμ€ λΆμ λ° μ€λͺ β
π CommentPath ν΄λμ€ λΆμ λ° μ€λͺ .
- CommentPath ν΄λμ€λ κ³μΈ΅ν λκΈ μμ€ν μμ κ° λκΈμ κ²½λ‘(path)λ₯Ό κ΄λ¦¬νλ μν μ ν©λλ€.
- κ° λκΈμ pathλΌλ λ¬Έμμ΄λ‘ ννλλ©°, pathλ μΌμ ν κ·μΉμ λ°λΌ λκΈμ λΆλͺ¨-μμ κ΄κ³λ₯Ό λνλ λλ€.
- μ΄ ν΄λμ€λ λκΈμ κΉμ΄(depth), λΆλͺ¨ λκΈ(parentPath), μλ‘μ΄ μμ λκΈ(createChildCommentPath) λ±μ κ΄λ¦¬νλ κΈ°λ₯μ μ 곡ν©λλ€.
β 1οΈβ£ ν΄λμ€ μ λ°μ μΈ κ°μ.
π ν΅μ¬ κ°λ
1οΈβ£ path νλ
- pathλ λκΈμ κ³μΈ΅ ꡬ쑰λ₯Ό νννλ λ¬Έμμ΄μ λλ€.
- κ° λκΈμ 5μ리μ©(DEPHT_CHUNK_SIZE = 5)μ λ¬Έμμ΄μ κ°μ§λ©°, λκΈμ΄ κΉμ΄μ§μλ‘ pathκ° κΈΈμ΄μ§λλ€.
π μμ:
λ£¨νΈ λκΈ: "00000"
첫 λ²μ§Έ μμ λκΈ: "0000000000"
λ λ²μ§Έ μμ λκΈ: "000000000000000"
- μ΄λ₯Ό ν΅ν΄ λκΈμ΄ μ΄λ κ³μΈ΅μ μνλμ§, λΆλͺ¨κ° λꡬμΈμ§, μμμ΄ μ΄λ»κ² λ°°μΉλ μ§λ₯Ό κ²°μ ν μ μμ΅λλ€.
2οΈβ£ CHARSET (λ¬Έμ μ§ν©)
- 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz (μ΄ 62κ° λ¬Έμ)
- pathμ κ° 5μ리(chunk)λ μ΄ λ¬Έμ μ§ν©μ μ¬μ©ν΄ ννλ©λλ€.
- μλ‘μ΄ λκΈμ΄ μΆκ°λ λ, pathλ λ¬Έμ μ§ν© λ΄μμ μ¦κ°(increase)νλ λ°©μμΌλ‘ μμ±λ©λλ€.
β 2οΈβ£ μ£Όμ νλ
private static final String CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
private static final int DEPTH_CHUNK_SIZE = 5; // κ° depthκ° 5μλ¦¬λ‘ ννλ¨
private static final int MAX_DEPTH = 5; // μ΅λ depth 5κΉμ§ νμ©
private static final String MIN_CHUNK = String.valueOf(CHARSET.charAt(0)).repeat(DEPTH_CHUNK_SIZE);
private static final String MAX_CHUNK = String.valueOf(CHARSET.charAt(CHARSET.length() - 1)).repeat(DEPTH_CHUNK_SIZE);
- MIN_CHUNK = β00000β : μ΅μ chunk κ°
- MAX_CHUNK = βzzzzzβ : μ΅λ chunk κ° (μ¦, λ μ΄μ μ¦κ° λΆκ°λ₯ν κ°)
- λκΈμ pathλ MIN_CHUNKλΆν° μμν΄ μ μ§μ μΌλ‘ μ¦κ°νλ λ°©μμ λλ€.
β 3οΈβ£ μ£Όμ λ©μλ λΆμ
- κ° λ©μλμ μν , μ¬μ© μκΈ°, λμ λ°©μμ μ€λͺ νκ² μ΅λλ€.
1οΈβ£ create(String path)
public static CommentPath create(String path) {
if (isDepthOverflowed(path)) {
throw new IllegalStateException("depth overflowed");
}
CommentPath commentPath = new CommentPath();
commentPath.path = path;
return commentPath;
}
- β
μν :
- μ£Όμ΄μ§ pathλ‘ CommentPath κ°μ²΄λ₯Ό μμ±νλ€.
- pathμ κΉμ΄κ° MAX_DEPTHλ₯Ό μ΄κ³Όνλ©΄ μμΈ λ°μ.
- β
μ¬μ© μκΈ°:
- λκΈμ DBμ μ μ₯ν λ, CommentPathλ₯Ό μμ±ν λ μ¬μ©.
- β
λμ λ°©μ:
-
- isDepthOverflowed(path)λ₯Ό νΈμΆνμ¬ μ΅λ κΉμ΄λ₯Ό μ΄κ³Όνλμ§ νμΈνλ€.
-
- λ¬Έμ κ° μμΌλ©΄ CommentPath κ°μ²΄λ₯Ό μμ±νμ¬ λ°ννλ€.
-
2οΈβ£ calculateDepth(String path)
private static int calculateDepth(String path) {
return path.length() / DEPTH_CHUNK_SIZE;
}
- β
μν :
- νμ¬ pathμ κΉμ΄λ₯Ό κ³μ°νλ€.
- path.length()λ₯Ό DEPTH_CHUNK_SIZEλ‘ λλλ©΄ κΉμ΄κ° λλ€.
- β
μ¬μ© μκΈ°:
- λκΈμ΄ λͺ λ²μ§Έ κΉμ΄μΈμ§ νμΈ ν λ.
- isRoot(), isDepthOverflowed() λ±μ λ©μλμμ μ¬μ©.
- β
λμ λ°©μ:
- path.length()λ₯Ό 5λ‘ λλλ€.
- μ: β0000000000β (10κΈμ) β calculateDepth(β0000000000β) β 10 / 5 = 2
3οΈβ£ getDepth()
public int getDepth() {
return calculateDepth(path);
}
- β
μν :
- νμ¬ λκΈμ κΉμ΄λ₯Ό λ°ννλ€.
- β
μ¬μ© μκΈ°:
- λκΈμ κΉμ΄λ₯Ό νμΈν λ.
- β
λμ λ°©μ:
- calculateDepth(path)λ₯Ό νΈμΆνμ¬ κΉμ΄λ₯Ό ꡬνλ€.
4οΈβ£ isRoot()
public boolean isRoot() {
return calculateDepth(path) == 1;
}
- β
μν :
- νμ¬ λκΈμ΄ λ£¨νΈ λκΈμΈμ§ νμΈνλ€.
- β
μ¬μ© μκΈ°:
- λΆλͺ¨ λκΈμ΄ μλ λ£¨νΈ λκΈμΈμ§ νμΈν λ.
- β
λμ λ°©μ:
- κΉμ΄κ° 1μ΄λ©΄ λ£¨νΈ λκΈλ‘ νλ¨.
5οΈβ£ getParentPath()
public String getParentPath() {
return path.substring(0, path.length() - DEPTH_CHUNK_SIZE);
}
- β
μν :
- λΆλͺ¨ λκΈμ pathλ₯Ό λ°ννλ€.
- β
μ¬μ© μκΈ°:
- λκΈμ λΆλͺ¨λ₯Ό μ°Ύμ λ.
- β
λμ λ°©μ:
- νμ¬ pathμμ λ§μ§λ§ 5μ리λ₯Ό μλΌλ΄μ΄ λ°ννλ€.
6οΈβ£ createChildCommentPath(String descendantsTopPath)
public CommentPath createChildCommentPath(String descendantsTopPath) {
if (descendantsTopPath == null) {
return CommentPath.creat(path + MIN_CHUNK);
}
String childrenTopPath = findChildrenTopPath(descendantsTopPath);
return CommentPath.create(increase(childrenTopPath));
}
- β
μν :
- νμ¬ λκΈμ μμ λκΈμ pathλ₯Ό μμ±νλ€.
- β
μ¬μ© μκΈ°:
- μλ‘μ΄ λλκΈμ μΆκ°ν λ.
- β
λμ λ°©μ:
-
- descendantsTopPathκ° nullμ΄λ©΄ MIN_CHUNKλ₯Ό λΆμ¬μ μμ λκΈμ μμ±.
-
- μμ λκΈμ pathλ₯Ό κ°μ Έμ¨ ν increase()λ₯Ό νΈμΆνμ¬ μ¦κ°.
-
7οΈβ£ findChildrenTopPath(String descendantsTopPath)
private String findChildrenTopPath(String descendantsTopPath) {
return descendantsTopPath.substring(0, (getDepth() + 1) * DEPTH_CHUNK_SIZE);
}
- β
μν :
- μμ λκΈ μ€ κ°μ₯ μμ λκΈμ pathλ₯Ό λ°ννλ€.
- β
μ¬μ© μκΈ°:
- μλ‘μ΄ λκΈμ μΆκ°ν λ, μ΄λ€ λκΈμ΄ νμ¬ λκΈμ κ°μ₯ μ΅κ·Ό μμ λκΈμΈμ§ μ°Ύμ λ.
- β
λμ λ°©μ:
- νμ¬ κΉμ΄λ³΄λ€ ν λ¨κ³ λ κΉμ path λΆλΆμ μλΌμ λ°ν.
8οΈβ£ increase(String path)
private String increase(String path) {
String lastChunk = path.substring(path.length() - DEPTH_CHUNK_SIZE);
if (isChunkOverflowed(lastChunk)) {
throw new IllegalStateException("chunk overflowed");
}
int charsetLength = CHARSET.length();
int value = 0;
for (char character : lastChunk.toCharArray()) {
value = value * charsetLength + CHARSET.indexOf(character);
}
value = value + 1;
String result = "";
for (int i = 0; i < DEPTH_CHUNK_SIZE; i++) {
result = CHARSET.charAt(value % charsetLength) + result;
value /= charsetLength;
}
return path.substring(0, path.length() - DEPTH_CHUNK_SIZE) + result;
}
- β
μν :
- λκΈ pathλ₯Ό μ¦κ°μμΌ μλ‘μ΄ μμ λκΈ μμ±
- β
μ¬μ© μκΈ°:
- μλ‘μ΄ λλκΈμ μΆκ°ν λ
π λμ λ°©μ:
π μ λ ₯(path)
- μλ‘μ΄ λλκΈμ μΆκ°ν λ
- pathλ λκΈμ κ³μΈ΅ ꡬ쑰λ₯Ό λνλ΄λ λ¬Έμμ΄.
- μλ₯Ό λ€μ΄ β0000000000β(2λ²μ§Έ κΉμ΄μ λκΈ)μ΄λΌλ μ£Όμ΄μ‘λ€κ³ κ°μ .
π 1λ¨κ³: λ§μ§λ§ 5μ리(Chunk) μΆμΆ
String lastChunk = path.substring(path.length() - DEPTH_CHUNK_SIZE);
- pathμμ λ§μ§λ§ DEPTH_CHUNK_SIZE(=5)λ§νΌμ λ¬Έμμ΄μ μλΌλΈλ€.
- μμ :
path = "0000000000";
lastChunk = path.substring(5); // "00000"
π 2λ¨κ³: lastChunk κ°μ΄ μ΅λκ°μΈμ§ νμΈ
if (isChunkOverflowed(lastChunk)) {
throw new IllegalStateException("chunk overflowed");
}
- isChunkOverflowed(lastChunk) λ©μλλ₯Ό νΈμΆνμ¬ lastChunkκ° βzzzzzβ(μ΅λκ°)μΈμ§ νμΈ.
- λ§μ½ βzzzzzβλΌλ©΄ λ μ΄μ μ¦κ°ν μ μμΌλ―λ‘ μμΈλ₯Ό λμ§λ€.
π 3λ¨κ³: lastChunk κ°μ 10μ§μλ‘ λ³ν
int charsetLength = CHARSET.length();
int value = 0;
for (char character : lastChunk.toCharArray()) {
value = value * charsetLength + CHARSET.indexOf(character);
}
- CHARSETμ 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz (μ΄ 62κ° λ¬Έμ).
- lastChunk(νμ¬ 5μ리 λ¬Έμμ΄)λ₯Ό 62μ§μμμ 10μ§μλ‘ λ³ννλ€.
π μμ 1: β00000β λ³ν
- CHARSET.index(β0β) = 0
- λ³ν κ³Όμ :
value = (0 * 62) + 0 = 0 value = (0 * 62) + 0 = 0 value = (0 * 62) + 0 = 0 value = (0 * 62) + 0 = 0 value = (0 * 62) + 0 = 0
π μμ 2: β0000zβ λ³ν
- βzβμ μΈλ±μ€λ 61
value = (0 * 62) + 0 = 0 value = (0 * 62) + 0 = 0 value = (0 * 62) + 0 = 0 value = (0 * 62) + 0 = 0 value = (0 * 62) + 61 = 61
π 4λ¨κ³: κ° μ¦κ° (+ 1 μ°μ°)
value = value + 1;
- 10μ§μμ κ°μ΄ 1μ¦κ°νλ€.
π μμ 1: β00000β β β00001β
value = 0 + 1 = 1
π μμ 2: β0000zβ β β00010β
value = 61 + 1 = 62
π 5λ¨κ³: λ€μ 62μ§μ λ¬Έμμ΄λ‘ λ³ν
String result = "";
for (int i = 0; i < DEPTH_CHUNK_SIZE; i++) {
result = CHARSET.charAt(value % charsetLength) + result;
value /= charsetLength;
}
- μ¦κ°λ 10μ§μ κ°μ λ€μ 62μ§μ λ¬Έμμ΄λ‘ λ³ννλ€.
π μμ 1: value = 1
- value % 62 = 1 β β1β
- value /= 62 = -
- κ²°κ³Ό: β00001β
π μμ 2: value = 62
- value % 62 = 0 β β0β
- value /= 62 = 1
- value % 62 = 1 β β1β
- μ΅μ’ κ²°κ³Ό: β00010β
π 6λ¨κ³: κΈ°μ‘΄ pathμμ λ§μ§λ§ chunkλ₯Ό μλ‘μ΄ κ°μΌλ‘ κ΅μ²΄
return path.substring(0, path.length() - DEPTH_CHUNK_SIZE) + result;
- μλ pathμ λ§μ§λ§ 5μ리λ₯Ό μλ‘μ΄ κ°μΌλ‘ λ³κ²½ν λ¬Έμμ΄μ λ°ν.
π μμ
path = "0000000000";
result = "00001";
μ΅μ’
λ°νκ°: "0000000001"
π μ 체 λμ μμ
π μμ 1
increase("0000000000"); // κΈ°μ‘΄ λκΈμ path
-
- β0000000000βμμ λ§μ§λ§ 5μ리 β00000βμ μΆμΆ.
-
- β00000β β 10μ§μ λ³ν β 0
-
- 0 + 1 = 1
-
- 1 β 62μ§μ λ³ν β β00001β
-
- β0000000000β β β0000000001βλ‘ λ³ν
- β μ΅μ’ κ²°κ³Ό : β0000000001β
π μμ 2
increase("000000000z"); // κΈ°μ‘΄ λκΈμ path
-
- β000000000zβμμ λ§μ§λ§ 5μ리 β0000zβμ μΆμΆ.
-
- β0000zβ β 10μ§μ λ³ν β 61
-
- 61 + 1 = 62
-
- 62 β 62μ§μ λ³ν β β00010β
-
- β000000000zβ β β0000000010βλ‘ λ³ν
- β μ΅μ’ κ²°κ³Ό : β0000000010β