public class HexColorGenerator {
public static String generateRandomHexColor() {
Random random = new Random();
호출 될 때마다 Random 인스턴스를 생성하는 코드인데 의도하신 부분일까요?
인스턴스를 미리 만들어서 사용하는 캐싱 작업은 필요한 곳에서 사용하기.
서버에서 색상에 대한 유효성 검증(hex인지 여부 확인)을 해야하는 걸까요?
프론트에서도 색상을 표현하는 다양한 방식이 있을 것입니다. hex 뿐만아니라, 디자인 시스템을 적용한다고 하면 디자인 정보를 포함한 '디자인 토큰'을 사용할 수도 있죠. 그런 UI 변경사항에 서버가 의존성을 가지고 있을 필요가 있는지, 의존성을 가지게 된다면 왜 그 의존성이 필요한지에 대해서 생각해보시면 좋을 것 같습니다.
사실 이 부분은 우리팀도 프로젝트를 하면서 계속 고민했던 부분이다. 처음에 요구사항은 html 색상코드를 사용하라는 것이었다.
이 값이 제대로 들어왔는지 서버에서도 유효성 검사를 해야할까?
백엔드에서는 유효성 검사는 꼼꼼하게 하는 게 좋지 않을까? 라는 의견이었고, 프론트에서는 프론트에서 html 코드에 맞춰서 색상을 보내기 때문에 서버에서까지 유효성 검사를 하지 않아도 될 것 같다는 의견이었다.
나는 휴먼에러가 발생할 수 있어서 여러 단계에 걸쳐서 유효성 검사를 하는 게 좋다고 생각했지만 나중에는 생각을 달리하게 됐다.
그 이유는 이렇다.
1)색상은 그렇게까지 중요한 도메인이 아니다.
라벨 색상은 여러 단계에 걸쳐서 꼼꼼하게 유효성 검사를 해야할 정도로 중요한 도메인이 아니다. 여러 단계에 걸쳐서 에러가 발생하지 않게 할 필요는 없다고 생각한다.
2)그렇기 때문에, DB 통신을 할 정도로 리소스를 사용할 이유는 없다.
유효성 검사를 하려면 유효한 html 코드들을 db에 넣어놓고, 폼에 들어온 색상 코드가 올바른 입력값인지 db의 값과 대조해봐야 한다.
FE 마스터인 크롱이 DB 통신은 최소화하는 게 좋다는 이야기를 해주셨는데, 이 말을 DB 통신이 필요한 곳에서만 이루어져야 한다는 조언으로 이해했다. 불필요한 리소스 사용을 막기 위해서 색상에 대한 유효성 검증은 프론트에 맡기기로 했다.
맨 처음에 소개한 피드백도 좋은 조언이라고 생각한다. 프론트에서 폼은 계속 바뀔 수 있기 때문에, 유효성 검사 역시 프론트의 폼에 의존하게 된다. 유지 보수 측면에서 어려움이 하나 추가되는 것이다.
이건 라벨의 유효성 검증을 어떻게 해야 할지를 팀에서 정하는 게 맞는 문제같다!
예외가 발생했을 때 발생했는지도 모른채 조용히 핸들링(정상 작동하도록)을 하게되면
왜 그 에러가 발생했는지 어느정도의 빈도로 발생하고 있는지 알기 어렵습니다
그래서 개인적으로는 예외가 발생했을 때, 에러를 아예 던져버리거나 간단하게라도 예외가 왜 발생했는지에 대해 로깅을 달아두는 편입니다. 예외가 발생했다는 사실에 대한 정보는 서비스의 결함을 발견해낼 수 있는 중요한 단서라고 생각합니다.
예전에 BE 마스터인 호눅스에게 예외처리 된 부분도 로그로 남겨두는 게 좋냐고 물어봤던 적이 있다. 호눅스는 "어떤 예외가 많이 발생하는지를 알려면 남겨두는 것이 좋다"라고 답했었다. 지금까지 코드 구현에 바빠서 로그처리를 하지 않았는데 앞으로는 꼭 하도록 하자.
의도하신 부분이 '저장을 시도한 멤버와 실제로 데이터베이스에 저장된 멤버가 동일한지'를 검증하기 위해 전체 필드를 대상으로 equals 메소드를 재정의 해주셨는데, 이렇게 되면 데이터베이스와 어플리케이션 단에서 동일한 데이터를 식별하는데 아래와 같이 다른 기준을 가지게될 수 있습니다
데이터베이스에서의 회원 데이터 식별자 -> id
어플리케이션에서의 회원 데이터 식별자 -> id, password, nickname, email
그래서 저는 보통 equals 를 재정의할 때 id 값만 재정의하여 사용하는 편입니다
이 피드백은 애플리케이션에서 중복된 회원을 걸러내는 방식에 대한 것이었다. 엔티티의 모든 필드값을 hashandequals로 재정의한 것에 대한 피드백이었는데,
db에서 회원 식별자가 id인 것과 어플리케이션에서 회원 식별자가 여러개로 다른 것을 주의하라는 말이었다.
생각해보면, id만으로도 충분히 중복을 걸러낼 수 있을 거 같다. db에 unique 특성이 걸려있을 테니. 그렇다면, 동일한 회원인지 여부도 id만으로 체크가 가능할 거 같다.
다만, db와 애플리케이션단에서 동일성 체크 로직이 다를 때 어떤 문제가 발생할 수 있을지에 대해선 감이 잘 안 잡힌다.
유저가 탈퇴했을 때
탈퇴한 유저 정보를 그대로 남겨야하는 상황에서 동일한 아이디로 다른 유저가 회원가입을 시도 했을 때
소프트 딜리트를 구현하려고 할 때 생기는 문제점 중 하나다.
아이디에 unique 특성을 제거하거나(근데 이렇게 하면 중복 체크가 어려워진다) 다중 컬럼 unqiue를 쓸 수 있는 것 같다.
방법은
loginId와 deleted_at이라는 컬럼을 다중 unqiue로 만드는 것이다.
만약, 처음에 dusgh123 이라는 id로 만들고 삭제했으면 dusgh123과 삭제한 날짜가 db에 저장된다.
그 다음에 다른 사람이 dusgh123으로 가입을 하면 deleted_at이 null이 되니까 처음 만들고 삭제한 계정과는 중복되지 않는다.
@SQLDelete(sql = "UPDATE User SET is_Deleted = true, deletedAt = CURRENT_TIMESTAMP WHERE id = ?")
@Table(
name="user",
uniqueConstraints={
@UniqueConstraint(
name= "user",
columnNames={"loginId", "deletedAt"}
)
}
)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private Long id;
private String loginId;
private String name;
private String password;
private String address;
private LocalDate birthdate;
@Enumerated(EnumType.STRING)
private Role role = USER;
private boolean isDeleted;
private LocalDate deletedAt;
우선 soft_delete 방식을 구현하고, loginId와 deletedAt에 복합 유니크 키 설정을 했다.
이렇게 soft_delete가 된 상태에서 다시 저 아이디로 가입을 해보자.


정상 가입됐다.

둘다 정상 삭제도 됐다.
다만, user를 soft_delete할 때 이 방식이 무조건 정답이라고 할 수는 없는 거 같다.
비전공자 오픈채팅방에서 사람들의 의견을 구하니
login_id를 그냥 아예 unqiue로 걸어두고 이미 탈퇴한 회원이더라도
다른 사람이 그 아이디로 가입하지 못하게 막는 것이 좋다는 말을 들었다.
처음 가입했던 회원과 새로운 회원의 자료를 어떻게 구분할 것이냐?
라는 질문을 들었다. 다만, 이건 pk를 auto_increment한 id로 따로 만들어놓고
이걸 기반으로 정보를 찾으면 될 거 같긴 하다.
이러한 이유 때문에 처음부터 login_id를 pk로 잡지 않고 db에서 만들어주는 unique한 id를 pk로 잡았기 때문이다.
만약에 게시판 서비스를 만들었고
회원의 login_id를 기준으로 검색을 한다고 할 때(사실 login_id보다는 닉네임으로 검색을 많이 할 거 같지만)
이거에 대해서는 쿼리가 좀 복잡하게 나갈 수는 있을 거 같다.
이건 이유가 있는데요. 예를 들면, email 로 PK 를 하고 있는 테이블이 있다고 가정해봅시다. 갑자기 잘 운영하다가 10년 뒤에 정부에서 email 수집을 금지했다고 해보죠. 그렇게 되면 RDB 테이블의 PK 를 어떻게 바꿀까요? 엄청 힘들겠죠? 심지어 운영중인 서버의 PK 를 바꿔야 하니, 사실 이 문제가 예전에 주민등록증을 PK 로 하던 회사들이 문제를 많이 겪었어서, 이제는 autogenerated_key 같은 형태를 쓰는게 거의 국룰이라고 보시면 됩니다.
외부에 요인을 받지 않고 unique 하게 사용할 수 있는 키 이기 때문이죠.
다른 팀 리뷰에서 이런 내용을 봤는데, 이것도 중요한 내용인 거 같다.